001    /*
002     * $Id: SquarefreeFactory.java 3356 2010-10-23 16:41:01Z 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.poly.AlgebraicNumber;
017    import edu.jas.poly.AlgebraicNumberRing;
018    import edu.jas.poly.GenPolynomialRing;
019    import edu.jas.structure.GcdRingElem;
020    import edu.jas.structure.RingFactory;
021    
022    
023    /**
024     * Squarefree factorization algorithms factory. Select appropriate squarefree
025     * factorization engine based on the coefficient types.
026     * @author Heinz Kredel
027     * @usage To create objects that implement the <code>Squarefree</code> interface
028     *        use the <code>SquarefreeFactory</code>. It will select an appropriate
029     *        implementation based on the types of polynomial coefficients C. To
030     *        obtain an implementation use <code>getImplementation()</code>, it
031     *        returns an object of a class which extends the
032     *        <code>SquarefreeAbstract</code> class which implements the
033     *        <code>Squarefree</code> interface.
034     * 
035     *        <pre>
036     * Squarefree&lt;CT&gt; engine;
037     * engine = SquarefreeFactory.&lt;CT&gt; getImplementation(cofac);
038     * c = engine.squarefreeFactors(a);
039     * </pre>
040     * 
041     *        For example, if the coefficient type is BigInteger, the usage looks
042     *        like
043     * 
044     *        <pre>
045     * BigInteger cofac = new BigInteger();
046     * Squarefree&lt;BigInteger&gt; engine;
047     * engine = SquarefreeFactory.getImplementation(cofac);
048     * Sm = engine.sqaurefreeFactors(poly);
049     * </pre>
050     * 
051     * @see edu.jas.ufd.Squarefree#squarefreeFactors(edu.jas.poly.GenPolynomial P)
052     */
053    
054    public class SquarefreeFactory {
055    
056    
057        private static final Logger logger = Logger.getLogger(SquarefreeFactory.class);
058    
059    
060        /**
061         * Protected factory constructor.
062         */
063        protected SquarefreeFactory() {
064        }
065    
066    
067        /**
068         * Determine suitable implementation of factorization algorithm, case
069         * ModInteger.
070         * @param fac ModIntegerRing.
071         * @return squarefree factorization algorithm implementation.
072         */
073        public static SquarefreeAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
074            return new SquarefreeFiniteFieldCharP<ModInteger>(fac);
075        }
076    
077    
078        /**
079         * Determine suitable implementation of factorization algorithm, case
080         * ModLong.
081         * @param fac ModLongRing.
082         * @return squarefree factorization algorithm implementation.
083         */
084        public static SquarefreeAbstract<ModLong> getImplementation(ModLongRing fac) {
085            return new SquarefreeFiniteFieldCharP<ModLong>(fac);
086        }
087    
088    
089        /**
090         * Determine suitable implementation of squarefree factorization algorithm,
091         * case BigInteger.
092         * @param fac BigInteger.
093         * @return squarefree factorization algorithm implementation.
094         */
095        public static SquarefreeAbstract<BigInteger> getImplementation(BigInteger fac) {
096            return new SquarefreeRingChar0<BigInteger>(fac);
097        }
098    
099    
100        /**
101         * Determine suitable implementation of squarefree factorization algorithms,
102         * case BigRational.
103         * @param fac BigRational.
104         * @return squarefree factorization algorithm implementation.
105         */
106        public static SquarefreeAbstract<BigRational> getImplementation(BigRational fac) {
107            return new SquarefreeFieldChar0<BigRational>(fac);
108        }
109    
110    
111        /**
112         * Determine suitable implementation of squarefree factorization algorithms,
113         * case AlgebraicNumber&lt;C&gt;.
114         * @param fac AlgebraicNumberRing&lt;C&gt;.
115         * @param <C> coefficient type, e.g. BigRational, ModInteger.
116         * @return squarefree factorization algorithm implementation.
117         */
118        public static <C extends GcdRingElem<C>> SquarefreeAbstract<AlgebraicNumber<C>> getImplementation(
119                AlgebraicNumberRing<C> fac) {
120            PolyUfdUtil.<C> ensureFieldProperty(fac);
121            if (fac.isField()) {
122                if (fac.characteristic().signum() == 0) {
123                    return new SquarefreeFieldChar0<AlgebraicNumber<C>>(fac);
124                } else {
125                    if (fac.isFinite()) {
126                        return new SquarefreeFiniteFieldCharP<AlgebraicNumber<C>>(fac);
127                    } else {
128                        return new SquarefreeInfiniteAlgebraicFieldCharP<C>(fac);
129                        //throw new RuntimeException("algebraic extension of infinite not implemented" 
130                        //                          + fac.getClass().getName());
131                    }
132                }
133            } else {
134                throw new ArithmeticException("eventually no integral domain " + fac.getClass().getName());
135            }
136        }
137    
138    
139        /**
140         * Determine suitable implementation of squarefree factorization algorithms,
141         * case Quotient&lt;C&gt;.
142         * @param fac QuotientRing&lt;C&gt;.
143         * @param <C> coefficient type, e.g. BigRational, ModInteger.
144         * @return squarefree factorization algorithm implementation.
145         */
146        public static <C extends GcdRingElem<C>> SquarefreeAbstract<Quotient<C>> getImplementation(
147                QuotientRing<C> fac) {
148            if (fac.characteristic().signum() == 0) {
149                return new SquarefreeFieldChar0<Quotient<C>>(fac);
150            } else {
151                return new SquarefreeInfiniteFieldCharP<C>(fac);
152            }
153        }
154    
155    
156        /**
157         * Determine suitable implementation of squarefree factorization algorithms,
158         * case GenPolynomial&lt;C&gt;.
159         * @param fac GenPolynomialRing&lt;C&gt;.
160         * @param <C> coefficient type, e.g. BigRational, ModInteger.
161         * @return squarefree factorization algorithm implementation.
162         */
163        public static <C extends GcdRingElem<C>> SquarefreeAbstract<C> getImplementation(GenPolynomialRing<C> fac) {
164            return getImplementationPoly(fac);
165        }
166    
167    
168        /*
169         * Determine suitable implementation of squarefree factorization algorithms,
170         * case GenPolynomial&lt;C&gt;.
171         * @param fac GenPolynomialRing&lt;C&gt;.
172         * @param <C> coefficient type, e.g. BigRational, ModInteger.
173         * @return squarefree factorization algorithm implementation.
174         */
175        protected static <C extends GcdRingElem<C>> SquarefreeAbstract<C> getImplementationPoly(
176                GenPolynomialRing<C> fac) {
177            if (fac.characteristic().signum() == 0) {
178                if (fac.coFac.isField()) {
179                    return new SquarefreeFieldChar0<C>(fac.coFac);
180                } else {
181                    return new SquarefreeRingChar0<C>(fac.coFac);
182                }
183            } else {
184                if (fac.coFac.isFinite()) {
185                    return new SquarefreeFiniteFieldCharP<C>(fac.coFac);
186                } else {
187                    Object ocfac = fac.coFac;
188                    SquarefreeAbstract saq = null;
189                    if (ocfac instanceof QuotientRing) {
190                        QuotientRing<C> qf = (QuotientRing<C>) ocfac;
191                        saq = new SquarefreeInfiniteFieldCharP<C>(qf);
192                    } else if (ocfac instanceof AlgebraicNumberRing) {
193                        AlgebraicNumberRing<C> af = (AlgebraicNumberRing<C>) ocfac;
194                        saq = new SquarefreeInfiniteAlgebraicFieldCharP<C>(af);
195                    }
196                    if (saq == null) {
197                        throw new IllegalArgumentException("no squarefree factorization " + fac.coFac);
198                    }
199                    SquarefreeAbstract<C> sa = (SquarefreeAbstract<C>) saq;
200                    return sa;
201                }
202            }
203        }
204    
205    
206        /**
207         * Determine suitable implementation of squarefree factorization algorithms,
208         * other cases.
209         * @param <C> coefficient type
210         * @param fac RingFactory&lt;C&gt;.
211         * @return squarefree factorization algorithm implementation.
212         */
213        @SuppressWarnings("unchecked")
214        public static <C extends GcdRingElem<C>> SquarefreeAbstract<C> getImplementation(RingFactory<C> fac) {
215            //logger.info("fac = " + fac.getClass().getName());
216            //System.out.println("fac_o = " + fac.getClass().getName());
217            int t = 0;
218            SquarefreeAbstract/*raw type<C>*/ufd = null;
219            AlgebraicNumberRing afac = null;
220            QuotientRing qfac = null;
221            GenPolynomialRing pfac = null;
222            while (true) { // switch
223                Object ofac = fac;
224                if (ofac instanceof BigInteger) {
225                    t = 1;
226                    break;
227                }
228                if (ofac instanceof BigRational) {
229                    t = 2;
230                    break;
231                }
232                if (ofac instanceof ModIntegerRing) {
233                    t = 3;
234                    break;
235                }
236                if (ofac instanceof ModLongRing) {
237                    t = 10;
238                    break;
239                }
240                if (ofac instanceof AlgebraicNumberRing) {
241                    //System.out.println("afac_o = " + ofac);
242                    afac = (AlgebraicNumberRing) ofac;
243                    ofac = afac.ring.coFac;
244                    //System.out.println("o_afac = " + ofac);
245                    t = 4;
246                    break;
247                }
248                if (ofac instanceof QuotientRing) {
249                    //System.out.println("qfac_o = " + ofac);
250                    qfac = (QuotientRing) ofac;
251                    t = 7;
252                    break;
253                }
254                if (ofac instanceof GenPolynomialRing) {
255                    //System.out.println("qfac_o = " + ofac);
256                    pfac = (GenPolynomialRing) ofac;
257                    t = 8;
258                    break;
259                }
260                if (fac.isField()) {
261                    //System.out.println("fac_field = " + fac);
262                    t = 9;
263                    break;
264                } else {
265                    t = 11;
266                    break;
267                }
268                //break;
269            }
270            //System.out.println("ft = " + t);
271            if (t == 1) { // BigInteger
272                ufd = new SquarefreeRingChar0/*raw*/(fac);
273            }
274            if (t == 2) { // BigRational
275                ufd = new SquarefreeFieldChar0/*raw*/(fac);
276            }
277            if (t == 3) { // ModInteger
278                ufd = new SquarefreeFiniteFieldCharP/*raw*/(fac);
279            }
280            if (t == 10) { // ModLong
281                ufd = new SquarefreeFiniteFieldCharP/*raw*/(fac);
282            }
283            if (t == 4) { // AlgebraicNumber
284                ufd = getImplementation(afac);
285            }
286            if (t == 7) { // Quotient
287                ufd = getImplementation(qfac);
288            }
289            if (t == 8) { // GenPolynomial
290                ufd = getImplementationPoly(pfac);
291            }
292            if (t == 9) { // other fields 
293                if (fac.characteristic().signum() == 0) {
294                    ufd = new SquarefreeFieldChar0/*raw*/(fac);
295                } else {
296                    if (fac.isFinite()) {
297                        ufd = new SquarefreeFiniteFieldCharP/*raw*/(fac);
298                    } else {
299                        ufd = new SquarefreeInfiniteFieldCharP/*raw*/(fac);
300                    }
301                }
302            }
303            if (t == 11) { // other rings 
304                if (fac.characteristic().signum() == 0) {
305                    ufd = new SquarefreeRingChar0/*raw*/(fac);
306                }
307                // else fail
308            }
309            if (ufd == null) {
310                throw new IllegalArgumentException("no squarefree factorization implementation for "
311                        + fac.getClass().getName());
312            }
313            logger.debug("ufd = " + ufd);
314            //System.out.println("ufd = " + ufd);
315            return (SquarefreeAbstract<C>) ufd;
316        }
317    
318    }