001/* 002 * $Id$ 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 = {}, lc = {}, tc = {}", fac, lc, 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 logger.info("modlist = {}", mlist); 274 if (mlist.size() <= 1) { 275 factors.add(P); 276 return factors; 277 } 278 if (!nf.isONE()) { 279 GenPolynomial<MOD> mp = mfac.getONE(); //mlist.get(0); 280 //System.out.println("mp = " + mp); 281 mp = mp.multiply(nf); 282 //System.out.println("mp = " + mp); 283 mlist.add(0, mp); // set(0,mp); 284 } 285 modfac[k] = mlist; 286 plist[k] = cofac.getIntegerModul(); // p 287 } 288 289 // search shortest factor list 290 int min = Integer.MAX_VALUE; 291 BitSet AD = null; 292 for (int k = 0; k < TT; k++) { 293 List<ExpVector> ev = PolyUtil.<MOD> leadingExpVector(modfac[k]); 294 BitSet D = factorDegrees(ev, degi); 295 if (AD == null) { 296 AD = D; 297 } else { 298 AD.and(D); 299 } 300 int s = modfac[k].size(); 301 logger.info("mod({}) #s = {}, D = {}", plist[k], s, D); 302 if (s < min) { 303 min = s; 304 mlist = modfac[k]; 305 } 306 } 307 logger.info("min = {}, AD = {}", min, AD); 308 if (mlist.size() <= 1) { 309 logger.info("mlist.size() = 1"); 310 factors.add(P); 311 return factors; 312 } 313 if (AD.cardinality() <= 2) { // only one possible factor 314 logger.info("degree set cardinality = {}", AD.cardinality()); 315 factors.add(P); 316 return factors; 317 } 318 319 final boolean allLists = false; //true; //false; 320 if (allLists) { 321 // try each factor list 322 for (int k = 0; k < TT; k++) { 323 mlist = modfac[k]; 324 if (debug) { 325 logger.info("lifting from {}", mlist); 326 } 327 if (P.leadingBaseCoefficient().isONE()) { // monic case 328 factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases 329 if (factors.size() == 1) { 330 factors = searchFactorsNonMonic(P, M, mlist, AD); 331 } 332 } else { 333 factors = searchFactorsNonMonic(P, M, mlist, AD); 334 } 335 intfac[k] = factors; 336 } 337 } else { 338 // try only shortest factor list 339 if (debug) { 340 logger.info("lifting shortest from {}", mlist); 341 } 342 if (P.leadingBaseCoefficient().isONE()) { 343 long t = System.currentTimeMillis(); 344 try { 345 mlist = PolyUtil.<MOD> monic(mlist); 346 factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases 347 t = System.currentTimeMillis() - t; 348 //System.out.println("monic time = " + t); 349 intfac[0] = factors; 350 if (debug) { 351 t = System.currentTimeMillis(); 352 List<GenPolynomial<BigInteger>> fnm = searchFactorsNonMonic(P, M, mlist, AD); 353 t = System.currentTimeMillis() - t; 354 System.out.println("non monic time = " + t); 355 if (!factors.equals(fnm)) { 356 System.out.println("monic factors = " + intfac[0]); //factors); 357 System.out.println("non monic factors = " + fnm); 358 } 359 } 360 } catch (RuntimeException e) { 361 t = System.currentTimeMillis(); 362 factors = searchFactorsNonMonic(P, M, mlist, AD); 363 t = System.currentTimeMillis() - t; 364 //System.out.println("only non monic time = " + t); 365 } 366 } else { 367 long t = System.currentTimeMillis(); 368 factors = searchFactorsNonMonic(P, M, mlist, AD); 369 t = System.currentTimeMillis() - t; 370 //System.out.println("non monic time = " + t); 371 } 372 return normalizeFactorization(factors); 373 } 374 375 // search longest factor list 376 int max = 0; 377 for (int k = 0; k < TT; k++) { 378 int s = intfac[k].size(); 379 logger.info("int s = {}", s); 380 if (s > max) { 381 max = s; 382 ilist = intfac[k]; 383 } 384 } 385 factors = normalizeFactorization(ilist); 386 return factors; 387 } 388 389 390 /** 391 * BitSet for factor degree list. 392 * @param E exponent vector list. 393 * @return {b_0,...,b_k} a BitSet of possible factor degrees. 394 */ 395 public BitSet factorDegrees(List<ExpVector> E, int deg) { 396 BitSet D = new BitSet(deg + 1); 397 D.set(0); // constant factor 398 for (ExpVector e : E) { 399 int i = (int) e.getVal(0); 400 BitSet s = new BitSet(deg + 1); 401 for (int k = 0; k < deg + 1 - i; k++) { // shift by i places 402 s.set(i + k, D.get(k)); 403 } 404 //System.out.println("s = " + s); 405 D.or(s); 406 //System.out.println("D = " + D); 407 } 408 return D; 409 } 410 411 412 /** 413 * Sum of all degrees. 414 * @param L univariate polynomial list. 415 * @return sum deg(p) for p in L. 416 */ 417 public static <C extends RingElem<C>> long degreeSum(List<GenPolynomial<C>> L) { 418 long s = 0L; 419 for (GenPolynomial<C> p : L) { 420 ExpVector e = p.leadingExpVector(); 421 long d = e.getVal(0); 422 s += d; 423 } 424 return s; 425 } 426 427 428 /** 429 * Factor search with modular Hensel lifting algorithm. Let p = 430 * f_i.ring.coFac.modul() i = 0, ..., n-1 and assume C == prod_{0,...,n-1} 431 * f_i mod p with ggt(f_i,f_j) == 1 mod p for i != j 432 * @param C GenPolynomial. 433 * @param M bound on the coefficients of g_i as factors of C. 434 * @param F = [f_0,...,f_{n-1}] List<GenPolynomial>. 435 * @param D bit set of possible factor degrees. 436 * @return [g_0,...,g_{n-1}] = lift(C,F), with C = prod_{0,...,n-1} g_i mod 437 * p**e. <b>Note:</b> does not work in all cases. 438 */ 439 List<GenPolynomial<BigInteger>> searchFactorsMonic(GenPolynomial<BigInteger> C, BigInteger M, 440 List<GenPolynomial<MOD>> F, BitSet D) { 441 //System.out.println("*** monic factor combination ***"); 442 if (C == null || C.isZERO() || F == null || F.size() == 0) { 443 throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); 444 } 445 GenPolynomialRing<BigInteger> pfac = C.ring; 446 if (pfac.nvar != 1) { // assert ? 447 throw new IllegalArgumentException("polynomial ring not univariate"); 448 } 449 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 450 List<GenPolynomial<MOD>> mlist = F; 451 List<GenPolynomial<MOD>> lift; 452 453 //MOD nf = null; 454 GenPolynomial<MOD> ct = mlist.get(0); 455 if (ct.isConstant()) { 456 //nf = ct.leadingBaseCoefficient(); 457 mlist.remove(ct); 458 //System.out.println("=== nf = " + nf); 459 if (mlist.size() <= 1) { 460 factors.add(C); 461 return factors; 462 } 463 } else { 464 //nf = ct.ring.coFac.getONE(); 465 } 466 //System.out.println("modlist = " + mlist); // includes not ldcf 467 ModularRingFactory<MOD> mcfac = (ModularRingFactory<MOD>) ct.ring.coFac; 468 BigInteger m = mcfac.getIntegerModul(); 469 long k = 1; 470 BigInteger pi = m; 471 while (pi.compareTo(M) < 0) { 472 k++; 473 pi = pi.multiply(m); 474 } 475 logger.info("p^k = {}^{}", m, k); 476 GenPolynomial<BigInteger> PP = C, P = C; 477 // lift via Hensel 478 try { 479 lift = HenselUtil.<MOD> liftHenselMonic(PP, mlist, k); 480 //System.out.println("lift = " + lift); 481 } catch (NoLiftingException e) { 482 throw new RuntimeException(e); 483 } 484 logger.info("lifted modlist = {}", lift); 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 {}, deg = {}", D, 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 {} > deg {}", mtrial.degree(0), 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 {}, deg = {}", D, 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 {}, degree = {}", deg, 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 = {}, cofactor {}", trial, cofactor); 645 logger.info("lifted intlist = {}, cofactor {}", itrial, 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 List<GenPolynomial<BigInteger>> factors; 701 factors = factorsSquarefreeOptions(P, false, false); 702 if (factors != null) { 703 return factors; 704 } 705 factors = factorsSquarefreeOptions(P, false, true); 706 if (factors != null) { 707 return factors; 708 } 709 factors = factorsSquarefreeOptions(P, true, false); 710 if (factors != null) { 711 return factors; 712 } 713 factors = factorsSquarefreeOptions(P, true, true); 714 if (factors != null) { 715 return factors; 716 } 717 logger.warn("factorsSquarefreeHensel not applicable or failed, reverting to Kronecker for: {}", P); 718 factors = super.factorsSquarefree(P); 719 return factors; 720 } 721 722 723 /** 724 * GenPolynomial factorization of a multivariate squarefree polynomial, 725 * using Hensel lifting if possible. 726 * @param P squarefree and primitive! (respectively monic) multivariate 727 * GenPolynomial over the integers. 728 * @param opti true, if polynomial variables should be optimized, else false. 729 * @param tlex true, if INVLEX term order should be forced, else false. 730 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 731 */ 732 public List<GenPolynomial<BigInteger>> factorsSquarefreeOptions(GenPolynomial<BigInteger> P, boolean opti, boolean tlex) { 733 GenPolynomial<BigInteger> Pp = P; 734 GenPolynomialRing<BigInteger> pfac = Pp.ring; 735 if (pfac.nvar <= 1) { 736 return baseFactorsSquarefree(Pp); 737 } 738 if (tlex) { 739 if (! pfac.tord.equals(TermOrderByName.INVLEX)) { 740 pfac = new GenPolynomialRing<BigInteger>(pfac,TermOrderByName.INVLEX); 741 Pp = pfac.copy(Pp); 742 logger.warn("invlexed polynomial: {}, from ring {}", Pp, P.ring); 743 } else { 744 tlex = false; 745 } 746 } 747 OptimizedPolynomialList<BigInteger> opt = null; 748 List<Integer> iperm = null; 749 final boolean USE_OPT = opti; 750 if (USE_OPT) { 751 List<GenPolynomial<BigInteger>> topt = new ArrayList<GenPolynomial<BigInteger>>(1); 752 topt.add(Pp); 753 opt = TermOrderOptimization.<BigInteger> optimizeTermOrder(pfac, topt); 754 if (!TermOrderOptimization.isIdentityPermutation(opt.perm)) { 755 iperm = TermOrderOptimization.inversePermutation(opt.perm); 756 Pp = opt.list.get(0); 757 logger.info("optimized polynomial: {}", Pp); 758 logger.warn("optimized ring: {}, original ring: {}", opt.ring, pfac); 759 } 760 } 761 ExpVector degv = Pp.degreeVector(); 762 int[] donv = degv.dependencyOnVariables(); 763 List<GenPolynomial<BigInteger>> facs = null; 764 if (degv.length() == donv.length) { // all variables appear, hack for Hensel, check 765 try { 766 logger.info("try factorsSquarefreeHensel: {}", Pp); 767 facs = factorsSquarefreeHensel(Pp); 768 } catch (Exception e) { 769 logger.info("exception {}", e); 770 //e.printStackTrace(); 771 } 772 } else { // not all variables appear, remove unused variables, hack for Hensel, check 773 GenPolynomial<BigInteger> pu = PolyUtil.<BigInteger> removeUnusedUpperVariables(Pp); 774 //GenPolynomial<BigInteger> pl = PolyUtil.<BigInteger> removeUnusedLowerVariables(pu); // not useful 775 try { 776 logger.info("try factorsSquarefreeHensel: {}", pu); 777 facs = factorsSquarefreeHensel(pu); 778 List<GenPolynomial<BigInteger>> fs = new ArrayList<GenPolynomial<BigInteger>>(facs.size()); 779 GenPolynomialRing<BigInteger> pf = Pp.ring; 780 //GenPolynomialRing<BigInteger> pfu = pu.ring; 781 for (GenPolynomial<BigInteger> p : facs) { 782 //GenPolynomial<BigInteger> pel = p.extendLower(pfu, 0, 0L); 783 GenPolynomial<BigInteger> pe = p.extend(pf, 0, 0L); 784 fs.add(pe); 785 } 786 //System.out.println("fs = " + fs); 787 facs = fs; 788 } catch (Exception e) { 789 logger.info("exception {}", e); 790 //e.printStackTrace(); 791 } 792 } 793 if (facs == null) { 794 return facs; 795 } 796 if (USE_OPT && iperm != null) { 797 facs = TermOrderOptimization.<BigInteger> permutation(iperm, pfac, facs); 798 logger.warn("de-optimized polynomials: {}", facs); 799 } 800 if (tlex) { 801 facs = P.ring.copy(facs); 802 logger.warn("de-invlexed polynomials: {}", facs); 803 } 804 facs = normalizeFactorization(facs); 805 return facs; 806 } 807 808 809 /** 810 * GenPolynomial factorization of a multivariate squarefree polynomial, 811 * using Hensel lifting. 812 * @param P squarefree and primitive! (respectively monic) multivariate 813 * GenPolynomial over the integers. 814 * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. 815 */ 816 @SuppressWarnings("unchecked") 817 public List<GenPolynomial<BigInteger>> factorsSquarefreeHensel(GenPolynomial<BigInteger> P) { 818 if (P == null) { 819 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 820 } 821 GenPolynomialRing<BigInteger> pfac = P.ring; 822 if (pfac.nvar == 1) { 823 return baseFactorsSquarefree(P); 824 } 825 List<GenPolynomial<BigInteger>> factors = new ArrayList<GenPolynomial<BigInteger>>(); 826 if (P.isZERO()) { 827 return factors; 828 } 829 if (P.degreeVector().totalDeg() <= 1L) { 830 factors.add(P); 831 return factors; 832 } 833 GenPolynomial<BigInteger> pd = P; 834 //System.out.println("pd = " + pd); 835 // ldcf(pd) 836 BigInteger ac = pd.leadingBaseCoefficient(); 837 838 // factor leading coefficient as polynomial in the lowest! variable 839 GenPolynomialRing<GenPolynomial<BigInteger>> rnfac = pfac.recursive(pfac.nvar - 1); 840 GenPolynomial<GenPolynomial<BigInteger>> pr = PolyUtil.<BigInteger> recursive(rnfac, pd); 841 GenPolynomial<GenPolynomial<BigInteger>> prr = PolyUtil.<BigInteger> switchVariables(pr); 842 843 GenPolynomial<BigInteger> prrc = engine.recursiveContent(prr); // can have content wrt this variable 844 List<GenPolynomial<BigInteger>> cfactors = null; 845 if (!prrc.isONE()) { 846 prr = PolyUtil.<BigInteger> recursiveDivide(prr, prrc); 847 GenPolynomial<BigInteger> prrcu = prrc.extendLower(pfac, 0, 0L); // since switched vars 848 pd = PolyUtil.<BigInteger> basePseudoDivide(pd, prrcu); 849 logger.info("recursive content = {}, new P = {}", prrc, pd); 850 cfactors = factorsSquarefree(prrc); 851 List<GenPolynomial<BigInteger>> cff = new ArrayList<GenPolynomial<BigInteger>>(cfactors.size()); 852 for (GenPolynomial<BigInteger> fs : cfactors) { 853 GenPolynomial<BigInteger> fsp = fs.extendLower(pfac, 0, 0L); // since switched vars 854 cff.add(fsp); 855 } 856 cfactors = cff; 857 logger.info("cfactors = {}", cfactors); 858 } 859 GenPolynomial<BigInteger> lprr = prr.leadingBaseCoefficient(); 860 //System.out.println("prr = " + prr); 861 logger.info("leading coeffcient = {}", lprr); 862 boolean isMonic = false; // multivariate monic 863 if (lprr.isConstant()) { // isONE ? 864 isMonic = true; 865 } 866 SortedMap<GenPolynomial<BigInteger>, Long> lfactors = factors(lprr); 867 //System.out.println("lfactors = " + lfactors); 868 List<GenPolynomial<BigInteger>> lfacs = new ArrayList<GenPolynomial<BigInteger>>(lfactors.keySet()); 869 logger.info("leading coefficient factors = {}", lfacs); 870 871 // search evaluation point and evaluate 872 GenPolynomialRing<BigInteger> cpfac = pfac; 873 GenPolynomial<BigInteger> pe = pd; 874 GenPolynomial<BigInteger> pep; 875 GenPolynomialRing<BigInteger> ccpfac = lprr.ring; 876 List<GenPolynomial<BigInteger>> ce = lfacs; 877 List<GenPolynomial<BigInteger>> cep = null; 878 List<BigInteger> cei = null; 879 List<BigInteger> dei = new ArrayList<BigInteger>(); 880 BigInteger pec = null; 881 BigInteger pecw = null; 882 BigInteger ped = null; 883 884 List<GenPolynomial<BigInteger>> ufactors = null; 885 List<TrialParts> tParts = new ArrayList<TrialParts>(); 886 List<GenPolynomial<BigInteger>> lf = null; 887 GenPolynomial<BigInteger> lpx = null; 888 List<GenPolynomial<BigInteger>> ln = null; 889 List<GenPolynomial<BigInteger>> un = null; 890 GenPolynomial<BigInteger> pes = null; 891 892 List<BigInteger> V = null; 893 long evStart = 0L; //3L * 5L; 894 List<Long> Evs = new ArrayList<Long>(pfac.nvar + 1); // Evs(0), Evs(1) unused 895 for (int j = 0; j <= pfac.nvar; j++) { 896 //Evs.add(evStart++); // bug 897 Evs.add(evStart); 898 if (evStart > 0) { 899 evStart = - evStart; 900 } else { 901 evStart = 1L - evStart; 902 } 903 } 904 //no: Collections.reverse(Evs); 905 evStart = Evs.get(0); 906 final int trials = 4; 907 int countSeparate = 0; 908 final int COUNT_MAX = 50; 909 double ran = 1.001; // higher values not good 910 boolean isPrimitive = true; 911 boolean notLucky = true; 912 while (notLucky) { // for Wang's test 913 if (Math.abs(evStart) > 371L) { 914 logger.warn("found points : V = {}, dei = {}", V, dei); 915 //if (tParts != null && tParts.size() > 0) { // at least one successful eval point 916 // logger.warn("some evaluation points found after {} iterations, tParts = {}", Math.abs(evStart), tParts); 917 // break; 918 //} 919 logger.warn("no evaluation point for: P = {}, prr = {}, lprr = {}, lfacs = {}", P, prr, lprr, lfacs); 920 throw new RuntimeException( 921 "no evaluation point found after " + Math.abs(evStart) + " iterations"); 922 } 923 if (Math.abs(evStart) % 100L <= 3L) { 924 ran = ran * (Math.PI - 2.14); 925 } 926 //System.out.println("-------------------------------------------- Evs = " + Evs); 927 notLucky = false; 928 V = new ArrayList<BigInteger>(); 929 cpfac = pfac; 930 pe = pd; 931 ccpfac = lprr.ring; 932 ce = lfacs; 933 cep = null; 934 cei = null; 935 pec = null; 936 ped = null; 937 long vi = 0L; 938 for (int j = pfac.nvar; j > 1; j--) { 939 // evaluation up to univariate case 940 long degp = pe.degree(cpfac.nvar - 2); 941 cpfac = cpfac.contract(1); 942 ccpfac = ccpfac.contract(1); 943 //vi = evStart; // + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p 944 vi = Evs.get(j); //evStart + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p 945 BigInteger Vi; 946 947 // search evaluation point 948 boolean doIt = true; 949 Vi = null; 950 pep = null; 951 while (doIt) { 952 logger.info("vi({}) = {}", j, vi); 953 Vi = new BigInteger(vi); 954 pep = PolyUtil.<BigInteger> evaluateMain(cpfac, pe, Vi); 955 //System.out.println("pep = " + pep); 956 //System.out.println("degp = " + degp + ", dege = " + pep.degree(cpfac.nvar - 1)); 957 // check lucky evaluation point 958 if (degp == pep.degree(cpfac.nvar - 1)) { 959 logger.info("pep = {}", pep); 960 //System.out.println("deg(pe) = " + degp + ", deg(pep) = " + pep.degree(cpfac.nvar-1)); 961 // check squarefree 962 if (sengine.isSquarefree(pep)) { // cpfac.nvar == 1 && ?? no, must test on each variable 963 //if ( isNearlySquarefree(pep) ) { 964 //System.out.println("squarefeee(pep)"); // + pep); 965 doIt = false; //break; 966 } else { 967 logger.info("pep not squarefree "); 968 } 969 } 970 if (vi > 0L) { 971 vi = -vi; 972 } else { 973 vi = 1L - vi; 974 } 975 } 976 //if ( !isMonic ) { 977 if (ccpfac.nvar >= 1) { 978 cep = PolyUtil.<BigInteger> evaluateMain(ccpfac, ce, Vi); 979 } else { 980 cei = PolyUtil.<BigInteger> evaluateMain(ccpfac.coFac, ce, Vi); 981 } 982 //} 983 int jj = (int) Math.round(ran + 0.52 * Math.random()); // j, random increment 984 //jj = 0; // ...4 test 985 //System.out.print("minimal jj = " + jj + ", vi_a " + vi); 986 if (vi > 0L) { 987 Evs.set(j, vi + jj); // record last tested value plus increment 988 evStart = vi + jj; 989 } else { 990 Evs.set(j, vi - jj); // record last tested value minus increment 991 evStart = vi - jj; 992 } 993 // ensure different evaluation points 994 Set<Long> Evset = new HashSet<Long>(Evs); 995 while (Evset.size() != Evs.size()) { 996 //logger.warn("same eval points: {} != {}", Evs, Evset); 997 long vgi = Evs.get(j); 998 if (vgi > 0L) { 999 vgi += 1L; 1000 } else { 1001 vgi -= 1L; 1002 } 1003 Evs.set(j, vgi); 1004 Evset.clear(); Evset.addAll(Evs); //= new HashSet<Long>(Evs); 1005 evStart = vgi; 1006 //logger.warn("same eval points: {}, j = {}", Evs, j); 1007 } 1008 //System.out.println(", j = " + j + ", vi_b " + Vi); 1009 //evStart = vi+1L; 1010 V.add(Vi); 1011 pe = pep; 1012 ce = cep; 1013 } 1014 //System.out.println("ce = " + ce + ", pe = " + pe + ", V = " + V); 1015 pecw = engine.baseContent(pe); // original Wang 1016 isPrimitive = pecw.isONE(); 1017 ped = ccpfac.coFac.getONE(); 1018 pec = pe.ring.coFac.getONE(); 1019 //System.out.println("cei = " + cei + ", pecw = " + pecw); 1020 if (!isMonic) { 1021 if (countSeparate > COUNT_MAX) { 1022 pec = pe.ring.coFac.getONE(); // hack is sometimes better 1023 } else { 1024 pec = pecw; 1025 } 1026 //pec = pecw; 1027 //System.out.println("cei = " + cei + ", pec = " + pec + ", pe = " + pe); 1028 if (lfacs.get(0).isConstant()) { 1029 ped = cei.remove(0); 1030 //lfacs.remove(0); // later 1031 } 1032 //System.out.println("lfacs = " + lfacs + ", cei = " + cei + ", ped = " + ped + ", pecw = " + pecw); 1033 // test Wang's condition 1034 dei = new ArrayList<BigInteger>(); 1035 dei.add(pec.multiply(ped).abs()); // .abs() 1036 int i = 1; 1037 for (BigInteger ci : cei) { 1038 if (ci.isZERO()) { 1039 logger.info("condition (0) not met for cei = {}", cei); // + ", dei = {}", dei); 1040 notLucky = true; 1041 break; 1042 } 1043 BigInteger q = ci.abs(); 1044 //System.out.println("q = " + q); 1045 for (int ii = i - 1; ii >= 0; ii--) { 1046 BigInteger r = dei.get(ii); 1047 //System.out.println("r = " + r); 1048 while (!r.isONE()) { 1049 r = r.gcd(q); 1050 q = q.divide(r); 1051 //System.out.println("r = " + r + ", q = " + q); 1052 } 1053 } 1054 dei.add(q); 1055 if (q.isONE()) { 1056 logger.info("condition (1) not met for dei = {}, cei = {}", dei, cei); 1057 if (!testSeparate(cei, pecw)) { 1058 countSeparate++; 1059 if (countSeparate > COUNT_MAX) { 1060 logger.info("too many inseparable evaluation points: {}, removing {}", countSeparate, 1061 pecw); 1062 } 1063 } 1064 notLucky = true; 1065 break; 1066 } 1067 i++; 1068 } 1069 //System.out.println("dei = " + dei); 1070 } 1071 if (notLucky) { 1072 continue; 1073 } 1074 logger.info("evaluation points = {}, dei = {}", V, dei); 1075 //System.out.println("Evs = " + Evs); 1076 logger.info("univariate polynomial = {}, pecw = {}", pe, pecw); 1077 //pe = pe.abs(); 1078 //ufactors = baseFactorsRadical(pe); //baseFactorsSquarefree(pe); wrong since not primitive 1079 ufactors = baseFactorsSquarefree(pe.divide(pecw)); //wrong if not primitive 1080 if (!pecw.isONE()) { 1081 ufactors.add(0, cpfac.getONE().multiply(pecw)); 1082 } 1083 if (ufactors.size() <= 1) { 1084 logger.info("irreducible univariate polynomial"); 1085 factors.add(pd); // P 1086 if (cfactors != null) { 1087 cfactors.addAll(factors); 1088 factors = cfactors; 1089 } 1090 return factors; 1091 } 1092 logger.info("univariate factors = {}", ufactors); // + ", of {}", pe); 1093 //System.out.println("lfacs = " + lfacs); 1094 //System.out.println("cei = " + cei); 1095 //System.out.println("pecw = " + pecw); 1096 1097 // determine leading coefficient polynomials for factors 1098 lf = new ArrayList<GenPolynomial<BigInteger>>(); 1099 lpx = lprr.ring.getONE(); 1100 for (int i = 0; i < ufactors.size(); i++) { 1101 lf.add(lprr.ring.getONE()); 1102 } 1103 //System.out.println("lf = " + lf); 1104 if (!isMonic || !pecw.isONE()) { 1105 if (lfacs.size() > 0 && lfacs.get(0).isConstant()) { 1106 //GenPolynomial<BigInteger> unused = 1107 lfacs.remove(0); 1108 //BigInteger xxi = xx.leadingBaseCoefficient(); 1109 //System.out.println("xx = " + xx + " == ped = " +ped); 1110 } 1111 for (int i = ufactors.size() - 1; i >= 0; i--) { 1112 GenPolynomial<BigInteger> pp = ufactors.get(i); 1113 BigInteger ppl = pp.leadingBaseCoefficient(); 1114 //System.out.println("ppl = " + ppl + ", pp = " + pp); 1115 ppl = ppl.multiply(pec); // content 1116 GenPolynomial<BigInteger> lfp = lf.get(i); 1117 int ii = 0; 1118 for (BigInteger ci : cei) { 1119 //System.out.println("ci = " + ci + ", lfp = " + lfp + ", lfacs.get(ii) = " + lfacs.get(ii)); 1120 if (ci.abs().isONE()) { 1121 System.out.println("ppl = " + ppl + ", ci = " + ci + ", lfp = " + lfp 1122 + ", lfacs.get(ii) = " + lfacs.get(ii)); 1123 notLucky = true; 1124 throw new RuntimeException("something is wrong, ci is a unit"); 1125 } 1126 while (ppl.remainder(ci).isZERO() && lfacs.size() > ii) { 1127 ppl = ppl.divide(ci); 1128 lfp = lfp.multiply(lfacs.get(ii)); 1129 } 1130 ii++; 1131 } 1132 //System.out.println("ppl = " + ppl + ", lfp = " + lfp); 1133 lfp = lfp.multiply(ppl); 1134 lf.set(i, lfp); 1135 } 1136 // adjust if pec != 1 1137 pec = pecw; 1138 lpx = Power.<GenPolynomial<BigInteger>> multiply(lprr.ring, lf); // test only, not used 1139 //System.out.println("lpx = " + lpx); 1140 if (!lprr.degreeVector().equals(lpx.degreeVector())) { 1141 logger.info("deg(lprr) != deg(lpx): lprr = {}, lpx = {}", lprr, lpx); 1142 notLucky = true; 1143 continue; 1144 } 1145 if (!pec.isONE()) { // content, was always false by hack 1146 // evaluate factors of ldcf 1147 List<GenPolynomial<BigInteger>> lfe = lf; 1148 List<BigInteger> lfei = null; 1149 ccpfac = lprr.ring; 1150 for (int j = lprr.ring.nvar; j > 0; j--) { 1151 ccpfac = ccpfac.contract(1); 1152 BigInteger Vi = V.get(lprr.ring.nvar - j); 1153 if (ccpfac.nvar >= 1) { 1154 lfe = PolyUtil.<BigInteger> evaluateMain(ccpfac, lfe, Vi); 1155 } else { 1156 lfei = PolyUtil.<BigInteger> evaluateMain(ccpfac.coFac, lfe, Vi); 1157 } 1158 } 1159 //System.out.println("lfe = " + lfe + ", lfei = " + lfei + ", V = " + V); 1160 1161 ln = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1162 un = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1163 for (int jj = 0; jj < lf.size(); jj++) { 1164 GenPolynomial<BigInteger> up = ufactors.get(jj); 1165 BigInteger ui = up.leadingBaseCoefficient(); 1166 BigInteger li = lfei.get(jj); 1167 BigInteger di = ui.gcd(li).abs(); 1168 BigInteger udi = ui.divide(di); 1169 BigInteger ldi = li.divide(di); 1170 GenPolynomial<BigInteger> lp = lf.get(jj); 1171 GenPolynomial<BigInteger> lpd = lp.multiply(udi); 1172 GenPolynomial<BigInteger> upd = up.multiply(ldi); 1173 if (pec.isONE()) { 1174 ln.add(lp); 1175 un.add(up); 1176 } else { 1177 ln.add(lpd); 1178 un.add(upd); 1179 BigInteger pec1 = pec.divide(ldi); 1180 //System.out.println("pec = " + pec + ", pec1 = " + pec1); 1181 pec = pec1; 1182 } 1183 } 1184 if (!lf.equals(ln) || !un.equals(ufactors)) { 1185 logger.debug("!lf.equals(ln) || !un.equals(ufactors)"); 1186 //System.out.println("pe = " + pe); 1187 //System.out.println("#ln = " + ln + ", #lf = " + lf); 1188 //System.out.println("#un = " + un + ", #ufactors = " + ufactors); 1189 //lf = ln; 1190 //ufactors = un; 1191 // adjust pe 1192 } 1193 if (!pec.isONE()) { // still not 1 1194 ln = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1195 un = new ArrayList<GenPolynomial<BigInteger>>(lf.size()); 1196 pes = pe; 1197 for (int jj = 0; jj < lf.size(); jj++) { 1198 GenPolynomial<BigInteger> up = ufactors.get(jj); 1199 GenPolynomial<BigInteger> lp = lf.get(jj); 1200 //System.out.println("up = " + up + ", lp = " + lp); 1201 if (!up.isConstant()) { 1202 up = up.multiply(pec); 1203 } 1204 lp = lp.multiply(pec); 1205 if (jj != 0) { 1206 pes = pes.multiply(pec); 1207 } 1208 un.add(up); 1209 ln.add(lp); 1210 } 1211 if (pes.equals(Power.<GenPolynomial<BigInteger>> multiply(pe.ring, un))) { 1212 //System.out.println("*pe = " + pes + ", pec = " + pec); 1213 //System.out.println("*ln = " + ln + ", *lf = " + lf); 1214 //System.out.println("*un = " + un + ", *ufactors = " + ufactors); 1215 //System.out.println("*pe == prod(un) "); 1216 isPrimitive = false; 1217 //pe = pes; 1218 //lf = ln; 1219 //ufactors = un; 1220 } else { 1221 //System.out.println("*pe != prod(un): " + Power.<GenPolynomial<BigInteger>> multiply(pe.ring,un)); 1222 } 1223 } 1224 } 1225 //if (notLucky) { 1226 // continue; 1227 //} 1228 logger.info("distributed factors of leading coefficient = {}", lf); 1229 lpx = Power.<GenPolynomial<BigInteger>> multiply(lprr.ring, lf); 1230 if (!lprr.abs().equals(lpx.abs())) { // not correctly distributed 1231 if (!lprr.degreeVector().equals(lpx.degreeVector())) { 1232 logger.info("lprr != lpx: lprr = {}, lpx = {}", lprr, lpx); 1233 notLucky = true; 1234 } 1235 } 1236 //logger.warn("V = {}, pe = {}, cei = {}, lf = {}, ln = {}", V, pe, cei, lf, ln); 1237 } // end determine leading coefficients for factors 1238 1239 if (!notLucky) { 1240 TrialParts tp = null; 1241 if (isPrimitive) { 1242 tp = new TrialParts(V, pe, ufactors, cei, lf); 1243 } else { 1244 tp = new TrialParts(V, pes, un, cei, ln); 1245 } 1246 //System.out.println("trialParts = " + tp); 1247 if (tp.univPoly != null) { 1248 if (tp.ldcfEval.size() != 0) { 1249 tParts.add(tp); 1250 } 1251 } 1252 if (tParts.size() < trials) { 1253 notLucky = true; 1254 } 1255 } 1256 } // end notLucky loop 1257 logger.warn("end notLucky loop, trial parts = {}", tParts.size()); 1258 1259 // search TrialParts with shortest factorization of univariate polynomial 1260 int min = Integer.MAX_VALUE; 1261 TrialParts tpmin = null; 1262 for (TrialParts tp : tParts) { 1263 //logger.info("tp.univFactors.size() = {}", tp.univFactors.size()); 1264 if (tp.univFactors.size() < min) { 1265 min = tp.univFactors.size(); 1266 tpmin = tp; 1267 } 1268 } 1269 for (TrialParts tp : tParts) { 1270 if (tp.univFactors.size() == min) { 1271 if (!tp.univFactors.get(0).isConstant()) { 1272 logger.info("tp.univFactors = {}", tp.univFactors); 1273 tpmin = tp; 1274 break; 1275 } 1276 } 1277 } 1278 // set to (first) shortest 1279 V = tpmin.evalPoints; 1280 pe = tpmin.univPoly; 1281 ufactors = tpmin.univFactors; 1282 cei = tpmin.ldcfEval; // unused 1283 lf = tpmin.ldcfFactors; 1284 logger.info("iterations = {}", Math.abs(evStart)); 1285 logger.info("minimal trial = {}", tpmin); 1286 1287 GenPolynomialRing<BigInteger> ufac = pe.ring; 1288 1289 //initialize prime list 1290 PrimeList primes = new PrimeList(PrimeList.Range.medium); // PrimeList.Range.medium); 1291 Iterator<java.math.BigInteger> primeIter = primes.iterator(); 1292 int pn = 50; //primes.size(); 1293 BigInteger ae = pe.leadingBaseCoefficient(); 1294 GenPolynomial<MOD> Pm = null; 1295 ModularRingFactory<MOD> cofac = null; 1296 GenPolynomialRing<MOD> mufac = null; 1297 1298 // search lucky prime 1299 for (int i = 0; i < 11; i++) { // prime meta loop 1300 //for ( int i = 0; i < 1; i++ ) { // meta loop 1301 java.math.BigInteger p = null; //new java.math.BigInteger("19"); //primes.next(); 1302 // 2 small, 5 medium and 4 large size primes 1303 if (i == 0) { // medium size 1304 primes = new PrimeList(PrimeList.Range.medium); 1305 primeIter = primes.iterator(); 1306 } 1307 if (i == 5) { // small size 1308 primes = new PrimeList(PrimeList.Range.small); 1309 primeIter = primes.iterator(); 1310 p = primeIter.next(); // 2 1311 p = primeIter.next(); // 3 1312 p = primeIter.next(); // 5 1313 p = primeIter.next(); // 7 1314 } 1315 if (i == 7) { // large size 1316 primes = new PrimeList(PrimeList.Range.large); 1317 primeIter = primes.iterator(); 1318 } 1319 int pi = 0; 1320 while (pi++ < pn && primeIter.hasNext()) { 1321 p = primeIter.next(); 1322 logger.info("prime = {}", p); 1323 // initialize coefficient factory and map normalization factor and polynomials 1324 ModularRingFactory<MOD> cf = null; 1325 if (ModLongRing.MAX_LONG.compareTo(p) > 0) { 1326 cf = (ModularRingFactory) new ModLongRing(p, true); 1327 } else { 1328 cf = (ModularRingFactory) new ModIntegerRing(p, true); 1329 } 1330 MOD nf = cf.fromInteger(ae.getVal()); 1331 if (nf.isZERO()) { 1332 continue; 1333 } 1334 mufac = new GenPolynomialRing<MOD>(cf, ufac); 1335 //System.out.println("mufac = " + mufac.toScript()); 1336 Pm = PolyUtil.<MOD> fromIntegerCoefficients(mufac, pe); 1337 //System.out.println("Pm = " + Pm); 1338 if (!mfactor.isSquarefree(Pm)) { 1339 continue; 1340 } 1341 cofac = cf; 1342 break; 1343 } 1344 if (cofac != null) { 1345 break; 1346 } 1347 } // end prime meta loop 1348 if (cofac == null) { // no lucky prime found 1349 throw new RuntimeException("giving up on Hensel preparation, no lucky prime found"); 1350 } 1351 logger.info("lucky prime = {}", cofac.getIntegerModul()); 1352 logger.debug("univariate modulo p: = {}", Pm); 1353 1354 // coefficient bound 1355 BigInteger an = pd.maxNorm(); 1356 BigInteger mn = an.multiply(ac.abs()).multiply(new BigInteger(2L)); 1357 long k = Power.logarithm(cofac.getIntegerModul(), mn) + 1L; 1358 //System.out.println("mn = " + mn + ", k = " +k); 1359 1360 BigInteger q = cofac.getIntegerModul().power(k); 1361 ModularRingFactory<MOD> muqfac; 1362 if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { 1363 muqfac = (ModularRingFactory) new ModLongRing(q.getVal()); 1364 } else { 1365 muqfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); 1366 } 1367 //System.out.println("muqfac = " + muqfac); 1368 GenPolynomialRing<MOD> mucpfac = new GenPolynomialRing<MOD>(muqfac, ufac); 1369 1370 List<GenPolynomial<MOD>> muqfactors = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, ufactors); 1371 GenPolynomial<MOD> peqq = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, pe); 1372 if (debug) { 1373 if (!mfactor.isFactorization(peqq, muqfactors)) { // should not happen 1374 System.out.println("muqfactors = " + muqfactors); 1375 System.out.println("peqq = " + peqq); 1376 throw new RuntimeException("something is wrong, no modular p^k factorization"); 1377 } 1378 } 1379 logger.info("univariate modulo p^k: {} = {}", peqq, muqfactors); 1380 1381 // convert C from Z[...] to Z_q[...] 1382 GenPolynomialRing<MOD> qcfac = new GenPolynomialRing<MOD>(muqfac, pd.ring); 1383 GenPolynomial<MOD> pq = PolyUtil.<MOD> fromIntegerCoefficients(qcfac, pd); 1384 //System.out.println("pd = " + pd); 1385 logger.info("multivariate modulo p^k: {}", pq); 1386 1387 //List<MOD> Vm = new ArrayList<MOD>(V.size()); 1388 //for (BigInteger v : V) { 1389 // MOD vm = muqfac.fromInteger(v.getVal()); 1390 // Vm.add(vm); 1391 //} 1392 //System.out.println("Vm = " + Vm); 1393 1394 // Hensel lifting of factors 1395 List<GenPolynomial<MOD>> mlift; 1396 try { 1397 mlift = HenselMultUtil.<MOD> liftHensel(pd, pq, muqfactors, V, k, lf); 1398 logger.info("mlift = {}", mlift); 1399 } catch (NoLiftingException nle) { 1400 //System.out.println("exception : " + nle); 1401 //nle.printStackTrace(); 1402 //mlift = new ArrayList<GenPolynomial<MOD>>(); 1403 throw new RuntimeException(nle); 1404 } catch (ArithmeticException aex) { 1405 //System.out.println("exception : " + aex); 1406 //aex.printStackTrace(); 1407 //mlift = new ArrayList<GenPolynomial<MOD>>(); 1408 throw aex; 1409 } 1410 if (mlift.size() <= 1) { // irreducible mod I, p^k, can this happen? 1411 logger.info("modular lift size == 1: {}", mlift); 1412 factors.add(pd); // P 1413 if (cfactors != null) { 1414 cfactors.addAll(factors); 1415 factors = cfactors; 1416 } 1417 return factors; 1418 } 1419 1420 // combine trial factors 1421 GenPolynomialRing<MOD> mfac = mlift.get(0).ring; 1422 int dl = (mlift.size() + 1) / 2; 1423 GenPolynomial<BigInteger> u = P; 1424 long deg = (u.degree() + 1L) / 2L; 1425 1426 GenPolynomial<BigInteger> ui = pd; 1427 for (int j = 1; j <= dl; j++) { 1428 //System.out.println("j = " + j + ", dl = " + dl + ", mlift = " + mlift); 1429 KsubSet<GenPolynomial<MOD>> subs = new KsubSet<GenPolynomial<MOD>>(mlift, j); 1430 for (List<GenPolynomial<MOD>> flist : subs) { 1431 //System.out.println("degreeSum = " + degreeSum(flist)); 1432 GenPolynomial<MOD> mtrial = Power.<GenPolynomial<MOD>> multiply(mfac, flist); 1433 if (mtrial.degree() > deg) { // this test is sometimes wrong 1434 logger.info("degree > deg {}, degree = {}", deg, mtrial.degree()); 1435 //continue; 1436 } 1437 GenPolynomial<BigInteger> trial = PolyUtil.integerFromModularCoefficients(pfac, mtrial); 1438 trial = engine.basePrimitivePart(trial); 1439 //if ( ! isPrimitive ) { 1440 //} 1441 if (debug) { 1442 logger.info("trial = {}", trial); // + ", mtrial = {}", mtrial); 1443 } 1444 if (PolyUtil.<BigInteger> baseSparsePseudoRemainder(ui, trial).isZERO()) { 1445 logger.info("successful trial = {}", trial); 1446 factors.add(trial); 1447 ui = PolyUtil.<BigInteger> basePseudoDivide(ui, trial); 1448 //System.out.println("ui = " + ui); 1449 mlift = removeOnce(mlift, flist); 1450 logger.info("new mlift= {}", mlift); 1451 //System.out.println("dl = " + dl); 1452 if (mlift.size() > 1) { 1453 dl = (mlift.size() + 1) / 2; 1454 j = 0; // since j++ 1455 break; 1456 } 1457 logger.info("last factor = {}", ui); 1458 factors.add(ui); 1459 if (cfactors != null) { 1460 cfactors.addAll(factors); 1461 factors = cfactors; 1462 } 1463 return normalizeFactorization(factors); 1464 } 1465 } 1466 } 1467 if (!ui.isONE() && !ui.equals(pd)) { 1468 logger.info("rest factor = {}", ui); 1469 // pp(ui) ?? no ?? 1470 factors.add(ui); 1471 } 1472 if (factors.size() == 0) { 1473 logger.info("irreducible P = {}", P); 1474 factors.add(pd); // P 1475 } 1476 if (cfactors != null) { 1477 cfactors.addAll(factors); 1478 factors = cfactors; 1479 } 1480 return normalizeFactorization(factors); 1481 } 1482 1483 1484 /** 1485 * Test if b has a prime factor different to the elements of A. 1486 * @param A list of integer with at least one different prime factor. 1487 * @param b integer to test with A. 1488 * @return true, if b hase a prime factor different to elements of A 1489 */ 1490 boolean testSeparate(List<BigInteger> A, BigInteger b) { 1491 int i = 0; 1492 //List<BigInteger> gei = new ArrayList<BigInteger>(A.size()); 1493 for (BigInteger c : A) { 1494 BigInteger g = c.gcd(b).abs(); 1495 //gei.add(g); 1496 if (!g.isONE()) { 1497 i++; 1498 } 1499 } 1500 //if ( i >= 1 ) { 1501 //System.out.println("gei = " + gei + ", cei = " + cei + ", pec(w) = " + pec); 1502 //} 1503 return (i <= 1); 1504 } 1505 1506 1507 // not useable 1508 boolean isNearlySquarefree(GenPolynomial<BigInteger> P) { // unused 1509 // in main variable 1510 GenPolynomialRing<BigInteger> pfac = P.ring; 1511 if (pfac.nvar >= 0) { // allways true 1512 return sengine.isSquarefree(P); 1513 } 1514 GenPolynomialRing<GenPolynomial<BigInteger>> rfac = pfac.recursive(1); 1515 GenPolynomial<GenPolynomial<BigInteger>> Pr = PolyUtil.<BigInteger> recursive(rfac, P); 1516 GenPolynomial<GenPolynomial<BigInteger>> Ps = PolyUtil.<BigInteger> recursiveDeriviative(Pr); 1517 System.out.println("Pr = " + Pr); 1518 System.out.println("Ps = " + Ps); 1519 GenPolynomial<GenPolynomial<BigInteger>> g = engine.recursiveUnivariateGcd(Pr, Ps); 1520 System.out.println("g_m = " + g); 1521 if (!g.isONE()) { 1522 return false; 1523 } 1524 // in lowest variable 1525 rfac = pfac.recursive(pfac.nvar - 1); 1526 Pr = PolyUtil.<BigInteger> recursive(rfac, P); 1527 Pr = PolyUtil.<BigInteger> switchVariables(Pr); 1528 Ps = PolyUtil.<BigInteger> recursiveDeriviative(Pr); 1529 System.out.println("Pr = " + Pr); 1530 System.out.println("Ps = " + Ps); 1531 g = engine.recursiveUnivariateGcd(Pr, Ps); 1532 System.out.println("g_1 = " + g); 1533 if (!g.isONE()) { 1534 return false; 1535 } 1536 return true; 1537 } 1538 1539} 1540 1541 1542/** 1543 * Container for factorization trial lifting parameters. 1544 */ 1545class TrialParts { 1546 1547 1548 /** 1549 * evaluation points 1550 */ 1551 public final List<BigInteger> evalPoints; 1552 1553 1554 /** 1555 * univariate polynomial 1556 */ 1557 public final GenPolynomial<BigInteger> univPoly; 1558 1559 1560 /** 1561 * irreducible factors of univariate polynomial 1562 */ 1563 public final List<GenPolynomial<BigInteger>> univFactors; 1564 1565 1566 /** 1567 * irreducible factors of leading coefficient 1568 */ 1569 public final List<GenPolynomial<BigInteger>> ldcfFactors; 1570 1571 1572 /** 1573 * evaluated factors of leading coefficient factors by evaluation points 1574 */ 1575 public final List<BigInteger> ldcfEval; 1576 1577 1578 /** 1579 * Constructor. 1580 * @param ev evaluation points. 1581 * @param up univariate polynomial. 1582 * @param uf irreducible factors of up. 1583 * @param le irreducible factors of leading coefficient. 1584 * @param lf evaluated le by evaluation points. 1585 */ 1586 public TrialParts(List<BigInteger> ev, GenPolynomial<BigInteger> up, List<GenPolynomial<BigInteger>> uf, 1587 List<BigInteger> le, List<GenPolynomial<BigInteger>> lf) { 1588 evalPoints = ev; 1589 univPoly = up; 1590 univFactors = uf; 1591 //ldcfPoly = lp; 1592 ldcfFactors = lf; 1593 ldcfEval = le; 1594 } 1595 1596 1597 /** 1598 * @see java.lang.Object#toString() 1599 */ 1600 @Override 1601 public String toString() { 1602 StringBuffer sb = new StringBuffer(); 1603 sb.append("TrialParts["); 1604 sb.append("evalPoints = " + evalPoints); 1605 sb.append(", univPoly = " + univPoly); 1606 sb.append(", univFactors = " + univFactors); 1607 sb.append(", ldcfEval = " + ldcfEval); 1608 sb.append(", ldcfFactors = " + ldcfFactors); 1609 sb.append("]"); 1610 return sb.toString(); 1611 } 1612 1613}