001/*
002 * $Id: GCDFactory.java 3852 2011-12-31 20:03:57Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import org.apache.log4j.Logger;
009
010import edu.jas.arith.BigInteger;
011import edu.jas.arith.BigRational;
012import edu.jas.arith.ModInteger;
013import edu.jas.arith.ModIntegerRing;
014import edu.jas.arith.ModLong;
015import edu.jas.arith.ModLongRing;
016import edu.jas.kern.ComputerThreads;
017import edu.jas.structure.GcdRingElem;
018import 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
066public 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        Object ofac = fac;
210        if (ofac instanceof BigInteger) {
211            ufd = new GreatestCommonDivisorModular<ModInteger>();
212            //ufd = new GreatestCommonDivisorSubres<BigInteger>();
213            //ufd = new GreatestCommonDivisorModular<ModInteger>(true);
214        } else if (ofac instanceof ModIntegerRing) {
215            ufd = new GreatestCommonDivisorModEval<ModInteger>();
216        } else if (ofac instanceof ModLongRing) {
217            ufd = new GreatestCommonDivisorModEval<ModLong>();
218        } else if (ofac instanceof BigRational) {
219            ufd = new GreatestCommonDivisorSubres<BigRational>();
220        } else {
221            if (fac.isField()) {
222                ufd = new GreatestCommonDivisorSimple<C>();
223            } else {
224                ufd = new GreatestCommonDivisorSubres<C>();
225            }
226        }
227        logger.debug("implementation = " + ufd);
228        return ufd;
229    }
230
231
232    /**
233     * Determine suitable proxy for gcd algorithms, other cases.
234     * @param fac RingFactory&lt;C&gt;.
235     * @return gcd algorithm implementation. <b>Note:</b> This method contains a
236     *         hack for Google app engine to not use threads.
237     * @see edu.jas.kern.ComputerThreads#NO_THREADS
238     */
239    @SuppressWarnings("unchecked")
240    public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) {
241        if (ComputerThreads.NO_THREADS) { // hack for Google app engine
242            return GCDFactory.<C> getImplementation(fac);
243        }
244        GreatestCommonDivisorAbstract/*raw type<C>*/ufd;
245        logger.debug("fac = " + fac.getClass().getName());
246        Object ofac = fac;
247        if (ofac instanceof BigInteger) {
248            ufd = new GCDProxy<BigInteger>(new GreatestCommonDivisorSubres<BigInteger>(),
249                                           new GreatestCommonDivisorModular<ModInteger>());
250        } else if (ofac instanceof ModIntegerRing) {
251            ufd = new GCDProxy<ModInteger>(new GreatestCommonDivisorSimple<ModInteger>(),  // Subres
252                                           new GreatestCommonDivisorModEval<ModInteger>());
253        } else if (ofac instanceof ModLongRing) {
254            ufd = new GCDProxy<ModLong>(new GreatestCommonDivisorSimple<ModLong>(), // Subres
255                                        new GreatestCommonDivisorModEval<ModLong>());
256        } else if (ofac instanceof BigRational) {
257            ufd = new GCDProxy<BigRational>(new GreatestCommonDivisorSubres<BigRational>(), 
258                                            new GreatestCommonDivisorSimple<BigRational>());
259        } else {
260            if (fac.isField()) {
261                ufd = new GCDProxy<C>(new GreatestCommonDivisorSimple<C>(),
262                                      new GreatestCommonDivisorSubres<C>());
263            } else {
264                ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(),
265                                      new GreatestCommonDivisorPrimitive<C>()); // no resultant
266            }
267        }
268        logger.debug("ufd = " + ufd);
269        return ufd;
270    }
271
272}