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