001/* 002 * $Id: FactorInteger.java 5842 2018-05-21 13:23:49Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.BitSet; 010import java.util.Iterator; 011import java.util.List; 012import java.util.SortedMap; 013 014import org.apache.log4j.Logger; 015 016import edu.jas.arith.BigInteger; 017import edu.jas.arith.ModIntegerRing; 018import edu.jas.arith.ModLongRing; 019import edu.jas.arith.Modular; 020import edu.jas.arith.ModularRingFactory; 021import edu.jas.arith.PrimeInteger; 022import edu.jas.arith.PrimeList; 023import edu.jas.poly.ExpVector; 024import edu.jas.poly.GenPolynomial; 025import edu.jas.poly.GenPolynomialRing; 026import edu.jas.poly.OptimizedPolynomialList; 027import edu.jas.poly.PolyUtil; 028import edu.jas.poly.TermOrderOptimization; 029import edu.jas.structure.GcdRingElem; 030import edu.jas.structure.Power; 031import edu.jas.structure.RingElem; 032import edu.jas.structure.RingFactory; 033import edu.jas.util.KsubSet; 034 035 036/** 037 * Integer coefficients factorization algorithms. This class implements 038 * factorization methods for polynomials over integers. 039 * @param <MOD> 040 * @author Heinz Kredel 041 */ 042public class FactorInteger<MOD extends GcdRingElem<MOD> & Modular> extends FactorAbstract<BigInteger> { 043 044 045 private static final Logger logger = Logger.getLogger(FactorInteger.class); 046 047 048 private static final boolean debug = logger.isDebugEnabled(); 049 050 051 /** 052 * Factorization engine for modular base coefficients. 053 */ 054 protected final FactorAbstract<MOD> mfactor; 055 056 057 /** 058 * Gcd engine for modular base coefficients. 059 */ 060 protected final GreatestCommonDivisorAbstract<MOD> mengine; 061 062 063 /** 064 * No argument constructor. 065 */ 066 public FactorInteger() { 067 this(BigInteger.ONE); 068 } 069 070 071 /** 072 * Constructor. 073 * @param cfac coefficient ring factory. 074 */ 075 @SuppressWarnings("unchecked") 076 public FactorInteger(RingFactory<BigInteger> cfac) { 077 super(cfac); 078 ModularRingFactory<MOD> mcofac = (ModularRingFactory<MOD>) (Object) new ModLongRing(13, true); // hack 079 mfactor = FactorFactory.getImplementation(mcofac); //new FactorModular(mcofac); 080 mengine = GCDFactory.getImplementation(mcofac); 081 //mengine = GCDFactory.getProxy(mcofac); 082 } 083 084 085 /** 086 * GenPolynomial test if is irreducible. 087 * @param P GenPolynomial. 088 * @return true if P is irreducible, else false. 089 */ 090 @Override 091 public boolean isIrreducible(GenPolynomial<BigInteger> P) { 092 if (P.ring.nvar == 1) { 093 if (isIrreducibleEisenstein(P)) { 094 return true; 095 } // else unknown 096 } 097 return super.isIrreducible(P); 098 } 099 100 101 /** 102 * GenPolynomial test if is irreducible with Eisenstein criterion. 103 * @param P univariate polynomial. 104 * @return true if P is irreducible, else false if it is unknown. 105 */ 106 public boolean isIrreducibleEisenstein(GenPolynomial<BigInteger> P) { 107 if (P.ring.nvar != 1) { 108 throw new IllegalArgumentException("only for univariate polynomials"); 109 } 110 if (P.degree(0) <= 1L) { // linear or constant is irreducible 111 return true; 112 } 113 BigInteger rcont = engine.baseContent(P.reductum()); 114 if (rcont.isZERO() || rcont.isONE()) { // case x**n 115 return false; 116 } 117 // todo test 118 if (rcont.compareTo(BigInteger.valueOf(PrimeInteger.BETA)) >= 0) { // integer too big 119 return false; 120 } 121 long lcont = rcont.getVal().longValue(); 122 BigInteger lc = P.leadingBaseCoefficient().abs(); 123 BigInteger tc = P.trailingBaseCoefficient().abs(); 124 SortedMap<Long, Integer> fac = PrimeInteger.factors(lcont); 125 for (Long p : fac.keySet()) { 126 BigInteger pi = BigInteger.valueOf(p); 127 if (!lc.remainder(pi).isZERO() && !tc.remainder(pi.power(2)).isZERO()) { 128 logger.info("isIrreducibleEisenstein: fac = " + fac + ", lc = " + lc + ", tc = " + tc); 129 return true; 130 } 131 } 132 return false; 133 } 134 135 136 /** 137 * GenPolynomial base factorization of a squarefree polynomial. 138 * @param P squarefree and primitive! GenPolynomial. 139 * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. 140 */ 141 @SuppressWarnings("unchecked") 142 @Override 143 public List<GenPolynomial<BigInteger>> baseFactorsSquarefree(GenPolynomial<BigInteger> P) { 144 if (P == null) { 145 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 146 } 147 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(); 148 if (P.isZERO()) { 149 return factors; 150 } 151 if (P.isONE()) { 152 factors.add(P); 153 return factors; 154 } 155 GenPolynomialRing<BigInteger> pfac = P.ring; 156 if (pfac.nvar > 1) { 157 throw new IllegalArgumentException( 158 this.getClass().getName() + " only for univariate polynomials"); 159 } 160 if (!engine.baseContent(P).isONE()) { 161 throw new IllegalArgumentException(this.getClass().getName() + " P not primitive"); 162 } 163 if (P.degree(0) <= 1L) { // linear is irreducible 164 factors.add(P); 165 return normalizeFactorization(factors); 166 } 167 if (isIrreducibleEisenstein(P)) { 168 factors.add(P); 169 return normalizeFactorization(factors); 170 } 171 // check cyclotomic factorization 172 //if (CycloUtil.isCyclotomicPolynomial(P)) { 173 //System.out.println("isCyclotomicPolynomial = " + P); 174 factors = CycloUtil.cyclotomicFactors(P); 175 if (factors.size() > 0) { 176 logger.info("cyclotomicFactors: #factors = " + factors.size()); 177 return normalizeFactorization(factors); 178 } 179 //} 180 // compute norm 181 BigInteger an = P.maxNorm(); 182 BigInteger ac = P.leadingBaseCoefficient(); 183 //compute factor coefficient bounds 184 ExpVector degv = P.degreeVector(); 185 int degi = (int) P.degree(0); 186 BigInteger M = an.multiply(PolyUtil.factorBound(degv)); 187 M = M.multiply(ac.abs().multiply(ac.fromInteger(8))); 188 //System.out.println("M = " + M); 189 //M = M.multiply(M); // test 190 191 //initialize prime list and degree vector 192 PrimeList primes = new PrimeList(PrimeList.Range.small); 193 int pn = 30; //primes.size(); 194 ModularRingFactory<MOD> cofac = null; 195 GenPolynomial<MOD> am = null; 196 GenPolynomialRing<MOD> mfac = null; 197 int TT = 5; // 7 198 if (degi > 100) { 199 TT += 2; 200 } 201 List<GenPolynomial<MOD>>[] modfac = new List[TT]; 202 List<GenPolynomial<BigInteger>>[] intfac = new List[TT]; 203 BigInteger[] plist = new BigInteger[TT]; 204 List<GenPolynomial<MOD>> mlist = null; 205 List<GenPolynomial<BigInteger>> ilist = null; 206 int i = 0; 207 if (debug) { 208 logger.debug("an = " + an); 209 logger.debug("ac = " + ac); 210 logger.debug("M = " + M); 211 logger.info("degv = " + degv); 212 } 213 Iterator<java.math.BigInteger> pit = primes.iterator(); 214 pit.next(); // skip p = 2 215 pit.next(); // skip p = 3 216 MOD nf = null; 217 for (int k = 0; k < TT; k++) { 218 if (k == TT - 1) { // -2 219 primes = new PrimeList(PrimeList.Range.medium); 220 pit = primes.iterator(); 221 } 222 //if (k == TT + 1) { // -1 223 // primes = new PrimeList(PrimeList.Range.large); 224 // pit = primes.iterator(); 225 //} 226 while (pit.hasNext()) { 227 java.math.BigInteger p = pit.next(); 228 //System.out.println("next run ++++++++++++++++++++++++++++++++++"); 229 if (++i >= pn) { 230 logger.error("prime list exhausted, pn = " + pn); 231 throw new ArithmeticException("prime list exhausted"); 232 } 233 if (ModLongRing.MAX_LONG.compareTo(p) > 0) { 234 cofac = (ModularRingFactory) new ModLongRing(p, true); 235 } else { 236 cofac = (ModularRingFactory) new ModIntegerRing(p, true); 237 } 238 logger.info("prime = " + cofac); 239 nf = cofac.fromInteger(ac.getVal()); 240 if (nf.isZERO()) { 241 logger.info("unlucky prime (nf) = " + p); 242 continue; 243 } 244 // initialize polynomial factory and map polynomial 245 mfac = new GenPolynomialRing<MOD>(cofac, pfac); 246 am = PolyUtil.<MOD> fromIntegerCoefficients(mfac, P); 247 if (!am.degreeVector().equals(degv)) { // allways true 248 logger.info("unlucky prime (deg) = " + p); 249 continue; 250 } 251 GenPolynomial<MOD> ap = PolyUtil.<MOD> baseDeriviative(am); 252 if (ap.isZERO()) { 253 logger.info("unlucky prime (a')= " + p); 254 continue; 255 } 256 GenPolynomial<MOD> g = mengine.baseGcd(am, ap); 257 if (g.isONE()) { 258 logger.info("**lucky prime = " + p); 259 break; 260 } 261 } 262 // now am is squarefree mod p, make monic and factor mod p 263 if (!nf.isONE()) { 264 //System.out.println("nf = " + nf); 265 am = am.divide(nf); // make monic 266 } 267 mlist = mfactor.baseFactorsSquarefree(am); 268 if (logger.isInfoEnabled()) { 269 logger.info("modlist = " + mlist); 270 } 271 if (mlist.size() <= 1) { 272 factors.add(P); 273 return factors; 274 } 275 if (!nf.isONE()) { 276 GenPolynomial<MOD> mp = mfac.getONE(); //mlist.get(0); 277 //System.out.println("mp = " + mp); 278 mp = mp.multiply(nf); 279 //System.out.println("mp = " + mp); 280 mlist.add(0, mp); // set(0,mp); 281 } 282 modfac[k] = mlist; 283 plist[k] = cofac.getIntegerModul(); // p 284 } 285 286 // search shortest factor list 287 int min = Integer.MAX_VALUE; 288 BitSet AD = null; 289 for (int k = 0; k < TT; k++) { 290 List<ExpVector> ev = PolyUtil.<MOD> leadingExpVector(modfac[k]); 291 BitSet D = factorDegrees(ev, degi); 292 if (AD == null) { 293 AD = D; 294 } else { 295 AD.and(D); 296 } 297 int s = modfac[k].size(); 298 logger.info("mod(" + plist[k] + ") #s = " + s + ", D = " + D /*+ ", lt = " + ev*/); 299 //System.out.println("mod s = " + s); 300 if (s < min) { 301 min = s; 302 mlist = modfac[k]; 303 } 304 } 305 logger.info("min = " + min + ", AD = " + AD); 306 if (mlist.size() <= 1) { 307 logger.info("mlist.size() = 1"); 308 factors.add(P); 309 return factors; 310 } 311 if (AD.cardinality() <= 2) { // only one possible factor 312 logger.info("degree set cardinality = " + AD.cardinality()); 313 factors.add(P); 314 return factors; 315 } 316 317 final boolean allLists = false; //true; //false; 318 if (allLists) { 319 // try each factor list 320 for (int k = 0; k < TT; k++) { 321 mlist = modfac[k]; 322 if (debug) { 323 logger.info("lifting from " + mlist); 324 } 325 if (P.leadingBaseCoefficient().isONE()) { // monic case 326 factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases 327 if (factors.size() == 1) { 328 factors = searchFactorsNonMonic(P, M, mlist, AD); 329 } 330 } else { 331 factors = searchFactorsNonMonic(P, M, mlist, AD); 332 } 333 intfac[k] = factors; 334 } 335 } else { 336 // try only shortest factor list 337 if (debug) { 338 logger.info("lifting shortest from " + mlist); 339 } 340 if (P.leadingBaseCoefficient().isONE()) { 341 long t = System.currentTimeMillis(); 342 try { 343 mlist = PolyUtil.<MOD> monic(mlist); 344 factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases 345 t = System.currentTimeMillis() - t; 346 //System.out.println("monic time = " + t); 347 intfac[0] = factors; 348 if (debug) { 349 t = System.currentTimeMillis(); 350 List<GenPolynomial<BigInteger>> fnm = searchFactorsNonMonic(P, M, mlist, AD); 351 t = System.currentTimeMillis() - t; 352 System.out.println("non monic time = " + t); 353 if (!factors.equals(fnm)) { 354 System.out.println("monic factors = " + intfac[0]); //factors); 355 System.out.println("non monic factors = " + fnm); 356 } 357 } 358 } catch (RuntimeException e) { 359 t = System.currentTimeMillis(); 360 factors = searchFactorsNonMonic(P, M, mlist, AD); 361 t = System.currentTimeMillis() - t; 362 //System.out.println("only non monic time = " + t); 363 } 364 } else { 365 long t = System.currentTimeMillis(); 366 factors = searchFactorsNonMonic(P, M, mlist, AD); 367 t = System.currentTimeMillis() - t; 368 //System.out.println("non monic time = " + t); 369 } 370 return normalizeFactorization(factors); 371 } 372 373 // search longest factor list 374 int max = 0; 375 for (int k = 0; k < TT; k++) { 376 int s = intfac[k].size(); 377 logger.info("int s = " + s); 378 if (s > max) { 379 max = s; 380 ilist = intfac[k]; 381 } 382 } 383 factors = normalizeFactorization(ilist); 384 return factors; 385 } 386 387 388 /** 389 * BitSet for factor degree list. 390 * @param E exponent vector list. 391 * @return b_0,...,b_k} a BitSet of possible factor degrees. 392 */ 393 public BitSet factorDegrees(List<ExpVector> E, int deg) { 394 BitSet D = new BitSet(deg + 1); 395 D.set(0); // constant factor 396 for (ExpVector e : E) { 397 int i = (int) e.getVal(0); 398 BitSet s = new BitSet(deg + 1); 399 for (int k = 0; k < deg + 1 - i; k++) { // shift by i places 400 s.set(i + k, D.get(k)); 401 } 402 //System.out.println("s = " + s); 403 D.or(s); 404 //System.out.println("D = " + D); 405 } 406 return D; 407 } 408 409 410 /** 411 * Sum of all degrees. 412 * @param L univariate polynomial list. 413 * @return sum deg(p) for p in L. 414 */ 415 public static <C extends RingElem<C>> long degreeSum(List<GenPolynomial<C>> L) { 416 long s = 0L; 417 for (GenPolynomial<C> p : L) { 418 ExpVector e = p.leadingExpVector(); 419 long d = e.getVal(0); 420 s += d; 421 } 422 return s; 423 } 424 425 426 /** 427 * Factor search with modular Hensel lifting algorithm. Let p = 428 * f_i.ring.coFac.modul() i = 0, ..., n-1 and assume C == prod_{0,...,n-1} 429 * f_i mod p with ggt(f_i,f_j) == 1 mod p for i != j 430 * @param C GenPolynomial. 431 * @param M bound on the coefficients of g_i as factors of C. 432 * @param F = [f_0,...,f_{n-1}] List<GenPolynomial>. 433 * @param D bit set of possible factor degrees. 434 * @return [g_0,...,g_{n-1}] = lift(C,F), with C = prod_{0,...,n-1} g_i mod 435 * p**e. <b>Note:</b> does not work in all cases. 436 */ 437 List<GenPolynomial<BigInteger>> searchFactorsMonic(GenPolynomial<BigInteger> C, BigInteger M, 438 List<GenPolynomial<MOD>> F, BitSet D) { 439 //System.out.println("*** monic factor combination ***"); 440 if (C == null || C.isZERO() || F == null || F.size() == 0) { 441 throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); 442 } 443 GenPolynomialRing<BigInteger> pfac = C.ring; 444 if (pfac.nvar != 1) { // assert ? 445 throw new IllegalArgumentException("polynomial ring not univariate"); 446 } 447 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 448 List<GenPolynomial<MOD>> mlist = F; 449 List<GenPolynomial<MOD>> lift; 450 451 //MOD nf = null; 452 GenPolynomial<MOD> ct = mlist.get(0); 453 if (ct.isConstant()) { 454 //nf = ct.leadingBaseCoefficient(); 455 mlist.remove(ct); 456 //System.out.println("=== nf = " + nf); 457 if (mlist.size() <= 1) { 458 factors.add(C); 459 return factors; 460 } 461 } else { 462 //nf = ct.ring.coFac.getONE(); 463 } 464 //System.out.println("modlist = " + mlist); // includes not ldcf 465 ModularRingFactory<MOD> mcfac = (ModularRingFactory<MOD>) ct.ring.coFac; 466 BigInteger m = mcfac.getIntegerModul(); 467 long k = 1; 468 BigInteger pi = m; 469 while (pi.compareTo(M) < 0) { 470 k++; 471 pi = pi.multiply(m); 472 } 473 logger.info("p^k = " + m + "^" + k); 474 GenPolynomial<BigInteger> PP = C, P = C; 475 // lift via Hensel 476 try { 477 lift = HenselUtil.<MOD> liftHenselMonic(PP, mlist, k); 478 //System.out.println("lift = " + lift); 479 } catch (NoLiftingException e) { 480 throw new RuntimeException(e); 481 } 482 if (logger.isInfoEnabled()) { 483 logger.info("lifted modlist = " + lift); 484 } 485 GenPolynomialRing<MOD> mpfac = lift.get(0).ring; 486 487 // combine trial factors 488 int dl = (lift.size() + 1) / 2; 489 //System.out.println("dl = " + dl); 490 GenPolynomial<BigInteger> u = PP; 491 long deg = (u.degree(0) + 1L) / 2L; 492 //System.out.println("deg = " + deg); 493 //BigInteger ldcf = u.leadingBaseCoefficient(); 494 //System.out.println("ldcf = " + ldcf); 495 for (int j = 1; j <= dl; j++) { 496 //System.out.println("j = " + j + ", dl = " + dl + ", lift = " + lift); 497 KsubSet<GenPolynomial<MOD>> ps = new KsubSet<GenPolynomial<MOD>>(lift, j); 498 for (List<GenPolynomial<MOD>> flist : ps) { 499 //System.out.println("degreeSum = " + degreeSum(flist)); 500 if (!D.get((int) FactorInteger.<MOD> degreeSum(flist))) { 501 logger.info("skipped by degree set " + D + ", deg = " + degreeSum(flist)); 502 continue; 503 } 504 GenPolynomial<MOD> mtrial = Power.<GenPolynomial<MOD>> multiply(mpfac, flist); 505 //GenPolynomial<MOD> mtrial = mpfac.getONE(); 506 //for (int kk = 0; kk < flist.size(); kk++) { 507 // GenPolynomial<MOD> fk = flist.get(kk); 508 // mtrial = mtrial.multiply(fk); 509 //} 510 //System.out.println("+flist = " + flist + ", mtrial = " + mtrial); 511 if (mtrial.degree(0) > deg) { // this test is sometimes wrong 512 logger.info("degree " + mtrial.degree(0) + " > deg " + deg); 513 //continue; 514 } 515 //System.out.println("+flist = " + flist); 516 GenPolynomial<BigInteger> trial = PolyUtil.integerFromModularCoefficients(pfac, mtrial); 517 //System.out.println("+trial = " + trial); 518 //trial = engine.basePrimitivePart( trial.multiply(ldcf) ); 519 trial = engine.basePrimitivePart(trial); 520 //System.out.println("pp(trial)= " + trial); 521 if (PolyUtil.<BigInteger> baseSparsePseudoRemainder(u, trial).isZERO()) { 522 logger.info("successful trial = " + trial); 523 //System.out.println("trial = " + trial); 524 //System.out.println("flist = " + flist); 525 //trial = engine.basePrimitivePart(trial); 526 //System.out.println("pp(trial)= " + trial); 527 factors.add(trial); 528 u = PolyUtil.<BigInteger> basePseudoDivide(u, trial); //u.divide( trial ); 529 //System.out.println("u = " + u); 530 //if (lift.removeAll(flist)) { 531 lift = removeOnce(lift, flist); 532 logger.info("new lift= " + lift); 533 dl = (lift.size() + 1) / 2; 534 //System.out.println("dl = " + dl); 535 j = 0; // since j++ 536 break; 537 //} logger.error("error removing flist from lift = " + lift); 538 } 539 } 540 } 541 if (!u.isONE() && !u.equals(P)) { 542 logger.info("rest u = " + u); 543 //System.out.println("rest u = " + u); 544 factors.add(u); 545 } 546 if (factors.size() == 0) { 547 logger.info("irred u = " + u); 548 //System.out.println("irred u = " + u); 549 factors.add(PP); 550 } 551 return normalizeFactorization(factors); 552 } 553 554 555 /** 556 * Factor search with modular Hensel lifting algorithm. Let p = 557 * f_i.ring.coFac.modul() i = 0, ..., n-1 and assume C == prod_{0,...,n-1} 558 * f_i mod p with ggt(f_i,f_j) == 1 mod p for i != j 559 * @param C GenPolynomial. 560 * @param M bound on the coefficients of g_i as factors of C. 561 * @param F = [f_0,...,f_{n-1}] List<GenPolynomial>. 562 * @param D bit set of possible factor degrees. 563 * @return [g_0,...,g_{n-1}] = lift(C,F), with C = prod_{0,...,n-1} g_i mod 564 * p**e. 565 */ 566 List<GenPolynomial<BigInteger>> searchFactorsNonMonic(GenPolynomial<BigInteger> C, BigInteger M, 567 List<GenPolynomial<MOD>> F, BitSet D) { 568 //System.out.println("*** non monic factor combination ***"); 569 if (C == null || C.isZERO() || F == null || F.size() == 0) { 570 throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); 571 } 572 GenPolynomialRing<BigInteger> pfac = C.ring; 573 if (pfac.nvar != 1) { // assert ? 574 throw new IllegalArgumentException("polynomial ring not univariate"); 575 } 576 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 577 List<GenPolynomial<MOD>> mlist = F; 578 579 MOD nf = null; 580 GenPolynomial<MOD> ct = mlist.get(0); 581 if (ct.isConstant()) { 582 nf = ct.leadingBaseCoefficient(); 583 mlist.remove(ct); 584 //System.out.println("=== nf = " + nf); 585 //System.out.println("=== ldcf = " + C.leadingBaseCoefficient()); 586 if (mlist.size() <= 1) { 587 factors.add(C); 588 return factors; 589 } 590 } else { 591 nf = ct.ring.coFac.getONE(); 592 } 593 //System.out.println("modlist = " + mlist); // includes not ldcf 594 GenPolynomialRing<MOD> mfac = ct.ring; 595 GenPolynomial<MOD> Pm = PolyUtil.<MOD> fromIntegerCoefficients(mfac, C); 596 GenPolynomial<BigInteger> PP = C, P = C; 597 598 // combine trial factors 599 int dl = (mlist.size() + 1) / 2; 600 GenPolynomial<BigInteger> u = PP; 601 long deg = (u.degree(0) + 1L) / 2L; 602 GenPolynomial<MOD> um = Pm; 603 //BigInteger ldcf = u.leadingBaseCoefficient(); 604 //System.out.println("ldcf = " + ldcf); 605 HenselApprox<MOD> ilist = null; 606 for (int j = 1; j <= dl; j++) { 607 //System.out.println("j = " + j + ", dl = " + dl + ", ilist = " + ilist); 608 KsubSet<GenPolynomial<MOD>> ps = new KsubSet<GenPolynomial<MOD>>(mlist, j); 609 for (List<GenPolynomial<MOD>> flist : ps) { 610 //System.out.println("degreeSum = " + degreeSum(flist)); 611 if (!D.get((int) FactorInteger.<MOD> degreeSum(flist))) { 612 logger.info("skipped by degree set " + D + ", deg = " + degreeSum(flist)); 613 continue; 614 } 615 GenPolynomial<MOD> trial = mfac.getONE().multiply(nf); 616 for (int kk = 0; kk < flist.size(); kk++) { 617 GenPolynomial<MOD> fk = flist.get(kk); 618 trial = trial.multiply(fk); 619 } 620 if (trial.degree(0) > deg) { // this test is sometimes wrong 621 logger.info("degree > deg " + deg + ", degree = " + trial.degree(0)); 622 //continue; 623 } 624 GenPolynomial<MOD> cofactor = um.divide(trial); 625 //System.out.println("trial = " + trial); 626 //System.out.println("cofactor = " + cofactor); 627 628 // lift via Hensel 629 try { 630 // ilist = HenselUtil.liftHenselQuadraticFac(PP, M, trial, cofactor); 631 ilist = HenselUtil.<MOD> liftHenselQuadratic(PP, M, trial, cofactor); 632 //ilist = HenselUtil.<MOD> liftHensel(PP, M, trial, cofactor); 633 } catch (NoLiftingException e) { 634 // no liftable factors 635 if ( /*debug*/logger.isDebugEnabled()) { 636 logger.info("no liftable factors " + e); 637 //e.printStackTrace(); 638 } 639 continue; 640 } 641 GenPolynomial<BigInteger> itrial = ilist.A; 642 GenPolynomial<BigInteger> icofactor = ilist.B; 643 if (logger.isDebugEnabled()) { 644 logger.info(" modlist = " + trial + ", cofactor " + cofactor); 645 logger.info("lifted intlist = " + itrial + ", cofactor " + icofactor); 646 } 647 //System.out.println("lifted intlist = " + itrial + ", cofactor " + icofactor); 648 649 itrial = engine.basePrimitivePart(itrial); 650 //System.out.println("pp(trial)= " + itrial); 651 if (PolyUtil.<BigInteger> baseSparsePseudoRemainder(u, itrial).isZERO()) { 652 logger.info("successful trial = " + itrial); 653 //System.out.println("trial = " + itrial); 654 //System.out.println("cofactor = " + icofactor); 655 //System.out.println("flist = " + flist); 656 //itrial = engine.basePrimitivePart(itrial); 657 //System.out.println("pp(itrial)= " + itrial); 658 factors.add(itrial); 659 //u = PolyUtil.<BigInteger> basePseudoDivide(u, itrial); //u.divide( trial ); 660 u = icofactor; 661 PP = u; // fixed finally on 2009-05-03 662 um = cofactor; 663 //System.out.println("u = " + u); 664 //System.out.println("um = " + um); 665 //if (mlist.removeAll(flist)) { 666 mlist = removeOnce(mlist, flist); 667 logger.info("new mlist= " + mlist); 668 dl = (mlist.size() + 1) / 2; 669 j = 0; // since j++ 670 break; 671 //} logger.error("error removing flist from ilist = " + mlist); 672 } 673 } 674 } 675 if (!u.isONE() && !u.equals(P)) { 676 logger.info("rest u = " + u); 677 factors.add(u); 678 } 679 if (factors.size() == 0) { 680 logger.info("irred u = " + PP); 681 factors.add(PP); 682 } 683 return normalizeFactorization(factors); 684 } 685 686 687 /** 688 * GenPolynomial factorization of a multivariate squarefree polynomial, 689 * using Hensel lifting if possible. 690 * @param P squarefree and primitive! (respectively monic) multivariate 691 * GenPolynomial over the integers. 692 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 693 */ 694 @Override 695 public List<GenPolynomial<BigInteger>> factorsSquarefree(GenPolynomial<BigInteger> P) { 696 GenPolynomialRing<BigInteger> pfac = P.ring; 697 if (pfac.nvar <= 1) { 698 return baseFactorsSquarefree(P); 699 } 700 OptimizedPolynomialList<BigInteger> opt = null; 701 List<Integer> iperm = null; 702 final boolean USE_OPT = true; 703 if (USE_OPT) { 704 List<GenPolynomial<BigInteger>> topt = new ArrayList<GenPolynomial<BigInteger>>(1); 705 topt.add(P); 706 opt = TermOrderOptimization.<BigInteger> optimizeTermOrder(pfac,topt); 707 P = opt.list.get(0); 708 logger.info("optimized polynomial: " + P); 709 iperm = TermOrderOptimization.inversePermutation(opt.perm); 710 logger.warn("optimized ring: " + opt.ring + ", original ring: " + pfac); 711 } 712 ExpVector degv = P.degreeVector(); 713 int[] donv = degv.dependencyOnVariables(); 714 List<GenPolynomial<BigInteger>> facs = null; 715 if (degv.length() == donv.length) { // all variables appear, hack for Hensel, check 716 try { 717 logger.info("try factorsSquarefreeHensel: " + P); 718 facs = factorsSquarefreeHensel(P); 719 } catch (Exception e) { 720 logger.info("exception " + e); 721 //e.printStackTrace(); 722 } 723 } else { // not all variables appear, remove unused variables, hack for Hensel, check 724 GenPolynomial<BigInteger> pu = PolyUtil.<BigInteger> removeUnusedUpperVariables(P); 725 GenPolynomial<BigInteger> pl = PolyUtil.<BigInteger> removeUnusedLowerVariables(pu); // not useful 726 try { 727 logger.info("try factorsSquarefreeHensel: " + pl); 728 facs = factorsSquarefreeHensel(pu); 729 List<GenPolynomial<BigInteger>> fs = new ArrayList<GenPolynomial<BigInteger>>(facs.size()); 730 GenPolynomialRing<BigInteger> pf = P.ring; 731 GenPolynomialRing<BigInteger> pfu = pu.ring; 732 for (GenPolynomial<BigInteger> p : facs) { 733 GenPolynomial<BigInteger> pel = p.extendLower(pfu, 0, 0L); 734 GenPolynomial<BigInteger> pe = pel.extend(pf, 0, 0L); 735 fs.add(pe); 736 } 737 //System.out.println("fs = " + fs); 738 facs = fs; 739 } catch (Exception e) { 740 logger.info("exception " + e); 741 //e.printStackTrace(); 742 } 743 } 744 if (facs == null) { 745 logger.warn("factorsSquarefreeHensel not applicable or failed, reverting to Kronecker for: " + P); 746 facs = super.factorsSquarefree(P); 747 } 748 if (USE_OPT) { 749 facs = TermOrderOptimization.<BigInteger> permutation(iperm, pfac, facs); 750 logger.info("de-optimized polynomials: " + facs); 751 } 752 facs = normalizeFactorization(facs); 753 return facs; 754 } 755 756 757 /** 758 * GenPolynomial factorization of a multivariate squarefree polynomial, 759 * using Hensel lifting. 760 * @param P squarefree and primitive! (respectively monic) multivariate 761 * GenPolynomial over the integers. 762 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 763 */ 764 @SuppressWarnings("unchecked") 765 public List<GenPolynomial<BigInteger>> factorsSquarefreeHensel(GenPolynomial<BigInteger> P) { 766 if (P == null) { 767 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 768 } 769 GenPolynomialRing<BigInteger> pfac = P.ring; 770 if (pfac.nvar == 1) { 771 return baseFactorsSquarefree(P); 772 } 773 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(); 774 if (P.isZERO()) { 775 return factors; 776 } 777 if (P.degreeVector().totalDeg() <= 1L) { 778 factors.add(P); 779 return factors; 780 } 781 GenPolynomial<BigInteger> pd = P; 782 //System.out.println("pd = " + pd); 783 // ldcf(pd) 784 BigInteger ac = pd.leadingBaseCoefficient(); 785 786 // factor leading coefficient as polynomial in the lowest! variable 787 GenPolynomialRing<GenPolynomial<BigInteger>> rnfac = pfac.recursive(pfac.nvar - 1); 788 GenPolynomial<GenPolynomial<BigInteger>> pr = PolyUtil.<BigInteger> recursive(rnfac, pd); 789 GenPolynomial<GenPolynomial<BigInteger>> prr = PolyUtil.<BigInteger> switchVariables(pr); 790 791 GenPolynomial<BigInteger> prrc = engine.recursiveContent(prr); // can have content wrt this variable 792 List<GenPolynomial<BigInteger>> cfactors = null; 793 if (!prrc.isONE()) { 794 prr = PolyUtil.<BigInteger> recursiveDivide(prr, prrc); 795 GenPolynomial<BigInteger> prrcu = prrc.extendLower(pfac, 0, 0L); // since switched vars 796 pd = PolyUtil.<BigInteger> basePseudoDivide(pd, prrcu); 797 logger.info("recursive content = " + prrc + ", new P = " + pd); 798 cfactors = factorsSquarefree(prrc); 799 List<GenPolynomial<BigInteger>> cff = new ArrayList<GenPolynomial<BigInteger>>(cfactors.size()); 800 for (GenPolynomial<BigInteger> fs : cfactors) { 801 GenPolynomial<BigInteger> fsp = fs.extendLower(pfac, 0, 0L); // since switched vars 802 cff.add(fsp); 803 } 804 cfactors = cff; 805 logger.info("cfactors = " + cfactors); 806 } 807 GenPolynomial<BigInteger> lprr = prr.leadingBaseCoefficient(); 808 //System.out.println("prr = " + prr); 809 logger.info("leading coeffcient = " + lprr); 810 boolean isMonic = false; // multivariate monic 811 if (lprr.isConstant()) { // isONE ? 812 isMonic = true; 813 } 814 SortedMap<GenPolynomial<BigInteger>, Long> lfactors = factors(lprr); 815 //System.out.println("lfactors = " + lfactors); 816 List<GenPolynomial<BigInteger>> lfacs = new ArrayList<GenPolynomial<BigInteger>>(lfactors.keySet()); 817 logger.info("leading coefficient factors = " + lfacs); 818 819 // search evaluation point and evaluate 820 GenPolynomialRing<BigInteger> cpfac = pfac; 821 GenPolynomial<BigInteger> pe = pd; 822 GenPolynomial<BigInteger> pep; 823 GenPolynomialRing<BigInteger> ccpfac = lprr.ring; 824 List<GenPolynomial<BigInteger>> ce = lfacs; 825 List<GenPolynomial<BigInteger>> cep = null; 826 List<BigInteger> cei = null; 827 List<BigInteger> dei = new ArrayList<BigInteger>(); 828 BigInteger pec = null; 829 BigInteger pecw = null; 830 BigInteger ped = null; 831 832 List<GenPolynomial<BigInteger>> ufactors = null; 833 List<TrialParts> tParts = new ArrayList<TrialParts>(); 834 List<GenPolynomial<BigInteger>> lf = null; 835 GenPolynomial<BigInteger> lpx = null; 836 List<GenPolynomial<BigInteger>> ln = null; 837 List<GenPolynomial<BigInteger>> un = null; 838 GenPolynomial<BigInteger> pes = null; 839 840 List<BigInteger> V = null; 841 long evStart = 0L; //3L * 5L; 842 List<Long> Evs = new ArrayList<Long>(pfac.nvar + 1); // Evs(0), Evs(1) unused 843 for (int j = 0; j <= pfac.nvar; j++) { 844 Evs.add(evStart); 845 } 846 final int trials = 4; 847 int countSeparate = 0; 848 final int COUNT_MAX = 50; 849 double ran = 1.001; // higher values not good 850 boolean isPrimitive = true; 851 boolean notLucky = true; 852 while (notLucky) { // for Wang's test 853 if (Math.abs(evStart) > 371L) { 854 logger.warn("no evaluation point for: P = " + P + ", lprr = " + lprr + ", lfacs = " 855 + lfacs); 856 throw new RuntimeException( 857 "no evaluation point found after " + Math.abs(evStart) + " iterations"); 858 } 859 if (Math.abs(evStart) % 100L <= 3L) { 860 ran = ran * (Math.PI - 2.14); 861 } 862 //System.out.println("-------------------------------------------- Evs = " + Evs); 863 notLucky = false; 864 V = new ArrayList<BigInteger>(); 865 cpfac = pfac; 866 pe = pd; 867 ccpfac = lprr.ring; 868 ce = lfacs; 869 cep = null; 870 cei = null; 871 pec = null; 872 ped = null; 873 long vi = 0L; 874 for (int j = pfac.nvar; j > 1; j--) { 875 // evaluation up to univariate case 876 long degp = pe.degree(cpfac.nvar - 2); 877 cpfac = cpfac.contract(1); 878 ccpfac = ccpfac.contract(1); 879 //vi = evStart; // + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p 880 vi = Evs.get(j); //evStart + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p 881 BigInteger Vi; 882 883 // search evaluation point 884 boolean doIt = true; 885 Vi = null; 886 pep = null; 887 while (doIt) { 888 logger.info("vi(" + j + ") = " + vi); 889 Vi = new BigInteger(vi); 890 pep = PolyUtil.<BigInteger> evaluateMain(cpfac, pe, Vi); 891 //System.out.println("pep = " + pep); 892 // check lucky evaluation point 893 if (degp == pep.degree(cpfac.nvar - 1)) { 894 logger.info("pep = " + pep); 895 //System.out.println("deg(pe) = " + degp + ", deg(pep) = " + pep.degree(cpfac.nvar-1)); 896 // check squarefree 897 if (sengine.isSquarefree(pep)) { // cpfac.nvar == 1 && ?? no, must test on each variable 898 //if ( isNearlySquarefree(pep) ) { 899 //System.out.println("squarefeee(pep)"); // + pep); 900 doIt = false; //break; 901 } else { 902 logger.info("pep not squarefree "); 903 } 904 } 905 if (vi > 0L) { 906 vi = -vi; 907 } else { 908 vi = 1L - vi; 909 } 910 } 911 //if ( !isMonic ) { 912 if (ccpfac.nvar >= 1) { 913 cep = PolyUtil.<BigInteger> evaluateMain(ccpfac, ce, Vi); 914 } else { 915 cei = PolyUtil.<BigInteger> evaluateMain(ccpfac.coFac, ce, Vi); 916 } 917 //} 918 int jj = (int) Math.round(ran + 0.52 * Math.random()); // j, random increment 919 //jj = 0; // ...4 test 920 //System.out.println("minimal jj = " + jj + ", vi " + vi); 921 if (vi > 0L) { 922 Evs.set(j, vi + jj); // record last tested value plus increment 923 evStart = vi + jj; 924 } else { 925 Evs.set(j, vi - jj); // record last tested value minus increment 926 evStart = vi - jj; 927 } 928 //evStart = vi+1L; 929 V.add(Vi); 930 pe = pep; 931 ce = cep; 932 } 933 //System.out.println("ce = " + ce + ", pe = " + pe); 934 pecw = engine.baseContent(pe); // original Wang 935 isPrimitive = pecw.isONE(); 936 ped = ccpfac.coFac.getONE(); 937 pec = pe.ring.coFac.getONE(); 938 //System.out.println("cei = " + cei + ", pecw = " + pecw); 939 if (!isMonic) { 940 if (countSeparate > COUNT_MAX) { 941 pec = pe.ring.coFac.getONE(); // hack is sometimes better 942 } else { 943 pec = pecw; 944 } 945 //pec = pecw; 946 //System.out.println("cei = " + cei + ", pec = " + pec + ", pe = " + pe); 947 if (lfacs.get(0).isConstant()) { 948 ped = cei.remove(0); 949 //lfacs.remove(0); // later 950 } 951 //System.out.println("lfacs = " + lfacs + ", cei = " + cei + ", ped = " + ped + ", pecw = " + pecw); 952 // test Wang's condition 953 dei = new ArrayList<BigInteger>(); 954 dei.add(pec.multiply(ped).abs()); // .abs() 955 int i = 1; 956 for (BigInteger ci : cei) { 957 if (ci.isZERO()) { 958 logger.info("condition (0) not met for cei = " + cei); // + ", dei = " + dei); 959 notLucky = true; 960 break; 961 } 962 BigInteger q = ci.abs(); 963 //System.out.println("q = " + q); 964 for (int ii = i - 1; ii >= 0; ii--) { 965 BigInteger r = dei.get(ii); 966 //System.out.println("r = " + r); 967 while (!r.isONE()) { 968 r = r.gcd(q); 969 q = q.divide(r); 970 //System.out.println("r = " + r + ", q = " + q); 971 } 972 } 973 dei.add(q); 974 if (q.isONE()) { 975 logger.info("condition (1) not met for dei = " + dei + ", cei = " + cei); 976 if (!testSeparate(cei, pecw)) { 977 countSeparate++; 978 if (countSeparate > COUNT_MAX) { 979 logger.info("too many inseparable evaluation points: " + countSeparate 980 + ", removing " + pecw); 981 } 982 } 983 notLucky = true; 984 break; 985 } 986 i++; 987 } 988 //System.out.println("dei = " + dei); 989 } 990 if (notLucky) { 991 continue; 992 } 993 logger.info("evaluation points = " + V + ", dei = " + dei); 994 //System.out.println("Evs = " + Evs); 995 logger.info("univariate polynomial = " + pe + ", pecw = " + pecw); 996 //pe = pe.abs(); 997 //ufactors = baseFactorsRadical(pe); //baseFactorsSquarefree(pe); wrong since not primitive 998 ufactors = baseFactorsSquarefree(pe.divide(pecw)); //wrong if not primitive 999 if (!pecw.isONE()) { 1000 ufactors.add(0, cpfac.getONE().multiply(pecw)); 1001 } 1002 if (ufactors.size() <= 1) { 1003 logger.info("irreducible univariate polynomial"); 1004 factors.add(pd); // P 1005 if (cfactors != null) { 1006 cfactors.addAll(factors); 1007 factors = cfactors; 1008 } 1009 return factors; 1010 } 1011 logger.info("univariate factors = " + ufactors); // + ", of " + pe); 1012 //System.out.println("lfacs = " + lfacs); 1013 //System.out.println("cei = " + cei); 1014 //System.out.println("pecw = " + pecw); 1015 1016 // determine leading coefficient polynomials for factors 1017 lf = new ArrayList<GenPolynomial<BigInteger>>(); 1018 lpx = lprr.ring.getONE(); 1019 for (int i = 0; i < ufactors.size(); i++) { 1020 lf.add(lprr.ring.getONE()); 1021 } 1022 //System.out.println("lf = " + lf); 1023 if (!isMonic || !pecw.isONE()) { 1024 if (lfacs.size() > 0 && lfacs.get(0).isConstant()) { 1025 //GenPolynomial<BigInteger> unused = 1026 lfacs.remove(0); 1027 //BigInteger xxi = xx.leadingBaseCoefficient(); 1028 //System.out.println("xx = " + xx + " == ped = " +ped); 1029 } 1030 for (int i = ufactors.size() - 1; i >= 0; i--) { 1031 GenPolynomial<BigInteger> pp = ufactors.get(i); 1032 BigInteger ppl = pp.leadingBaseCoefficient(); 1033 //System.out.println("ppl = " + ppl + ", pp = " + pp); 1034 ppl = ppl.multiply(pec); // content 1035 GenPolynomial<BigInteger> lfp = lf.get(i); 1036 int ii = 0; 1037 for (BigInteger ci : cei) { 1038 //System.out.println("ci = " + ci + ", lfp = " + lfp + ", lfacs.get(ii) = " + lfacs.get(ii)); 1039 if (ci.abs().isONE()) { 1040 System.out.println("ppl = " + ppl + ", ci = " + ci + ", lfp = " + lfp 1041 + ", lfacs.get(ii) = " + lfacs.get(ii)); 1042 notLucky = true; 1043 throw new RuntimeException("something is wrong, ci is a unit"); 1044 } 1045 while (ppl.remainder(ci).isZERO() && lfacs.size() > ii) { 1046 ppl = ppl.divide(ci); 1047 lfp = lfp.multiply(lfacs.get(ii)); 1048 } 1049 ii++; 1050 } 1051 //System.out.println("ppl = " + ppl + ", lfp = " + lfp); 1052 lfp = lfp.multiply(ppl); 1053 lf.set(i, lfp); 1054 } 1055 // adjust if pec != 1 1056 pec = pecw; 1057 lpx = Power.<GenPolynomial<BigInteger>> multiply(lprr.ring, lf); // test only, not used 1058 //System.out.println("lpx = " + lpx); 1059 if (!lprr.degreeVector().equals(lpx.degreeVector())) { 1060 logger.info("deg(lprr) != deg(lpx): lprr = " + lprr + ", lpx = " + lpx); 1061 notLucky = true; 1062 continue; 1063 } 1064 if (!pec.isONE()) { // content, was always false by hack 1065 // evaluate factors of ldcf 1066 List<GenPolynomial<BigInteger>> lfe = lf; 1067 List<BigInteger> lfei = null; 1068 ccpfac = lprr.ring; 1069 for (int j = lprr.ring.nvar; j > 0; j--) { 1070 ccpfac = ccpfac.contract(1); 1071 BigInteger Vi = V.get(lprr.ring.nvar - j); 1072 if (ccpfac.nvar >= 1) { 1073 lfe = PolyUtil.<BigInteger> evaluateMain(ccpfac, lfe, Vi); 1074 } else { 1075 lfei = PolyUtil.<BigInteger> evaluateMain(ccpfac.coFac, lfe, Vi); 1076 } 1077 } 1078 //System.out.println("lfe = " + lfe + ", lfei = " + lfei + ", V = " + V); 1079 1080 ln = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1081 un = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1082 for (int jj = 0; jj < lf.size(); jj++) { 1083 GenPolynomial<BigInteger> up = ufactors.get(jj); 1084 BigInteger ui = up.leadingBaseCoefficient(); 1085 BigInteger li = lfei.get(jj); 1086 BigInteger di = ui.gcd(li).abs(); 1087 BigInteger udi = ui.divide(di); 1088 BigInteger ldi = li.divide(di); 1089 GenPolynomial<BigInteger> lp = lf.get(jj); 1090 GenPolynomial<BigInteger> lpd = lp.multiply(udi); 1091 GenPolynomial<BigInteger> upd = up.multiply(ldi); 1092 if (pec.isONE()) { 1093 ln.add(lp); 1094 un.add(up); 1095 } else { 1096 ln.add(lpd); 1097 un.add(upd); 1098 BigInteger pec1 = pec.divide(ldi); 1099 //System.out.println("pec = " + pec + ", pec1 = " + pec1); 1100 pec = pec1; 1101 } 1102 } 1103 if (!lf.equals(ln) || !un.equals(ufactors)) { 1104 logger.debug("!lf.equals(ln) || !un.equals(ufactors)"); 1105 //System.out.println("pe = " + pe); 1106 //System.out.println("#ln = " + ln + ", #lf = " + lf); 1107 //System.out.println("#un = " + un + ", #ufactors = " + ufactors); 1108 //lf = ln; 1109 //ufactors = un; 1110 // adjust pe 1111 } 1112 if (!pec.isONE()) { // still not 1 1113 ln = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1114 un = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1115 pes = pe; 1116 for (int jj = 0; jj < lf.size(); jj++) { 1117 GenPolynomial<BigInteger> up = ufactors.get(jj); 1118 GenPolynomial<BigInteger> lp = lf.get(jj); 1119 //System.out.println("up = " + up + ", lp = " + lp); 1120 if (!up.isConstant()) { 1121 up = up.multiply(pec); 1122 } 1123 lp = lp.multiply(pec); 1124 if (jj != 0) { 1125 pes = pes.multiply(pec); 1126 } 1127 un.add(up); 1128 ln.add(lp); 1129 } 1130 if (pes.equals(Power.<GenPolynomial<BigInteger>> multiply(pe.ring, un))) { 1131 //System.out.println("*pe = " + pes + ", pec = " + pec); 1132 //ystem.out.println("*ln = " + ln + ", *lf = " + lf); 1133 //System.out.println("*un = " + un + ", *ufactors = " + ufactors); 1134 //System.out.println("*pe == prod(un) "); 1135 isPrimitive = false; 1136 //pe = pes; 1137 //lf = ln; 1138 //ufactors = un; 1139 } else { 1140 //System.out.println("*pe != prod(un): " + Power.<GenPolynomial<BigInteger>> multiply(pe.ring,un)); 1141 } 1142 } 1143 } 1144 //if (notLucky) { 1145 // continue; 1146 //} 1147 logger.info("distributed factors of leading coefficient = " + lf); 1148 lpx = Power.<GenPolynomial<BigInteger>> multiply(lprr.ring, lf); 1149 if (!lprr.abs().equals(lpx.abs())) { // not correctly distributed 1150 if (!lprr.degreeVector().equals(lpx.degreeVector())) { 1151 logger.info("lprr != lpx: lprr = " + lprr + ", lpx = " + lpx); 1152 notLucky = true; 1153 } 1154 } 1155 } // end determine leading coefficients for factors 1156 1157 if (!notLucky) { 1158 TrialParts tp = null; 1159 if (isPrimitive) { 1160 tp = new TrialParts(V, pe, ufactors, cei, lf); 1161 } else { 1162 tp = new TrialParts(V, pes, un, cei, ln); 1163 } 1164 //System.out.println("trialParts = " + tp); 1165 if (tp.univPoly != null) { 1166 if (tp.ldcfEval.size() != 0) { 1167 tParts.add(tp); 1168 } 1169 } 1170 if (tParts.size() < trials) { 1171 notLucky = true; 1172 } 1173 } 1174 } // end notLucky loop 1175 1176 // search TrialParts with shortest factorization of univariate polynomial 1177 int min = Integer.MAX_VALUE; 1178 TrialParts tpmin = null; 1179 for (TrialParts tp : tParts) { 1180 logger.info("tp.univFactors.size() = " + tp.univFactors.size()); 1181 if (tp.univFactors.size() < min) { 1182 min = tp.univFactors.size(); 1183 tpmin = tp; 1184 } 1185 } 1186 for (TrialParts tp : tParts) { 1187 //logger.info("tp.univFactors.get(0) = " + tp.univFactors.get(0)); 1188 if (tp.univFactors.size() == min) { 1189 if (!tp.univFactors.get(0).isConstant()) { 1190 tpmin = tp; 1191 break; 1192 } 1193 } 1194 } 1195 // set to (first) shortest 1196 V = tpmin.evalPoints; 1197 pe = tpmin.univPoly; 1198 ufactors = tpmin.univFactors; 1199 cei = tpmin.ldcfEval; // unused 1200 lf = tpmin.ldcfFactors; 1201 logger.info("iterations = " + Math.abs(evStart)); 1202 logger.info("minimal trial = " + tpmin); 1203 1204 GenPolynomialRing<BigInteger> ufac = pe.ring; 1205 1206 //initialize prime list 1207 PrimeList primes = new PrimeList(PrimeList.Range.medium); // PrimeList.Range.medium); 1208 Iterator<java.math.BigInteger> primeIter = primes.iterator(); 1209 int pn = 50; //primes.size(); 1210 BigInteger ae = pe.leadingBaseCoefficient(); 1211 GenPolynomial<MOD> Pm = null; 1212 ModularRingFactory<MOD> cofac = null; 1213 GenPolynomialRing<MOD> mufac = null; 1214 1215 // search lucky prime 1216 for (int i = 0; i < 11; i++) { // prime meta loop 1217 //for ( int i = 0; i < 1; i++ ) { // meta loop 1218 java.math.BigInteger p = null; //new java.math.BigInteger("19"); //primes.next(); 1219 // 2 small, 5 medium and 4 large size primes 1220 if (i == 0) { // medium size 1221 primes = new PrimeList(PrimeList.Range.medium); 1222 primeIter = primes.iterator(); 1223 } 1224 if (i == 5) { // small size 1225 primes = new PrimeList(PrimeList.Range.small); 1226 primeIter = primes.iterator(); 1227 p = primeIter.next(); // 2 1228 p = primeIter.next(); // 3 1229 p = primeIter.next(); // 5 1230 p = primeIter.next(); // 7 1231 } 1232 if (i == 7) { // large size 1233 primes = new PrimeList(PrimeList.Range.large); 1234 primeIter = primes.iterator(); 1235 } 1236 int pi = 0; 1237 while (pi < pn && primeIter.hasNext()) { 1238 p = primeIter.next(); 1239 logger.info("prime = " + p); 1240 // initialize coefficient factory and map normalization factor and polynomials 1241 ModularRingFactory<MOD> cf = null; 1242 if (ModLongRing.MAX_LONG.compareTo(p) > 0) { 1243 cf = (ModularRingFactory) new ModLongRing(p, true); 1244 } else { 1245 cf = (ModularRingFactory) new ModIntegerRing(p, true); 1246 } 1247 MOD nf = cf.fromInteger(ae.getVal()); 1248 if (nf.isZERO()) { 1249 continue; 1250 } 1251 mufac = new GenPolynomialRing<MOD>(cf, ufac); 1252 //System.out.println("mufac = " + mufac.toScript()); 1253 Pm = PolyUtil.<MOD> fromIntegerCoefficients(mufac, pe); 1254 //System.out.println("Pm = " + Pm); 1255 if (!mfactor.isSquarefree(Pm)) { 1256 continue; 1257 } 1258 cofac = cf; 1259 break; 1260 } 1261 if (cofac != null) { 1262 break; 1263 } 1264 } // end prime meta loop 1265 if (cofac == null) { // no lucky prime found 1266 throw new RuntimeException("giving up on Hensel preparation, no lucky prime found"); 1267 } 1268 logger.info("lucky prime = " + cofac.getIntegerModul()); 1269 if (logger.isDebugEnabled()) { 1270 logger.debug("univariate modulo p: = " + Pm); 1271 } 1272 1273 // coefficient bound 1274 BigInteger an = pd.maxNorm(); 1275 BigInteger mn = an.multiply(ac.abs()).multiply(new BigInteger(2L)); 1276 long k = Power.logarithm(cofac.getIntegerModul(), mn) + 1L; 1277 //System.out.println("mn = " + mn + ", k = " +k); 1278 1279 BigInteger q = cofac.getIntegerModul().power(k); 1280 ModularRingFactory<MOD> muqfac; 1281 if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { 1282 muqfac = (ModularRingFactory) new ModLongRing(q.getVal()); 1283 } else { 1284 muqfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); 1285 } 1286 //System.out.println("muqfac = " + muqfac); 1287 GenPolynomialRing<MOD> mucpfac = new GenPolynomialRing<MOD>(muqfac, ufac); 1288 1289 List<GenPolynomial<MOD>> muqfactors = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, ufactors); 1290 GenPolynomial<MOD> peqq = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, pe); 1291 if (debug) { 1292 if (!mfactor.isFactorization(peqq, muqfactors)) { // should not happen 1293 System.out.println("muqfactors = " + muqfactors); 1294 System.out.println("peqq = " + peqq); 1295 throw new RuntimeException("something is wrong, no modular p^k factorization"); 1296 } 1297 } 1298 logger.info("univariate modulo p^k: " + peqq + " = " + muqfactors); 1299 1300 // convert C from Z[...] to Z_q[...] 1301 GenPolynomialRing<MOD> qcfac = new GenPolynomialRing<MOD>(muqfac, pd.ring); 1302 GenPolynomial<MOD> pq = PolyUtil.<MOD> fromIntegerCoefficients(qcfac, pd); 1303 //System.out.println("pd = " + pd); 1304 logger.info("multivariate modulo p^k: " + pq); 1305 1306 //List<MOD> Vm = new ArrayList<MOD>(V.size()); 1307 //for (BigInteger v : V) { 1308 // MOD vm = muqfac.fromInteger(v.getVal()); 1309 // Vm.add(vm); 1310 //} 1311 //System.out.println("Vm = " + Vm); 1312 1313 // Hensel lifting of factors 1314 List<GenPolynomial<MOD>> mlift; 1315 try { 1316 mlift = HenselMultUtil.<MOD> liftHensel(pd, pq, muqfactors, V, k, lf); 1317 logger.info("mlift = " + mlift); 1318 } catch (NoLiftingException nle) { 1319 //System.out.println("exception : " + nle); 1320 //nle.printStackTrace(); 1321 //mlift = new ArrayList<GenPolynomial<MOD>>(); 1322 throw new RuntimeException(nle); 1323 } catch (ArithmeticException aex) { 1324 //System.out.println("exception : " + aex); 1325 //aex.printStackTrace(); 1326 //mlift = new ArrayList<GenPolynomial<MOD>>(); 1327 throw aex; 1328 } 1329 if (mlift.size() <= 1) { // irreducible mod I, p^k, can this happen? 1330 logger.info("modular lift size == 1: " + mlift); 1331 factors.add(pd); // P 1332 if (cfactors != null) { 1333 cfactors.addAll(factors); 1334 factors = cfactors; 1335 } 1336 return factors; 1337 } 1338 1339 // combine trial factors 1340 GenPolynomialRing<MOD> mfac = mlift.get(0).ring; 1341 int dl = (mlift.size() + 1) / 2; 1342 GenPolynomial<BigInteger> u = P; 1343 long deg = (u.degree() + 1L) / 2L; 1344 1345 GenPolynomial<BigInteger> ui = pd; 1346 for (int j = 1; j <= dl; j++) { 1347 //System.out.println("j = " + j + ", dl = " + dl + ", mlift = " + mlift); 1348 KsubSet<GenPolynomial<MOD>> subs = new KsubSet<GenPolynomial<MOD>>(mlift, j); 1349 for (List<GenPolynomial<MOD>> flist : subs) { 1350 //System.out.println("degreeSum = " + degreeSum(flist)); 1351 GenPolynomial<MOD> mtrial = Power.<GenPolynomial<MOD>> multiply(mfac, flist); 1352 if (mtrial.degree() > deg) { // this test is sometimes wrong 1353 logger.info("degree > deg " + deg + ", degree = " + mtrial.degree()); 1354 //continue; 1355 } 1356 GenPolynomial<BigInteger> trial = PolyUtil.integerFromModularCoefficients(pfac, mtrial); 1357 trial = engine.basePrimitivePart(trial); 1358 //if ( ! isPrimitive ) { 1359 //} 1360 if (debug) { 1361 logger.info("trial = " + trial); // + ", mtrial = " + mtrial); 1362 } 1363 if (PolyUtil.<BigInteger> baseSparsePseudoRemainder(ui, trial).isZERO()) { 1364 logger.info("successful trial = " + trial); 1365 factors.add(trial); 1366 ui = PolyUtil.<BigInteger> basePseudoDivide(ui, trial); 1367 //System.out.println("ui = " + ui); 1368 mlift = removeOnce(mlift, flist); 1369 logger.info("new mlift= " + mlift); 1370 //System.out.println("dl = " + dl); 1371 if (mlift.size() > 1) { 1372 dl = (mlift.size() + 1) / 2; 1373 j = 0; // since j++ 1374 break; 1375 } 1376 logger.info("last factor = " + ui); 1377 factors.add(ui); 1378 if (cfactors != null) { 1379 cfactors.addAll(factors); 1380 factors = cfactors; 1381 } 1382 return normalizeFactorization(factors); 1383 } 1384 } 1385 } 1386 if (!ui.isONE() && !ui.equals(pd)) { 1387 logger.info("rest factor = " + ui); 1388 // pp(ui) ?? no ?? 1389 factors.add(ui); 1390 } 1391 if (factors.size() == 0) { 1392 logger.info("irreducible P = " + P); 1393 factors.add(pd); // P 1394 } 1395 if (cfactors != null) { 1396 cfactors.addAll(factors); 1397 factors = cfactors; 1398 } 1399 return normalizeFactorization(factors); 1400 } 1401 1402 1403 /** 1404 * Test if b has a prime factor different to the elements of A. 1405 * @param A list of integer with at least one different prime factor. 1406 * @param b integer to test with A. 1407 * @return true, if b hase a prime factor different to elements of A 1408 */ 1409 boolean testSeparate(List<BigInteger> A, BigInteger b) { 1410 int i = 0; 1411 //List<BigInteger> gei = new ArrayList<BigInteger>(A.size()); 1412 for (BigInteger c : A) { 1413 BigInteger g = c.gcd(b).abs(); 1414 //gei.add(g); 1415 if (!g.isONE()) { 1416 i++; 1417 } 1418 } 1419 //if ( i >= 1 ) { 1420 //System.out.println("gei = " + gei + ", cei = " + cei + ", pec(w) = " + pec); 1421 //} 1422 return (i <= 1); 1423 } 1424 1425 1426 // not useable 1427 boolean isNearlySquarefree(GenPolynomial<BigInteger> P) { // unused 1428 // in main variable 1429 GenPolynomialRing<BigInteger> pfac = P.ring; 1430 if (pfac.nvar >= 0) { // allways true 1431 return sengine.isSquarefree(P); 1432 } 1433 GenPolynomialRing<GenPolynomial<BigInteger>> rfac = pfac.recursive(1); 1434 GenPolynomial<GenPolynomial<BigInteger>> Pr = PolyUtil.<BigInteger> recursive(rfac, P); 1435 GenPolynomial<GenPolynomial<BigInteger>> Ps = PolyUtil.<BigInteger> recursiveDeriviative(Pr); 1436 System.out.println("Pr = " + Pr); 1437 System.out.println("Ps = " + Ps); 1438 GenPolynomial<GenPolynomial<BigInteger>> g = engine.recursiveUnivariateGcd(Pr, Ps); 1439 System.out.println("g_m = " + g); 1440 if (!g.isONE()) { 1441 return false; 1442 } 1443 // in lowest variable 1444 rfac = pfac.recursive(pfac.nvar - 1); 1445 Pr = PolyUtil.<BigInteger> recursive(rfac, P); 1446 Pr = PolyUtil.<BigInteger> switchVariables(Pr); 1447 Ps = PolyUtil.<BigInteger> recursiveDeriviative(Pr); 1448 System.out.println("Pr = " + Pr); 1449 System.out.println("Ps = " + Ps); 1450 g = engine.recursiveUnivariateGcd(Pr, Ps); 1451 System.out.println("g_1 = " + g); 1452 if (!g.isONE()) { 1453 return false; 1454 } 1455 return true; 1456 } 1457 1458} 1459 1460 1461/** 1462 * Container for factorization trial lifting parameters. 1463 */ 1464class TrialParts { 1465 1466 1467 /** 1468 * evaluation points 1469 */ 1470 public final List<BigInteger> evalPoints; 1471 1472 1473 /** 1474 * univariate polynomial 1475 */ 1476 public final GenPolynomial<BigInteger> univPoly; 1477 1478 1479 /** 1480 * irreducible factors of univariate polynomial 1481 */ 1482 public final List<GenPolynomial<BigInteger>> univFactors; 1483 1484 1485 /** 1486 * irreducible factors of leading coefficient 1487 */ 1488 public final List<GenPolynomial<BigInteger>> ldcfFactors; 1489 1490 1491 /** 1492 * evaluated factors of leading coefficient factors by evaluation points 1493 */ 1494 public final List<BigInteger> ldcfEval; 1495 1496 1497 /** 1498 * Constructor. 1499 * @param ev evaluation points. 1500 * @param up univariate polynomial. 1501 * @param uf irreducible factors of up. 1502 * @param le irreducible factors of leading coefficient. 1503 * @param lf evaluated le by evaluation points. 1504 */ 1505 public TrialParts(List<BigInteger> ev, GenPolynomial<BigInteger> up, List<GenPolynomial<BigInteger>> uf, 1506 List<BigInteger> le, List<GenPolynomial<BigInteger>> lf) { 1507 evalPoints = ev; 1508 univPoly = up; 1509 univFactors = uf; 1510 //ldcfPoly = lp; 1511 ldcfFactors = lf; 1512 ldcfEval = le; 1513 } 1514 1515 1516 /** 1517 * @see java.lang.Object#toString() 1518 */ 1519 @Override 1520 public String toString() { 1521 StringBuffer sb = new StringBuffer(); 1522 sb.append("TrialParts["); 1523 sb.append("evalPoints = " + evalPoints); 1524 sb.append(", univPoly = " + univPoly); 1525 sb.append(", univFactors = " + univFactors); 1526 sb.append(", ldcfEval = " + ldcfEval); 1527 sb.append(", ldcfFactors = " + ldcfFactors); 1528 sb.append("]"); 1529 return sb.toString(); 1530 } 1531 1532}