001    /*
002     * $Id: GCDFactory.java 3676 2011-07-02 10:51:16Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import org.apache.log4j.Logger;
009    
010    import edu.jas.arith.BigInteger;
011    import edu.jas.arith.BigRational;
012    import edu.jas.arith.ModInteger;
013    import edu.jas.arith.ModIntegerRing;
014    import edu.jas.arith.ModLong;
015    import edu.jas.arith.ModLongRing;
016    import edu.jas.kern.ComputerThreads;
017    import edu.jas.structure.GcdRingElem;
018    import edu.jas.structure.RingFactory;
019    
020    
021    /**
022     * Greatest common divisor algorithms factory. Select appropriate GCD engine
023     * based on the coefficient types.
024     * @todo Base decision also an degree vectors and number of variables of
025     *       polynomials. Incorporate also number of CPUs / threads available (done
026     *       with GCDProxy).
027     * @author Heinz Kredel
028     * @usage To create objects that implement the
029     *        <code>GreatestCommonDivisor</code> interface use the
030     *        <code>GCDFactory</code>. It will select an appropriate implementation
031     *        based on the types of polynomial coefficients C. There are two methods
032     *        to obtain an implementation: <code>getProxy()</code> and
033     *        <code>getImplementation()</code>. <code>getImplementation()</code>
034     *        returns an object of a class which implements the
035     *        <code>GreatestCommonDivisor</code> interface. <code>getProxy()</code>
036     *        returns a proxy object of a class which implements the
037     *        <code>GreatestCommonDivisor</code>r interface. The proxy will run two
038     *        implementations in parallel, return the first computed result and
039     *        cancel the second running task. On systems with one CPU the computing
040     *        time will be two times the time of the fastest algorithm
041     *        implmentation. On systems with more than two CPUs the computing time
042     *        will be the time of the fastest algorithm implmentation.
043     * 
044     *        <pre>
045     * GreatestCommonDivisor&lt;CT&gt; engine;
046     * engine = GCDFactory.&lt;CT&gt; getImplementation(cofac);
047     * or engine = GCDFactory.&lt;CT&gt; getProxy(cofac);
048     * c = engine.gcd(a, b);
049     * </pre>
050     * 
051     *        For example, if the coefficient type is BigInteger, the usage looks
052     *        like
053     * 
054     *        <pre>
055     * BigInteger cofac = new BigInteger();
056     * GreatestCommonDivisor&lt;BigInteger&gt; engine;
057     * engine = GCDFactory.getImplementation(cofac);
058     * or engine = GCDFactory.getProxy(cofac);
059     * c = engine.gcd(a, b);
060     * </pre>
061     * 
062     * @see edu.jas.ufd.GreatestCommonDivisor#gcd(edu.jas.poly.GenPolynomial P,
063     *      edu.jas.poly.GenPolynomial S)
064     */
065    
066    public class GCDFactory {
067    
068    
069        private static final Logger logger = Logger.getLogger(GCDFactory.class);
070    
071    
072        /**
073         * Protected factory constructor.
074         */
075        protected GCDFactory() {
076        }
077    
078    
079        /**
080         * Determine suitable implementation of gcd algorithms, case ModLong.
081         * @param fac ModLongRing.
082         * @return gcd algorithm implementation.
083         */
084        public static GreatestCommonDivisorAbstract<ModLong> getImplementation(ModLongRing fac) {
085            GreatestCommonDivisorAbstract<ModLong> ufd;
086            if (fac.isField()) {
087                ufd = new GreatestCommonDivisorModEval<ModLong>();
088                return ufd;
089            }
090            ufd = new GreatestCommonDivisorSubres<ModLong>();
091            return ufd;
092        }
093    
094    
095        /**
096         * Determine suitable proxy for gcd algorithms, case ModLong.
097         * @param fac ModLongRing.
098         * @return gcd algorithm implementation.
099         */
100        public static GreatestCommonDivisorAbstract<ModLong> getProxy(ModLongRing fac) {
101            GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2;
102            ufd1 = new GreatestCommonDivisorSubres<ModLong>();
103            if (fac.isField()) {
104                ufd2 = new GreatestCommonDivisorModEval<ModLong>();
105            } else {
106                ufd2 = new GreatestCommonDivisorSimple<ModLong>();
107            }
108            return new GCDProxy<ModLong>(ufd1, ufd2);
109        }
110    
111    
112        /**
113         * Determine suitable implementation of gcd algorithms, case ModInteger.
114         * @param fac ModIntegerRing.
115         * @return gcd algorithm implementation.
116         */
117        public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
118            GreatestCommonDivisorAbstract<ModInteger> ufd;
119            if (fac.isField()) {
120                ufd = new GreatestCommonDivisorModEval<ModInteger>();
121                return ufd;
122            }
123            ufd = new GreatestCommonDivisorSubres<ModInteger>();
124            return ufd;
125        }
126    
127    
128        /**
129         * Determine suitable proxy for gcd algorithms, case ModInteger.
130         * @param fac ModIntegerRing.
131         * @return gcd algorithm implementation.
132         */
133        public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) {
134            GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2;
135            ufd1 = new GreatestCommonDivisorSubres<ModInteger>();
136            if (fac.isField()) {
137                ufd2 = new GreatestCommonDivisorModEval<ModInteger>();
138            } else {
139                ufd2 = new GreatestCommonDivisorSimple<ModInteger>();
140            }
141            return new GCDProxy<ModInteger>(ufd1, ufd2);
142        }
143    
144    
145        /**
146         * Determine suitable implementation of gcd algorithms, case BigInteger.
147         * @param fac BigInteger.
148         * @return gcd algorithm implementation.
149         */
150        public static GreatestCommonDivisorAbstract<BigInteger> getImplementation(BigInteger fac) {
151            GreatestCommonDivisorAbstract<BigInteger> ufd;
152            if (true) {
153                ufd = new GreatestCommonDivisorModular<ModLong>(); // dummy type
154            } else {
155                ufd = new GreatestCommonDivisorSubres<BigInteger>();
156            }
157            return ufd;
158        }
159    
160    
161        /**
162         * Determine suitable procy for gcd algorithms, case BigInteger.
163         * @param fac BigInteger.
164         * @return gcd algorithm implementation.
165         */
166        public static GreatestCommonDivisorAbstract<BigInteger> getProxy(BigInteger fac) {
167            GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2;
168            ufd1 = new GreatestCommonDivisorSubres<BigInteger>();
169            ufd2 = new GreatestCommonDivisorModular<ModLong>(); // dummy type
170            return new GCDProxy<BigInteger>(ufd1, ufd2);
171        }
172    
173    
174        /**
175         * Determine suitable implementation of gcd algorithms, case BigRational.
176         * @param fac BigRational.
177         * @return gcd algorithm implementation.
178         */
179        public static GreatestCommonDivisorAbstract<BigRational> getImplementation(BigRational fac) {
180            GreatestCommonDivisorAbstract<BigRational> ufd;
181            ufd = new GreatestCommonDivisorPrimitive<BigRational>();
182            return ufd;
183        }
184    
185    
186        /**
187         * Determine suitable proxy for gcd algorithms, case BigRational.
188         * @param fac BigRational.
189         * @return gcd algorithm implementation.
190         */
191        public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) {
192            GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2;
193            ufd1 = new GreatestCommonDivisorSubres<BigRational>();
194            ufd2 = new GreatestCommonDivisorSimple<BigRational>();
195            return new GCDProxy<BigRational>(ufd1, ufd2);
196        }
197    
198    
199        /**
200         * Determine suitable implementation of gcd algorithms, other cases.
201         * @param fac RingFactory&lt;C&gt;.
202         * @return gcd algorithm implementation.
203         */
204        @SuppressWarnings("unchecked")
205        public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation(
206                        RingFactory<C> fac) {
207            GreatestCommonDivisorAbstract/*raw type<C>*/ufd;
208            logger.debug("fac = " + fac.getClass().getName());
209            int t = 0;
210            Object ofac = fac;
211            if (ofac instanceof BigInteger) {
212                t = 1;
213            }
214            if (ofac instanceof ModIntegerRing) {
215                t = 2;
216            }
217            if (ofac instanceof BigRational) {
218                t = 3;
219            }
220            if (ofac instanceof ModLongRing) {
221                t = 4;
222            }
223            //System.out.println("gt = " + t);
224            if (t == 1) {
225                ufd = new GreatestCommonDivisorModular/*<BigInteger>*/();
226                //ufd = new GreatestCommonDivisorSubres<BigInteger>();
227                //ufd = new GreatestCommonDivisorModular/*<BigInteger>*/(true);
228            } else if (t == 2) {
229                ufd = new GreatestCommonDivisorModEval<ModInteger>();
230            } else if (t == 3) {
231                ufd = new GreatestCommonDivisorSubres<C>();
232            } else if (t == 4) {
233                ufd = new GreatestCommonDivisorModEval<ModLong>();
234            } else {
235                if (fac.isField()) {
236                    ufd = new GreatestCommonDivisorSimple<C>();
237                } else {
238                    ufd = new GreatestCommonDivisorSubres<C>();
239                }
240            }
241            logger.debug("implementation = " + ufd);
242            return ufd;
243        }
244    
245    
246        /**
247         * Determine suitable proxy for gcd algorithms, other cases.
248         * @param fac RingFactory&lt;C&gt;.
249         * @return gcd algorithm implementation. <b>Note:</b> This method contains a
250         *         hack for Google app engine to not use threads.
251         * @see edu.jas.kern.ComputerThreads#NO_THREADS
252         */
253        @SuppressWarnings("unchecked")
254        public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) {
255            if (ComputerThreads.NO_THREADS) { // hack for Google app engine
256                return GCDFactory.<C> getImplementation(fac);
257            }
258            GreatestCommonDivisorAbstract/*raw type<C>*/ufd;
259            logger.debug("fac = " + fac.getClass().getName());
260            int t = 0;
261            Object ofac = fac;
262            if (ofac instanceof BigInteger) {
263                t = 1;
264            }
265            if (ofac instanceof ModIntegerRing) {
266                t = 2;
267            }
268            if (ofac instanceof BigRational) {
269                t = 3;
270            }
271            if (ofac instanceof ModLongRing) {
272                t = 4;
273            }
274            //System.out.println("t     = " + t);
275            if (t == 1) {
276                ufd = new GCDProxy<BigInteger>(new GreatestCommonDivisorSubres<BigInteger>(),
277                                new GreatestCommonDivisorModular/*<BigInteger>*/());
278                //    new GreatestCommonDivisorModular/*<BigInteger>*/(true) );
279            } else if (t == 2) {
280                ufd = new GCDProxy<ModInteger>(new GreatestCommonDivisorSubres<ModInteger>(),
281                                new GreatestCommonDivisorModEval<ModInteger>());
282            } else if (t == 3) {
283                ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(), new GreatestCommonDivisorSimple<C>());
284            } else if (t == 4) {
285                ufd = new GCDProxy<ModLong>(new GreatestCommonDivisorSubres<ModLong>(),
286                                new GreatestCommonDivisorModEval<ModLong>());
287            } else {
288                if (fac.isField()) {
289                    ufd = new GCDProxy<C>(new GreatestCommonDivisorSimple<C>(),
290                                    new GreatestCommonDivisorSubres<C>());
291                } else {
292                    ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(),
293                                    new GreatestCommonDivisorPrimitive<C>());
294                }
295            }
296            logger.debug("ufd = " + ufd);
297            return ufd;
298        }
299    
300    }