001/*
002 * $Id$
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    @SuppressWarnings("unchecked")
141    public static <C extends GcdRingElem<C>> FactorAbstract<AlgebraicNumber<C>> getImplementation(
142                    AlgebraicNumberRing<C> fac) {
143        int s = fac.characteristic().signum();
144        if (s > 0) {
145            return new FactorModularBerlekamp/*<AlgebraicNumberRing<C>>*/((RingFactory)fac);
146        } else {
147            return new FactorAlgebraic<C>(fac);
148        }
149    }
150
151
152    /**
153     * Determine suitable implementation of factorization algorithms, case
154     * Complex&lt;C&gt;.
155     * @param fac ComplexRing&lt;C&gt;.
156     * @param <C> coefficient type, e.g. BigRational, ModInteger.
157     * @return factorization algorithm implementation.
158     */
159    public static <C extends GcdRingElem<C>> FactorAbstract<Complex<C>> getImplementation(
160                    ComplexRing<C> fac) {
161        return new FactorComplex<C>(fac);
162    }
163
164
165    /**
166     * Determine suitable implementation of factorization algorithms, case
167     * Quotient&lt;C&gt;.
168     * @param fac QuotientRing&lt;C&gt;.
169     * @param <C> coefficient type, e.g. BigRational, ModInteger.
170     * @return factorization algorithm implementation.
171     */
172    public static <C extends GcdRingElem<C>> FactorAbstract<Quotient<C>> getImplementation(
173                    QuotientRing<C> fac) {
174        return new FactorQuotient<C>(fac);
175    }
176
177
178    /**
179     * Determine suitable implementation of factorization algorithms, case
180     * recursive GenPolynomial&lt;C&gt;. Use <code>recursiveFactors()</code>.
181     * @param fac GenPolynomialRing&lt;C&gt;.
182     * @param <C> coefficient type, e.g. BigRational, ModInteger.
183     * @return factorization algorithm implementation.
184     */
185    public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(GenPolynomialRing<C> fac) {
186        return getImplementation(fac.coFac);
187    }
188
189
190    /**
191     * Determine suitable implementation of factorization algorithms, other
192     * cases.
193     * @param <C> coefficient type
194     * @param fac RingFactory&lt;C&gt;.
195     * @return factorization algorithm implementation.
196     */
197    @SuppressWarnings( "unchecked" )
198    public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(RingFactory<C> fac) {
199        logger.info("factor factory = {}", fac.getClass().getName());
200        //System.out.println("fac_o_ufd = " + fac.getClass().getName());
201        FactorAbstract/*raw type<C>*/ ufd = null;
202        AlgebraicNumberRing afac = null;
203        ComplexRing cfac = null;
204        QuotientRing qfac = null;
205        GenPolynomialRing pfac = null;
206        Object ofac = fac;
207        if (ofac instanceof BigInteger) {
208            ufd = new FactorInteger();
209        } else if (ofac instanceof BigRational) {
210            ufd = new FactorRational();
211        } else if (ofac instanceof ModIntegerRing) {
212            ufd = new FactorModular(fac);
213        } else if (ofac instanceof ModLongRing) {
214            ufd = new FactorModular(fac);
215        } else if (ofac instanceof ModIntRing) {
216            ufd = new FactorModular(fac);
217        } else if (ofac instanceof ComplexRing) {
218            cfac = (ComplexRing<C>) ofac;
219            ufd = new FactorComplex(cfac);
220        } else if (ofac instanceof AlgebraicNumberRing) {
221            //System.out.println("afac_o = " + ofac);
222            afac = (AlgebraicNumberRing) ofac;
223            //ofac = afac.ring.coFac;
224            int s = afac.characteristic().signum();
225            if (s > 0) {
226                ufd = new FactorModularBerlekamp/*raw <C>*/(afac);
227            } else {
228                ufd = new FactorAlgebraic/*raw <C>*/(afac);
229            }
230        } else if (ofac instanceof QuotientRing) {
231            //System.out.println("qfac_o = " + ofac);
232            qfac = (QuotientRing) ofac;
233            ufd = new FactorQuotient/*raw <C>*/(qfac);
234        } else if (ofac instanceof GenPolynomialRing) {
235            //System.out.println("qfac_o = " + ofac);
236            pfac = (GenPolynomialRing) ofac;
237            ufd = getImplementation(pfac.coFac);
238        } else {
239            throw new IllegalArgumentException(
240                            "no factorization implementation for " + fac.getClass().getName());
241        }
242        //logger.info("implementation = {}", ufd);
243        return (FactorAbstract<C>) ufd;
244    }
245
246}