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