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