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