001    /*
002     * $Id: FactorFactory.java 3676 2011-07-02 10:51:16Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import org.apache.log4j.Logger;
009    
010    import edu.jas.arith.BigInteger;
011    import edu.jas.arith.BigRational;
012    import edu.jas.arith.ModInteger;
013    import edu.jas.arith.ModIntegerRing;
014    import edu.jas.arith.ModLong;
015    import edu.jas.arith.ModLongRing;
016    import edu.jas.arith.Rational;
017    import edu.jas.poly.AlgebraicNumber;
018    import edu.jas.poly.AlgebraicNumberRing;
019    import edu.jas.poly.Complex;
020    import edu.jas.poly.ComplexRing;
021    import edu.jas.poly.GenPolynomialRing;
022    import edu.jas.root.RealAlgebraicNumber;
023    import edu.jas.root.RealAlgebraicRing;
024    import edu.jas.structure.GcdRingElem;
025    import edu.jas.structure.RingFactory;
026    
027    
028    /**
029     * Factorization algorithms factory. Select appropriate factorization engine
030     * based on the coefficient types.
031     * @author Heinz Kredel
032     * @usage To create objects that implement the <code>Factorization</code>
033     *        interface use the <code>FactorFactory</code>. It will select an
034     *        appropriate implementation based on the types of polynomial
035     *        coefficients C. To obtain an implementation use
036     *        <code>getImplementation()</code>, it returns an object of a class
037     *        which extends the <code>FactorAbstract</code> class which implements
038     *        the <code>Factorization</code> interface.
039     * 
040     *        <pre>
041     * Factorization&lt;CT&gt; engine;
042     * engine = FactorFactory.&lt;CT&gt; getImplementation(cofac);
043     * c = engine.factors(a);
044     * </pre>
045     * 
046     *        For example, if the coefficient type is BigInteger, the usage looks
047     *        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     * @see edu.jas.ufd.Factorization#factors(edu.jas.poly.GenPolynomial P)
057     */
058    
059    public class FactorFactory {
060    
061    
062        private static final Logger logger = Logger.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         * BigInteger.
097         * @param fac BigInteger.
098         * @return factorization algorithm implementation.
099         */
100        public static FactorAbstract<BigInteger> getImplementation(BigInteger fac) {
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            return new FactorRational();
113        }
114    
115    
116        /**
117         * Determine suitable implementation of factorization algorithms, case
118         * AlgebraicNumber&lt;C&gt;.
119         * @param fac AlgebraicNumberRing&lt;C&gt;.
120         * @param <C> coefficient type, e.g. BigRational, ModInteger.
121         * @return factorization algorithm implementation.
122         */
123        public static <C extends GcdRingElem<C>> FactorAbstract<AlgebraicNumber<C>> getImplementation(
124                        AlgebraicNumberRing<C> fac) {
125            return new FactorAlgebraic<C>(fac);
126        }
127    
128    
129        /**
130         * Determine suitable implementation of factorization algorithms, case
131         * Complex&lt;C&gt;.
132         * @param fac ComplexRing&lt;C&gt;.
133         * @param <C> coefficient type, e.g. BigRational, ModInteger.
134         * @return factorization algorithm implementation.
135         */
136        public static <C extends GcdRingElem<C>> FactorAbstract<Complex<C>> getImplementation(ComplexRing<C> fac) {
137            return new FactorComplex<C>(fac);
138        }
139    
140    
141        /**
142         * Determine suitable implementation of factorization algorithms, case
143         * Quotient&lt;C&gt;.
144         * @param fac QuotientRing&lt;C&gt;.
145         * @param <C> coefficient type, e.g. BigRational, ModInteger.
146         * @return factorization algorithm implementation.
147         */
148        public static <C extends GcdRingElem<C>> FactorAbstract<Quotient<C>> getImplementation(QuotientRing<C> fac) {
149            return new FactorQuotient<C>(fac);
150        }
151    
152    
153        /**
154         * Determine suitable implementation of factorization algorithms, case
155         * recursive GenPolynomial&lt;C&gt;. Use <code>recursiveFactors()</code>.
156         * @param fac GenPolynomialRing&lt;C&gt;.
157         * @param <C> coefficient type, e.g. BigRational, ModInteger.
158         * @return factorization algorithm implementation.
159         */
160        public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(GenPolynomialRing<C> fac) {
161            return getImplementation(fac.coFac);
162        }
163    
164    
165        /**
166         * Determine suitable implementation of factorization algorithms, case
167         * RealAlgebraicNumber&lt;C&gt;.
168         * @param fac RealAlgebraicRing&lt;C&gt;.
169         * @param <C> coefficient type, e.g. BigRational.
170         * @return factorization algorithm implementation.
171         */
172        public static <C extends GcdRingElem<C> & Rational> FactorAbstract<RealAlgebraicNumber<C>> getImplementation(
173                        RealAlgebraicRing<C> fac) {
174            return new FactorRealAlgebraic<C>(fac);
175        }
176    
177    
178        /**
179         * Determine suitable implementation of factorization algorithms, other
180         * cases.
181         * @param <C> coefficient type
182         * @param fac RingFactory&lt;C&gt;.
183         * @return factorization algorithm implementation.
184         */
185        @SuppressWarnings("unchecked")
186        public static <C extends GcdRingElem<C>> FactorAbstract<C> getImplementation(RingFactory<C> fac) {
187            //logger.info("fac = " + fac.getClass().getName());
188            //System.out.println("fac_o = " + fac.getClass().getName());
189            FactorAbstract/*raw type<C>*/ufd = null;
190            AlgebraicNumberRing afac = null;
191            RealAlgebraicRing rfac = null;
192            QuotientRing qfac = null;
193            GenPolynomialRing pfac = null;
194            Object ofac = fac;
195            if (ofac instanceof BigInteger) {
196                ufd = new FactorInteger();
197            } else if (ofac instanceof BigRational) {
198                ufd = new FactorRational();
199            } else if (ofac instanceof ModIntegerRing) {
200                ufd = new FactorModular(fac);
201            } else if (ofac instanceof ModLongRing) {
202                ufd = new FactorModular(fac);
203            } else if (ofac instanceof ComplexRing) {
204                ufd = new FactorComplex(fac);
205            } else if (ofac instanceof AlgebraicNumberRing) {
206                //System.out.println("afac_o = " + ofac);
207                afac = (AlgebraicNumberRing) ofac;
208                ofac = afac.ring.coFac;
209                ufd = new FactorAlgebraic/*raw <C>*/(afac);
210            } else if (ofac instanceof QuotientRing) {
211                //System.out.println("qfac_o = " + ofac);
212                qfac = (QuotientRing) ofac;
213                ufd = new FactorQuotient/*raw <C>*/(qfac);
214            } else if (ofac instanceof GenPolynomialRing) {
215                //System.out.println("qfac_o = " + ofac);
216                pfac = (GenPolynomialRing) ofac;
217                ufd = getImplementation(pfac.coFac);
218            } else if (ofac instanceof RealAlgebraicRing) {
219                //System.out.println("rfac_o = " + ofac);
220                rfac = (RealAlgebraicRing) ofac;
221                ofac = rfac.algebraic;
222                ufd = new FactorRealAlgebraic/*raw <C>*/(rfac);
223            } else {
224                throw new IllegalArgumentException("no factorization implementation for "
225                                + fac.getClass().getName());
226            }
227            logger.info("implementation = " + ufd);
228            return (FactorAbstract<C>) ufd;
229        }
230    
231    }