001/* 002 * $Id: FactorModular.java 5774 2017-11-05 17:04:30Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011import java.util.SortedMap; 012import java.util.SortedSet; 013import java.util.TreeMap; 014import java.util.TreeSet; 015 016import org.apache.log4j.Logger; 017 018import edu.jas.arith.BigInteger; 019import edu.jas.arith.ModLongRing; 020import edu.jas.arith.Modular; 021import edu.jas.arith.ModularRingFactory; 022import edu.jas.poly.GenPolynomial; 023import edu.jas.poly.GenPolynomialRing; 024import edu.jas.poly.PolyUtil; 025import edu.jas.structure.GcdRingElem; 026import edu.jas.structure.Power; 027import edu.jas.structure.RingFactory; 028 029 030/** 031 * Modular coefficients factorization algorithms. This class implements 032 * factorization methods for polynomials over (prime) modular integers. 033 * @author Heinz Kredel 034 */ 035 036public class FactorModular<MOD extends GcdRingElem<MOD> & Modular> extends FactorAbsolute<MOD> { 037 038 039 private static final Logger logger = Logger.getLogger(FactorModular.class); 040 041 042 private static final boolean debug = logger.isDebugEnabled(); 043 044 045 /** 046 * No argument constructor, do not use. 047 */ 048 @SuppressWarnings({ "cast", "unused" }) 049 private FactorModular() { 050 this((RingFactory<MOD>) (Object) new ModLongRing(13, true)); // hack, 13 unimportant 051 } 052 053 054 /** 055 * Constructor. 056 * @param cfac coefficient ring factory. 057 */ 058 public FactorModular(RingFactory<MOD> cfac) { 059 super(cfac); 060 } 061 062 063 /** 064 * GenPolynomial base distinct degree factorization. 065 * @param P squarefree and monic GenPolynomial. 066 * @return [e_1 -> p_1, ..., e_k -> p_k] with P = prod_{i=1,...,k} p_i 067 * and p_i has only irreducible factors of degree e_i. 068 */ 069 public SortedMap<Long, GenPolynomial<MOD>> baseDistinctDegreeFactors(GenPolynomial<MOD> P) { 070 if (P == null) { 071 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 072 } 073 SortedMap<Long, GenPolynomial<MOD>> facs = new TreeMap<Long, GenPolynomial<MOD>>(); 074 if (P.isZERO()) { 075 return facs; 076 } 077 GenPolynomialRing<MOD> pfac = P.ring; 078 if (pfac.nvar > 1) { 079 throw new IllegalArgumentException( 080 this.getClass().getName() + " only for univariate polynomials"); 081 } 082 ModularRingFactory<MOD> mr = (ModularRingFactory<MOD>) pfac.coFac; 083 java.math.BigInteger m = mr.getIntegerModul().getVal(); 084 //if (m.longValue() == 2L) { 085 // logger.warn(this.getClass().getName() + " case p = 2 not implemented"); 086 //} 087 GenPolynomial<MOD> x = pfac.univariate(0); 088 GenPolynomial<MOD> h = x; 089 GenPolynomial<MOD> f = P; 090 GenPolynomial<MOD> g; 091 Power<GenPolynomial<MOD>> pow = new Power<GenPolynomial<MOD>>(pfac); 092 long d = 0; 093 while (d + 1 <= f.degree(0) / 2) { 094 d++; 095 h = pow.modPower(h, m, f); 096 g = engine.gcd(h.subtract(x), f); 097 if (!g.isONE()) { 098 facs.put(d, g); 099 f = f.divide(g); 100 } 101 } 102 if (!f.isONE()) { 103 d = f.degree(0); 104 facs.put(d, f); 105 } 106 return facs; 107 } 108 109 110 /** 111 * GenPolynomial base equal degree factorization. 112 * @param P squarefree and monic GenPolynomial. 113 * @param deg such that P has only irreducible factors of degree deg. 114 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 115 */ 116 public List<GenPolynomial<MOD>> baseEqualDegreeFactors(GenPolynomial<MOD> P, long deg) { 117 if (P == null) { 118 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 119 } 120 List<GenPolynomial<MOD>> facs = new ArrayList<GenPolynomial<MOD>>(); 121 if (P.isZERO()) { 122 return facs; 123 } 124 GenPolynomialRing<MOD> pfac = P.ring; 125 if (pfac.nvar > 1) { 126 throw new IllegalArgumentException( 127 this.getClass().getName() + " only for univariate polynomials"); 128 } 129 if (P.degree(0) == deg) { 130 facs.add(P); 131 return facs; 132 } 133 ModularRingFactory<MOD> mr = (ModularRingFactory<MOD>) pfac.coFac; 134 java.math.BigInteger m = mr.getIntegerModul().getVal(); 135 //System.out.println("m = " + m); 136 boolean p2 = false; 137 if (m.equals(java.math.BigInteger.valueOf(2L))) { 138 p2 = true; 139 //throw new RuntimeException(this.getClass().getName() + " case p = 2 not implemented"); 140 } 141 GenPolynomial<MOD> one = pfac.getONE(); 142 GenPolynomial<MOD> t = pfac.univariate(0, 1L); 143 GenPolynomial<MOD> r; 144 GenPolynomial<MOD> h; 145 GenPolynomial<MOD> f = P; 146 //GreatestCommonDivisor<MOD> engine = GCDFactory.<MOD> getImplementation(pfac.coFac); 147 Power<GenPolynomial<MOD>> pow = new Power<GenPolynomial<MOD>>(pfac); 148 GenPolynomial<MOD> g = null; 149 int degi = (int) deg; //f.degree(0); 150 //System.out.println("deg = " + deg); 151 BigInteger di = (new BigInteger(m)).power(deg); 152 //System.out.println("di = " + di); 153 java.math.BigInteger d = di.getVal(); //.longValue()-1; 154 //System.out.println("d = " + d); 155 d = d.shiftRight(1); // divide by 2 156 do { 157 if (p2) { 158 h = t; 159 for (int i = 1; i < degi; i++) { 160 h = t.sum(h.multiply(h)); 161 h = h.remainder(f); 162 } 163 t = t.multiply(pfac.univariate(0, 2L)); 164 //System.out.println("h = " + h); 165 } else { 166 r = pfac.random(17, degi, 2 * degi, 1.0f); 167 if (r.degree(0) >= f.degree(0)) { 168 r = r.remainder(f); 169 } 170 r = r.monic(); 171 //System.out.println("r = " + r); 172 h = pow.modPower(r, d, f).subtract(one); 173 degi++; 174 } 175 g = engine.gcd(h, f); 176 //System.out.println("g = " + g); 177 } while (g.degree(0) == 0 || g.degree(0) == f.degree(0)); 178 f = f.divide(g); 179 facs.addAll(baseEqualDegreeFactors(f, deg)); 180 facs.addAll(baseEqualDegreeFactors(g, deg)); 181 return facs; 182 } 183 184 185 /** 186 * GenPolynomial base factorization of a squarefree polynomial. 187 * @param P squarefree and monic! GenPolynomial. 188 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 189 */ 190 @Override 191 public List<GenPolynomial<MOD>> baseFactorsSquarefree(GenPolynomial<MOD> P) { 192 if (P == null) { 193 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 194 } 195 List<GenPolynomial<MOD>> factors = new ArrayList<GenPolynomial<MOD>>(); 196 if (P.isZERO()) { 197 return factors; 198 } 199 if (P.isONE()) { 200 factors.add(P); 201 return factors; 202 } 203 GenPolynomialRing<MOD> pfac = P.ring; 204 if (pfac.nvar > 1) { 205 throw new IllegalArgumentException( 206 this.getClass().getName() + " only for univariate polynomials"); 207 } 208 if (!P.leadingBaseCoefficient().isONE()) { 209 throw new IllegalArgumentException("ldcf(P) != 1: " + P); 210 } 211 SortedMap<Long, GenPolynomial<MOD>> dfacs = baseDistinctDegreeFactors(P); 212 if (debug) { 213 logger.info("dfacs = " + dfacs); 214 //System.out.println("dfacs = " + dfacs); 215 } 216 for (Map.Entry<Long, GenPolynomial<MOD>> me : dfacs.entrySet()) { 217 Long e = me.getKey(); 218 GenPolynomial<MOD> f = me.getValue(); // dfacs.get(e); 219 List<GenPolynomial<MOD>> efacs = baseEqualDegreeFactors(f, e); 220 if (debug) { 221 logger.info("efacs " + e + " = " + efacs); 222 //System.out.println("efacs " + e + " = " + efacs); 223 } 224 factors.addAll(efacs); 225 } 226 //System.out.println("factors = " + factors); 227 factors = PolyUtil.<MOD> monic(factors); 228 SortedSet<GenPolynomial<MOD>> ss = new TreeSet<GenPolynomial<MOD>>(factors); 229 //System.out.println("sorted = " + ss); 230 factors.clear(); 231 factors.addAll(ss); 232 return factors; 233 } 234 235}