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