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