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