001/*
002 * $Id: FactorFactory.java 5871 2018-07-20 15:58:45Z kredel $
003 */
004
005package edu.jas.ufd;
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.poly.AlgebraicNumber;
018import edu.jas.poly.AlgebraicNumberRing;
019import edu.jas.poly.Complex;
020import edu.jas.poly.ComplexRing;
021import edu.jas.poly.GenPolynomialRing;
022import edu.jas.structure.GcdRingElem;
023import edu.jas.structure.RingFactory;
024
025
026/**
027 * Factorization algorithms factory. Select appropriate factorization engine
028 * based on the coefficient types.
029 * @author Heinz Kredel
030 * @usage To create objects that implement the <code>Factorization</code>
031 *        interface use the <code>FactorFactory</code>. It will select an
032 *        appropriate implementation based on the types of polynomial
033 *        coefficients C. To obtain an implementation use
034 *        <code>getImplementation()</code>, it returns an object of a class
035 *        which extends the <code>FactorAbstract</code> class which implements
036 *        the <code>Factorization</code> interface.
037 * 
038 *        <pre>
039 *        Factorization&lt;CT&gt; engine;
040 *        engine = FactorFactory.&lt;CT&gt; getImplementation(cofac);
041 *        c = engine.factors(a);
042 *        </pre>
043 * 
044 *        For example, if the coefficient type is BigInteger, the usage looks
045 *        like
046 * 
047 *        <pre>
048 *        BigInteger cofac = new BigInteger();
049 *        Factorization&lt;BigInteger&gt; engine;
050 *        engine = FactorFactory.getImplementation(cofac);
051 *        Sm = engine.factors(poly);
052 *        </pre>
053 * 
054 * @see edu.jas.ufd.Factorization#factors(edu.jas.poly.GenPolynomial P)
055 */
056
057public class FactorFactory {
058
059
060    private static final Logger logger = LogManager.getLogger(FactorFactory.class);
061
062
063    /**
064     * Protected factory constructor.
065     */
066    protected FactorFactory() {
067    }
068
069
070    /**
071     * Determine suitable implementation of factorization algorithm, case
072     * ModInteger.
073     * @param fac ModIntegerRing.
074     * @return factorization algorithm implementation.
075     */
076    public static FactorAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
077        return new FactorModular<ModInteger>(fac);
078    }
079
080
081    /**
082     * Determine suitable implementation of factorization algorithm, case
083     * ModInteger.
084     * @param fac ModIntegerRing.
085     * @return factorization algorithm implementation.
086     */
087    public static FactorAbstract<ModLong> getImplementation(ModLongRing fac) {
088        return new FactorModular<ModLong>(fac);
089    }
090
091
092    /**
093     * Determine suitable implementation of factorization algorithm, case
094     * BigInteger.
095     * @param fac BigInteger.
096     * @return factorization algorithm implementation.
097     */
098    public static FactorAbstract<BigInteger> getImplementation(BigInteger fac) {
099        if (fac == null) {
100            throw new IllegalArgumentException("fac == null not supported");
101        }
102        return new FactorInteger<ModLong>();
103    }
104
105
106    /**
107     * Determine suitable implementation of factorization algorithms, case
108     * BigRational.
109     * @param fac BigRational.
110     * @return factorization algorithm implementation.
111     */
112    public static FactorAbstract<BigRational> getImplementation(BigRational fac) {
113        if (fac == null) {
114            throw new IllegalArgumentException("fac == null not supported");
115        }
116        return new FactorRational();
117    }
118
119
120    /**
121     * Determine suitable implementation of factorization algorithms, case
122     * AlgebraicNumber&lt;C&gt;.
123     * @param fac AlgebraicNumberRing&lt;C&gt;.
124     * @param <C> coefficient type, e.g. BigRational, ModInteger.
125     * @return factorization algorithm implementation.
126     */
127    public static <C extends GcdRingElem<C>> FactorAbstract<AlgebraicNumber<C>> getImplementation(
128                    AlgebraicNumberRing<C> fac) {
129        return new FactorAlgebraic<C>(fac);
130    }
131
132
133    /**
134     * Determine suitable implementation of factorization algorithms, case
135     * Complex&lt;C&gt;.
136     * @param fac ComplexRing&lt;C&gt;.
137     * @param <C> coefficient type, e.g. BigRational, ModInteger.
138     * @return factorization algorithm implementation.
139     */
140    public static <C extends GcdRingElem<C>> FactorAbstract<Complex<C>> getImplementation(
141                    ComplexRing<C> fac) {
142        return new FactorComplex<C>(fac);
143    }
144
145
146    /**
147     * Determine suitable implementation of factorization algorithms, case
148     * Quotient&lt;C&gt;.
149     * @param fac QuotientRing&lt;C&gt;.
150     * @param <C> coefficient type, e.g. BigRational, ModInteger.
151     * @return factorization algorithm implementation.
152     */
153    public static <C extends GcdRingElem<C>> FactorAbstract<Quotient<C>> getImplementation(
154                    QuotientRing<C> fac) {
155        return new FactorQuotient<C>(fac);
156    }
157
158
159    /**
160     * Determine suitable implementation of factorization algorithms, case
161     * recursive GenPolynomial&lt;C&gt;. Use <code>recursiveFactors()</code>.
162     * @param fac GenPolynomialRing&lt;C&gt;.
163     * @param <C> coefficient type, e.g. BigRational, ModInteger.
164     * @return factorization algorithm implementation.
165     */
166    public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(GenPolynomialRing<C> fac) {
167        return getImplementation(fac.coFac);
168    }
169
170
171    /**
172     * Determine suitable implementation of factorization algorithms, other
173     * cases.
174     * @param <C> coefficient type
175     * @param fac RingFactory&lt;C&gt;.
176     * @return factorization algorithm implementation.
177     */
178    @SuppressWarnings({ "unchecked", "cast" })
179    public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(RingFactory<C> fac) {
180        logger.info("factor factory = " + fac.getClass().getName());
181        //System.out.println("fac_o_ufd = " + fac.getClass().getName());
182        FactorAbstract/*raw type<C>*/ ufd = null;
183        AlgebraicNumberRing afac = null;
184        ComplexRing cfac = null;
185        QuotientRing qfac = null;
186        GenPolynomialRing pfac = null;
187        Object ofac = fac;
188        if (ofac instanceof BigInteger) {
189            ufd = new FactorInteger();
190        } else if (ofac instanceof BigRational) {
191            ufd = new FactorRational();
192        } else if (ofac instanceof ModIntegerRing) {
193            ufd = new FactorModular(fac);
194        } else if (ofac instanceof ModLongRing) {
195            ufd = new FactorModular(fac);
196        } else if (ofac instanceof ComplexRing) {
197            cfac = (ComplexRing<C>) ofac;
198            ufd = new FactorComplex(cfac);
199        } else if (ofac instanceof AlgebraicNumberRing) {
200            //System.out.println("afac_o = " + ofac);
201            afac = (AlgebraicNumberRing) ofac;
202            //ofac = afac.ring.coFac;
203            ufd = new FactorAlgebraic/*raw <C>*/(afac);
204        } else if (ofac instanceof QuotientRing) {
205            //System.out.println("qfac_o = " + ofac);
206            qfac = (QuotientRing) ofac;
207            ufd = new FactorQuotient/*raw <C>*/(qfac);
208        } else if (ofac instanceof GenPolynomialRing) {
209            //System.out.println("qfac_o = " + ofac);
210            pfac = (GenPolynomialRing) ofac;
211            ufd = getImplementation(pfac.coFac);
212        } else {
213            throw new IllegalArgumentException(
214                            "no factorization implementation for " + fac.getClass().getName());
215        }
216        //logger.info("implementation = " + ufd);
217        return (FactorAbstract<C>) ufd;
218    }
219
220}