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