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