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