001/*
002 * $Id: SGCDFactory.java 5502 2016-05-12 21:58:10Z kredel $
003 */
004
005package edu.jas.fd;
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 * Solvable greatest common divisor algorithms factory. Select appropriate SGCD
023 * engine 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> 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 *        implementation. On systems with more than two CPUs the computing time
039 *        will be the time of the fastest algorithm implementation.
040 * 
041 *        <pre>
042 *        GreatestCommonDivisor&lt;CT&gt; engine;
043 *        engine = SGCDFactory.&lt;CT&gt; getImplementation(cofac);
044 *        or engine = SGCDFactory.&lt;CT&gt; getProxy(cofac);
045 *        c = engine.leftGcd(a, b);
046 *        </pre>
047 * 
048 *        For example, if the coefficient type is <code>BigInteger</code>, the
049 *        usage looks like
050 * 
051 *        <pre>
052 *        BigInteger cofac = new BigInteger();
053 *        GreatestCommonDivisor&lt;BigInteger&gt; engine;
054 *        engine = SGCDFactory.getImplementation(cofac);
055 *        or engine = SGCDFactory.getProxy(cofac);
056 *        c = engine.leftGcd(a, b);
057 *        </pre>
058 * 
059 * @see edu.jas.fd.GreatestCommonDivisor#leftGcd(edu.jas.poly.GenSolvablePolynomial
060 *      P, edu.jas.poly.GenSolvablePolynomial S)
061 */
062
063public class SGCDFactory {
064
065
066    private static final Logger logger = Logger.getLogger(SGCDFactory.class);
067
068
069    /**
070     * Protected factory constructor.
071     */
072    protected SGCDFactory() {
073    }
074
075
076    /**
077     * Determine suitable implementation of gcd algorithms, case ModLong.
078     * @param fac ModLongRing.
079     * @return gcd algorithm implementation.
080     */
081    public static GreatestCommonDivisorAbstract<ModLong> getImplementation(ModLongRing fac) {
082        GreatestCommonDivisorAbstract<ModLong> ufd;
083        if (fac.isField()) {
084            ufd = new GreatestCommonDivisorSimple<ModLong>(fac);
085            return ufd;
086        }
087        ufd = new GreatestCommonDivisorPrimitive<ModLong>(fac);
088        return ufd;
089    }
090
091
092    /**
093     * Determine suitable proxy for gcd algorithms, case ModLong.
094     * @param fac ModLongRing.
095     * @return gcd algorithm implementation.
096     */
097    public static GreatestCommonDivisorAbstract<ModLong> getProxy(ModLongRing fac) {
098        GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2;
099        ufd1 = new GreatestCommonDivisorPrimitive<ModLong>(fac);
100        if (fac.isField()) {
101            ufd2 = new GreatestCommonDivisorSimple<ModLong>(fac);
102        } else {
103            ufd2 = new GreatestCommonDivisorSyzygy<ModLong>(fac);
104        }
105        return new SGCDParallelProxy<ModLong>(fac, ufd1, ufd2);
106    }
107
108
109    /**
110     * Determine suitable implementation of gcd algorithms, case ModInteger.
111     * @param fac ModIntegerRing.
112     * @return gcd algorithm implementation.
113     */
114    public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
115        GreatestCommonDivisorAbstract<ModInteger> ufd;
116        if (fac.isField()) {
117            ufd = new GreatestCommonDivisorSimple<ModInteger>(fac);
118            return ufd;
119        }
120        ufd = new GreatestCommonDivisorPrimitive<ModInteger>(fac);
121        return ufd;
122    }
123
124
125    /**
126     * Determine suitable proxy for gcd algorithms, case ModInteger.
127     * @param fac ModIntegerRing.
128     * @return gcd algorithm implementation.
129     */
130    public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) {
131        GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2;
132        ufd1 = new GreatestCommonDivisorPrimitive<ModInteger>(fac);
133        if (fac.isField()) {
134            ufd2 = new GreatestCommonDivisorSimple<ModInteger>(fac);
135        } else {
136            ufd2 = new GreatestCommonDivisorSyzygy<ModInteger>(fac);
137        }
138        return new SGCDParallelProxy<ModInteger>(fac, ufd1, ufd2);
139    }
140
141
142    /**
143     * Determine suitable implementation of gcd algorithms, case BigInteger.
144     * @param fac BigInteger.
145     * @return gcd algorithm implementation.
146     */
147    @SuppressWarnings("unused")
148    public static GreatestCommonDivisorAbstract<BigInteger> getImplementation(BigInteger fac) {
149        GreatestCommonDivisorAbstract<BigInteger> ufd;
150        if (true) {
151            ufd = new GreatestCommonDivisorPrimitive<BigInteger>(fac);
152        } else {
153            ufd = new GreatestCommonDivisorSimple<BigInteger>(fac);
154        }
155        return ufd;
156    }
157
158
159    /**
160     * Determine suitable proxy for gcd algorithms, case BigInteger.
161     * @param fac BigInteger.
162     * @return gcd algorithm implementation.
163     */
164    public static GreatestCommonDivisorAbstract<BigInteger> getProxy(BigInteger fac) {
165        if (fac == null) {
166            throw new IllegalArgumentException("fac == null not supported");
167        }
168        GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2;
169        ufd1 = new GreatestCommonDivisorPrimitive<BigInteger>(fac);
170        ufd2 = new GreatestCommonDivisorSyzygy<BigInteger>(fac);
171        return new SGCDParallelProxy<BigInteger>(fac, ufd1, ufd2);
172    }
173
174
175    /**
176     * Determine suitable implementation of gcd algorithms, case BigRational.
177     * @param fac BigRational.
178     * @return gcd algorithm implementation.
179     */
180    public static GreatestCommonDivisorAbstract<BigRational> getImplementation(BigRational fac) {
181        if (fac == null) {
182            throw new IllegalArgumentException("fac == null not supported");
183        }
184        GreatestCommonDivisorAbstract<BigRational> ufd;
185        ufd = new GreatestCommonDivisorPrimitive<BigRational>(fac);
186        return ufd;
187    }
188
189
190    /**
191     * Determine suitable proxy for gcd algorithms, case BigRational.
192     * @param fac BigRational.
193     * @return gcd algorithm implementation.
194     */
195    public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) {
196        if (fac == null) {
197            throw new IllegalArgumentException("fac == null not supported");
198        }
199        GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2;
200        ufd1 = new GreatestCommonDivisorPrimitive<BigRational>(fac);
201        ufd2 = new GreatestCommonDivisorSimple<BigRational>(fac);
202        return new SGCDParallelProxy<BigRational>(fac, ufd1, ufd2);
203    }
204
205
206    /**
207     * Determine suitable implementation of gcd algorithms, other cases.
208     * @param fac RingFactory&lt;C&gt;.
209     * @return gcd algorithm implementation.
210     */
211    @SuppressWarnings("unchecked")
212    public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation(
213                    RingFactory<C> fac) {
214        GreatestCommonDivisorAbstract/*raw type<C>*/ ufd;
215        logger.debug("fac = " + fac.getClass().getName());
216        Object ofac = fac;
217        if (ofac instanceof BigInteger) {
218            ufd = new GreatestCommonDivisorPrimitive<C>(fac);
219        } else if (ofac instanceof ModIntegerRing) {
220            if (fac.isField()) {
221                ufd = new GreatestCommonDivisorSimple<C>(fac);
222            } else {
223                ufd = new GreatestCommonDivisorPrimitive<C>(fac);
224            }
225        } else if (ofac instanceof ModLongRing) {
226            if (fac.isField()) {
227                ufd = new GreatestCommonDivisorSimple<C>(fac);
228            } else {
229                ufd = new GreatestCommonDivisorPrimitive<C>(fac);
230            }
231        } else if (ofac instanceof BigRational) {
232            ufd = new GreatestCommonDivisorSimple<C>(fac);
233        } else {
234            if (fac.isField()) {
235                ufd = new GreatestCommonDivisorSimple<C>(fac);
236            } else {
237                ufd = new GreatestCommonDivisorPrimitive<C>(fac);
238            }
239        }
240        logger.debug("implementation = " + ufd);
241        return ufd;
242    }
243
244
245    /**
246     * Determine suitable proxy for gcd algorithms, other cases.
247     * @param fac RingFactory&lt;C&gt;.
248     * @return gcd algorithm implementation. <b>Note:</b> This method contains a
249     *         hack for Google app engine to not use threads.
250     * @see edu.jas.kern.ComputerThreads#NO_THREADS
251     */
252    @SuppressWarnings("unchecked")
253    public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) {
254        if (ComputerThreads.NO_THREADS) { // hack for Google app engine
255            return SGCDFactory.<C> getImplementation(fac);
256        }
257        GreatestCommonDivisorAbstract/*raw type<C>*/ ufd;
258        logger.debug("fac = " + fac.getClass().getName());
259        Object ofac = fac;
260        if (ofac instanceof BigInteger) {
261            ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac),
262                            new GreatestCommonDivisorPrimitive<C>(fac));
263        } else if (ofac instanceof ModIntegerRing) {
264            ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac),
265                            new GreatestCommonDivisorPrimitive<C>(fac));
266        } else if (ofac instanceof ModLongRing) {
267            ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac),
268                            new GreatestCommonDivisorPrimitive<C>(fac));
269        } else if (ofac instanceof BigRational) {
270            ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorPrimitive<C>(fac),
271                            new GreatestCommonDivisorSimple<C>(fac));
272        } else {
273            if (fac.isField()) {
274                ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac),
275                                new GreatestCommonDivisorPrimitive<C>(fac));
276            } else {
277                ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSyzygy<C>(fac),
278                                new GreatestCommonDivisorPrimitive<C>(fac));
279            }
280        }
281        logger.debug("ufd = " + ufd);
282        return ufd;
283    }
284
285}