001/*
002 * $Id: FactorRational.java 5754 2017-05-28 15:07:12Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.SortedMap;
011import java.util.TreeMap;
012import java.util.Map;
013
014import org.apache.log4j.Logger;
015
016import edu.jas.arith.BigInteger;
017import edu.jas.arith.BigRational;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.PolyUtil;
021
022
023/**
024 * Rational number coefficients factorization algorithms. This class implements
025 * factorization methods for polynomials over rational numbers.
026 * @author Heinz Kredel
027 */
028
029public class FactorRational extends FactorAbsolute<BigRational> {
030
031
032    private static final Logger logger = Logger.getLogger(FactorRational.class);
033
034
035    private static final boolean debug = logger.isInfoEnabled();
036
037
038    /**
039     * Factorization engine for integer base coefficients.
040     */
041    protected final FactorAbstract<BigInteger> iengine;
042
043
044    /**
045     * No argument constructor.
046     */
047    protected FactorRational() {
048        super(BigRational.ONE);
049        iengine = FactorFactory.getImplementation(BigInteger.ONE);
050    }
051
052
053    /**
054     * GenPolynomial base factorization of a squarefree polynomial.
055     * @param P squarefree GenPolynomial.
056     * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
057     */
058    @Override
059    public List<GenPolynomial<BigRational>> baseFactorsSquarefree(GenPolynomial<BigRational> P) {
060        if (P == null) {
061            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
062        }
063        List<GenPolynomial<BigRational>> factors = new ArrayList<GenPolynomial<BigRational>>();
064        if (P.isZERO()) {
065            return factors;
066        }
067        if (P.isONE()) {
068            factors.add(P);
069            return factors;
070        }
071        GenPolynomialRing<BigRational> pfac = P.ring;
072        if (pfac.nvar > 1) {
073            throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
074        }
075        GenPolynomial<BigRational> Pr = P;
076        BigRational ldcf = P.leadingBaseCoefficient();
077        if (!ldcf.isONE()) {
078            //System.out.println("ldcf = " + ldcf);
079            Pr = Pr.monic();
080        }
081        BigInteger bi = BigInteger.ONE;
082        GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(bi, pfac);
083        GenPolynomial<BigInteger> Pi = PolyUtil.integerFromRationalCoefficients(ifac, Pr);
084        if (debug) {
085            logger.info("Pi = " + Pi);
086        }
087        List<GenPolynomial<BigInteger>> ifacts = iengine.baseFactorsSquarefree(Pi);
088        if (logger.isInfoEnabled()) {
089            logger.info("ifacts = " + ifacts);
090        }
091        if (ifacts.size() <= 1) {
092            factors.add(P);
093            return factors;
094        }
095        List<GenPolynomial<BigRational>> rfacts = PolyUtil.fromIntegerCoefficients(pfac, ifacts);
096        //System.out.println("rfacts = " + rfacts);
097        rfacts = PolyUtil.monic(rfacts);
098        //System.out.println("rfacts = " + rfacts);
099        if (!ldcf.isONE()) {
100            GenPolynomial<BigRational> r = rfacts.get(0);
101            rfacts.remove(r);
102            r = r.multiply(ldcf);
103            rfacts.set(0, r);
104        }
105        if (logger.isInfoEnabled()) {
106            logger.info("rfacts = " + rfacts);
107        }
108        factors.addAll(rfacts);
109        return factors;
110    }
111
112
113    /**
114     * GenPolynomial factorization of a squarefree polynomial.
115     * @param P squarefree GenPolynomial.
116     * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
117     */
118    @Override
119    public List<GenPolynomial<BigRational>> factorsSquarefree(GenPolynomial<BigRational> P) {
120        if (P == null) {
121            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
122        }
123        List<GenPolynomial<BigRational>> factors = new ArrayList<GenPolynomial<BigRational>>();
124        if (P.isZERO()) {
125            return factors;
126        }
127        if (P.isONE()) {
128            factors.add(P);
129            return factors;
130        }
131        GenPolynomialRing<BigRational> pfac = P.ring;
132        if (pfac.nvar == 1) {
133            return baseFactorsSquarefree(P);
134        }
135        GenPolynomial<BigRational> Pr = P;
136        BigRational ldcf = P.leadingBaseCoefficient();
137        if (!ldcf.isONE()) {
138            //System.out.println("ldcf = " + ldcf);
139            Pr = Pr.monic();
140        }
141        BigInteger bi = BigInteger.ONE;
142        GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(bi, pfac);
143        GenPolynomial<BigInteger> Pi = PolyUtil.integerFromRationalCoefficients(ifac, Pr);
144        if (debug) {
145            logger.info("Pi = " + Pi);
146        }
147        List<GenPolynomial<BigInteger>> ifacts = iengine.factorsSquarefree(Pi);
148        if (logger.isInfoEnabled()) {
149            logger.info("ifacts = " + ifacts);
150        }
151        if (ifacts.size() <= 1) {
152            factors.add(P);
153            return factors;
154        }
155        List<GenPolynomial<BigRational>> rfacts = PolyUtil.fromIntegerCoefficients(pfac, ifacts);
156        //System.out.println("rfacts = " + rfacts);
157        rfacts = PolyUtil.monic(rfacts);
158        //System.out.println("rfacts = " + rfacts);
159        if (!ldcf.isONE()) {
160            GenPolynomial<BigRational> r = rfacts.get(0);
161            rfacts.remove(r);
162            r = r.multiply(ldcf);
163            rfacts.set(0, r);
164        }
165        if (logger.isInfoEnabled()) {
166            logger.info("rfacts = " + rfacts);
167        }
168        factors.addAll(rfacts);
169        return factors;
170    }
171
172
173    /**
174     * GenPolynomial factorization of a polynomial.
175     * @param P GenPolynomial.
176     * @return [p_1 -&gt; e_1, ..., p_k -&gt; e_k] with P = prod_{i=1,...,k}
177     *         p_i**e_i and p_i irreducible.
178     */
179    @Override
180    public SortedMap<GenPolynomial<BigRational>, Long> factors(GenPolynomial<BigRational> P) {
181        if (P == null) {
182            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
183        }
184        GenPolynomialRing<BigRational> pfac = P.ring;
185        SortedMap<GenPolynomial<BigRational>, Long> factors = new TreeMap<GenPolynomial<BigRational>, Long>(pfac.getComparator());
186        if (P.isZERO()) {
187            return factors;
188        }
189        if (P.isONE()) {
190            factors.put(P, 1L);
191            return factors;
192        }
193        if (pfac.nvar == 1) {
194            return baseFactors(P);
195        }
196        GenPolynomial<BigRational> Pr = P;
197        BigInteger bi = BigInteger.ONE;
198        GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(bi, pfac);
199        GenPolynomial<BigInteger> Pi = PolyUtil.integerFromRationalCoefficients(ifac, Pr);
200        if (debug) {
201            logger.info("Pi = " + Pi);
202        }
203        SortedMap<GenPolynomial<BigInteger>, Long> ifacts = iengine.factors(Pi);
204        if (logger.isInfoEnabled()) {
205            logger.info("ifacts = " + ifacts);
206        }
207        for (Map.Entry<GenPolynomial<BigInteger>, Long> me : ifacts.entrySet()) {
208            GenPolynomial<BigInteger> g = me.getKey();
209            if (g.isONE()) { // skip 1
210                continue;
211            }
212            Long d = me.getValue(); // facs.get(g);
213            GenPolynomial<BigRational> rp = PolyUtil.fromIntegerCoefficients(pfac, g);
214            factors.put(rp, d);
215        }
216        return factors;
217    }
218
219}