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 -> e_1, ..., p_k -> 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}