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