001/* 002 * $Id: GreatestCommonDivisorHensel.java 5871 2018-07-20 15:58:45Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.Iterator; 010import java.util.List; 011 012import org.apache.logging.log4j.Logger; 013import org.apache.logging.log4j.LogManager; 014 015import edu.jas.arith.BigInteger; 016import edu.jas.arith.ModIntegerRing; 017import edu.jas.arith.ModLongRing; 018import edu.jas.arith.Modular; 019import edu.jas.arith.ModularRingFactory; 020import edu.jas.arith.PrimeList; 021import edu.jas.poly.ExpVector; 022import edu.jas.poly.GenPolynomial; 023import edu.jas.poly.GenPolynomialRing; 024import edu.jas.poly.PolyUtil; 025import edu.jas.structure.GcdRingElem; 026import edu.jas.structure.NotInvertibleException; 027import edu.jas.structure.Power; 028import edu.jas.structure.RingFactory; 029 030 031// import edu.jas.application.Ideal; 032 033 034/** 035 * Greatest common divisor algorithms with subresultant polynomial remainder 036 * sequence and univariate Hensel lifting. 037 * @author Heinz Kredel 038 */ 039 040public class GreatestCommonDivisorHensel<MOD extends GcdRingElem<MOD> & Modular> 041 extends GreatestCommonDivisorAbstract<BigInteger> { 042 043 044 private static final Logger logger = LogManager.getLogger(GreatestCommonDivisorHensel.class); 045 046 047 private static final boolean debug = logger.isDebugEnabled(); 048 049 050 /** 051 * Flag for linear or quadratic Hensel lift. 052 */ 053 public final boolean quadratic; 054 055 056 /** 057 * Fall back gcd algorithm. 058 */ 059 public final GreatestCommonDivisorAbstract<BigInteger> iufd; 060 061 062 /* 063 * Internal dispatcher. 064 */ 065 private final GreatestCommonDivisorAbstract<BigInteger> ufd; 066 067 068 /** 069 * Constructor. 070 */ 071 public GreatestCommonDivisorHensel() { 072 this(true); 073 } 074 075 076 /** 077 * Constructor. 078 * @param quadratic use quadratic Hensel lift. 079 */ 080 public GreatestCommonDivisorHensel(boolean quadratic) { 081 this.quadratic = quadratic; 082 iufd = new GreatestCommonDivisorSubres<BigInteger>(); 083 ufd = this; //iufd; 084 } 085 086 087 /** 088 * Univariate GenPolynomial greatest comon divisor. Uses univariate Hensel 089 * lifting. 090 * @param P univariate GenPolynomial. 091 * @param S univariate GenPolynomial. 092 * @return gcd(P,S). 093 */ 094 @Override 095 @SuppressWarnings("unchecked") 096 public GenPolynomial<BigInteger> baseGcd(GenPolynomial<BigInteger> P, GenPolynomial<BigInteger> S) { 097 if (S == null || S.isZERO()) { 098 return P; 099 } 100 if (P == null || P.isZERO()) { 101 return S; 102 } 103 if (P.ring.nvar > 1) { 104 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 105 } 106 GenPolynomialRing<BigInteger> fac = P.ring; 107 long e = P.degree(0); 108 long f = S.degree(0); 109 GenPolynomial<BigInteger> q; 110 GenPolynomial<BigInteger> r; 111 if (f > e) { 112 r = P; 113 q = S; 114 long g = f; 115 f = e; 116 e = g; 117 } else { 118 q = P; 119 r = S; 120 } 121 if (debug) { 122 logger.debug("degrees: e = " + e + ", f = " + f); 123 } 124 r = r.abs(); 125 q = q.abs(); 126 // compute contents and primitive parts 127 BigInteger a = baseContent(r); 128 BigInteger b = baseContent(q); 129 // gcd of coefficient contents 130 BigInteger c = gcd(a, b); // indirection 131 r = divide(r, a); // indirection 132 q = divide(q, b); // indirection 133 if (r.isONE()) { 134 return r.multiply(c); 135 } 136 if (q.isONE()) { 137 return q.multiply(c); 138 } 139 // compute normalization factor 140 BigInteger ac = r.leadingBaseCoefficient(); 141 BigInteger bc = q.leadingBaseCoefficient(); 142 BigInteger cc = gcd(ac, bc); // indirection 143 // compute degree vectors, only univeriate 144 ExpVector rdegv = r.degreeVector(); 145 ExpVector qdegv = q.degreeVector(); 146 //initialize prime list and degree vector 147 PrimeList primes = new PrimeList(PrimeList.Range.medium); 148 int pn = 50; //primes.size(); 149 150 ModularRingFactory<MOD> cofac; 151 GenPolynomial<MOD> qm; 152 GenPolynomial<MOD> qmf; 153 GenPolynomial<MOD> rm; 154 GenPolynomial<MOD> rmf; 155 GenPolynomial<MOD> cmf; 156 GenPolynomialRing<MOD> mfac; 157 GenPolynomial<MOD> cm = null; 158 GenPolynomial<MOD>[] ecm = null; 159 GenPolynomial<MOD> sm = null; 160 GenPolynomial<MOD> tm = null; 161 HenselApprox<MOD> lift = null; 162 if (debug) { 163 logger.debug("c = " + c); 164 logger.debug("cc = " + cc); 165 logger.debug("primes = " + primes); 166 } 167 168 int i = 0; 169 for (java.math.BigInteger p : primes) { 170 //System.out.println("next run ++++++++++++++++++++++++++++++++++"); 171 if (++i >= pn) { 172 logger.error("prime list exhausted, pn = " + pn); 173 //logger.info("primes = " + primes); 174 return iufd.baseGcd(P, S); 175 //throw new ArithmeticException("prime list exhausted"); 176 } 177 // initialize coefficient factory and map normalization factor 178 //cofac = new ModIntegerRing(p, true); 179 if (ModLongRing.MAX_LONG.compareTo(p) > 0) { 180 cofac = (ModularRingFactory) new ModLongRing(p, true); 181 } else { 182 cofac = (ModularRingFactory) new ModIntegerRing(p, true); 183 } 184 MOD nf = cofac.fromInteger(cc.getVal()); 185 if (nf.isZERO()) { 186 continue; 187 } 188 nf = cofac.fromInteger(q.leadingBaseCoefficient().getVal()); 189 if (nf.isZERO()) { 190 continue; 191 } 192 nf = cofac.fromInteger(r.leadingBaseCoefficient().getVal()); 193 if (nf.isZERO()) { 194 continue; 195 } 196 // initialize polynomial factory and map polynomials 197 mfac = new GenPolynomialRing<MOD>(cofac, fac.nvar, fac.tord, fac.getVars()); 198 qm = PolyUtil.<MOD> fromIntegerCoefficients(mfac, q); 199 if (!qm.degreeVector().equals(qdegv)) { 200 continue; 201 } 202 rm = PolyUtil.<MOD> fromIntegerCoefficients(mfac, r); 203 if (!rm.degreeVector().equals(rdegv)) { 204 continue; 205 } 206 if (debug) { 207 logger.info("cofac = " + cofac.getIntegerModul()); 208 } 209 210 // compute univariate modular gcd 211 cm = qm.gcd(rm); 212 213 // test for constant g.c.d 214 if (cm.isConstant()) { 215 logger.debug("cm, constant = " + cm); 216 return fac.getONE().multiply(c); 217 } 218 219 // compute factors and gcd with factor 220 GenPolynomial<BigInteger> crq; 221 rmf = rm.divide(cm); // rm = cm * rmf 222 ecm = cm.egcd(rmf); 223 if (ecm[0].isONE()) { 224 //logger.debug("gcd() first factor " + rmf); 225 crq = r; 226 cmf = rmf; 227 sm = ecm[1]; 228 tm = ecm[2]; 229 } else { 230 qmf = qm.divide(cm); // qm = cm * qmf 231 ecm = cm.egcd(qmf); 232 if (ecm[0].isONE()) { 233 //logger.debug("gcd() second factor " + qmf); 234 crq = q; 235 cmf = qmf; 236 sm = ecm[1]; 237 tm = ecm[2]; 238 } else { 239 logger.info("both gcd != 1: Hensel not applicable"); 240 return iufd.baseGcd(P, S); 241 } 242 } 243 BigInteger cn = crq.maxNorm(); 244 cn = cn.multiply(crq.leadingBaseCoefficient().abs()); 245 cn = cn.multiply(cn.fromInteger(2)); 246 if (debug) { 247 System.out.println("crq = " + crq); 248 System.out.println("cm = " + cm); 249 System.out.println("cmf = " + cmf); 250 System.out.println("sm = " + sm); 251 System.out.println("tm = " + tm); 252 System.out.println("cn = " + cn); 253 } 254 try { 255 if (quadratic) { 256 lift = HenselUtil.liftHenselQuadratic(crq, cn, cm, cmf, sm, tm); 257 } else { 258 lift = HenselUtil.liftHensel(crq, cn, cm, cmf, sm, tm); 259 } 260 } catch (NoLiftingException nle) { 261 logger.info("giving up on Hensel gcd reverting to Subres gcd " + nle); 262 return iufd.baseGcd(P, S); 263 } 264 q = lift.A; 265 if (debug) { 266 System.out.println("q = " + q); 267 System.out.println("qf = " + lift.B); 268 } 269 q = basePrimitivePart(q); 270 q = q.multiply(c).abs(); 271 if (PolyUtil.<BigInteger> baseSparsePseudoRemainder(P, q).isZERO() 272 && PolyUtil.<BigInteger> baseSparsePseudoRemainder(S, q).isZERO()) { 273 break; 274 } 275 logger.info("final devision not successfull"); 276 //System.out.println("P rem q = " + PolyUtil.<BigInteger>basePseudoRemainder(P,q)); 277 //System.out.println("S rem q = " + PolyUtil.<BigInteger>basePseudoRemainder(S,q)); 278 //break; 279 } 280 return q; 281 } 282 283 284 /** 285 * Univariate GenPolynomial recursive greatest comon divisor. Uses 286 * multivariate Hensel list. 287 * @param P univariate recursive GenPolynomial. 288 * @param S univariate recursive GenPolynomial. 289 * @return gcd(P,S). 290 */ 291 @Override 292 @SuppressWarnings("unchecked") 293 public GenPolynomial<GenPolynomial<BigInteger>> recursiveUnivariateGcd( 294 GenPolynomial<GenPolynomial<BigInteger>> P, GenPolynomial<GenPolynomial<BigInteger>> S) { 295 if (S == null || S.isZERO()) { 296 return P; 297 } 298 if (P == null || P.isZERO()) { 299 return S; 300 } 301 if (P.ring.nvar > 1) { 302 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 303 } 304 long e = P.degree(0); 305 long f = S.degree(0); 306 GenPolynomial<GenPolynomial<BigInteger>> q, r; //, s; 307 if (f > e) { 308 r = P; 309 q = S; 310 long g = f; 311 f = e; 312 e = g; 313 } else { 314 q = P; 315 r = S; 316 } 317 if (debug) { 318 logger.debug("degrees: e = " + e + ", f = " + f); 319 } 320 r = r.abs(); 321 q = q.abs(); 322 //logger.info("r: " + r + ", q: " + q); 323 324 GenPolynomial<BigInteger> a = ufd.recursiveContent(r); 325 GenPolynomial<BigInteger> b = ufd.recursiveContent(q); 326 327 GenPolynomial<BigInteger> c = ufd.gcd(a, b); // go to recursion 328 //System.out.println("rgcd c = " + c); 329 r = PolyUtil.<BigInteger> recursiveDivide(r, a); 330 q = PolyUtil.<BigInteger> recursiveDivide(q, b); 331 //a = PolyUtil.<BigInteger> basePseudoDivide(a, c); // unused ? 332 //b = PolyUtil.<BigInteger> basePseudoDivide(b, c); // unused ? 333 if (r.isONE()) { 334 return r.multiply(c); 335 } 336 if (q.isONE()) { 337 return q.multiply(c); 338 } 339 // check constant ldcf, TODO general case 340 GenPolynomial<BigInteger> la, lb, lc, lh; 341 la = r.leadingBaseCoefficient(); 342 lb = q.leadingBaseCoefficient(); 343 lc = ufd.gcd(la, lb); 344 //logger.info("la = " + la + ", lb = " + lb + ", lc = " + lc); 345 if (!lc.isConstant()) { 346 //continue; // easy way out 347 GenPolynomial<GenPolynomial<BigInteger>> T = iufd.recursiveUnivariateGcd(r, q); 348 T = T.abs().multiply(c); 349 logger.info("non monic ldcf (" + lc + ") not implemented: " + T + "= gcd(" + r + "," + q + ") * " 350 + c); 351 return T; 352 } 353 354 // convert from Z[y1,...,yr][x] to Z[x][y1,...,yr] to Z[x,y1,...,yr] 355 GenPolynomial<GenPolynomial<BigInteger>> qs = PolyUtil.<BigInteger> switchVariables(q); 356 GenPolynomial<GenPolynomial<BigInteger>> rs = PolyUtil.<BigInteger> switchVariables(r); 357 358 GenPolynomialRing<GenPolynomial<BigInteger>> rfac = qs.ring; 359 RingFactory<GenPolynomial<BigInteger>> rrfac = rfac.coFac; 360 GenPolynomialRing<BigInteger> cfac = (GenPolynomialRing<BigInteger>) rrfac; 361 GenPolynomialRing<BigInteger> dfac = cfac.extend(rfac.getVars()); 362 //System.out.println("pfac = " + P.ring.toScript()); 363 //System.out.println("rfac = " + rfac.toScript()); 364 //System.out.println("dfac = " + dfac.toScript()); 365 GenPolynomial<BigInteger> qd = PolyUtil.<BigInteger> distribute(dfac, qs); 366 GenPolynomial<BigInteger> rd = PolyUtil.<BigInteger> distribute(dfac, rs); 367 368 // compute normalization factor 369 BigInteger ac = rd.leadingBaseCoefficient(); 370 BigInteger bc = qd.leadingBaseCoefficient(); 371 BigInteger cc = gcd(ac, bc); // indirection 372 373 //initialize prime list 374 PrimeList primes = new PrimeList(PrimeList.Range.medium); 375 Iterator<java.math.BigInteger> primeIter = primes.iterator(); 376 int pn = 50; //primes.size(); 377 378 // double check variables 379 // need qe,re,qd,rd,a,b 380 GenPolynomial<BigInteger> ce0 = null; // qe0, re0, 381 382 for (int i = 0; i < 11; i++) { // meta loop 383 //System.out.println("======== run " + dfac.nvar + ", " + i); 384 java.math.BigInteger p = null; //new java.math.BigInteger("19"); //primes.next(); 385 // 5 small, 4 medium and 2 large size primes 386 if (i == 0) { // medium size 387 primes = new PrimeList(PrimeList.Range.medium); 388 primeIter = primes.iterator(); 389 } 390 if (i == 4) { // small size 391 primes = new PrimeList(PrimeList.Range.small); 392 primeIter = primes.iterator(); 393 p = primeIter.next(); // 2 394 p = primeIter.next(); // 3 395 p = primeIter.next(); // 5 396 p = primeIter.next(); // 7 397 } 398 if (i == 9) { // large size 399 primes = new PrimeList(PrimeList.Range.large); 400 primeIter = primes.iterator(); 401 } 402 ModularRingFactory<MOD> cofac = null; 403 int pi = 0; 404 while (pi < pn && primeIter.hasNext()) { 405 p = primeIter.next(); 406 //p = new java.math.BigInteger("19"); 407 logger.info("prime = " + p); 408 // initialize coefficient factory and map normalization factor and polynomials 409 ModularRingFactory<MOD> cf = null; 410 if (ModLongRing.MAX_LONG.compareTo(p) > 0) { 411 cf = (ModularRingFactory) new ModLongRing(p, true); 412 } else { 413 cf = (ModularRingFactory) new ModIntegerRing(p, true); 414 } 415 MOD nf = cf.fromInteger(cc.getVal()); 416 if (nf.isZERO()) { 417 continue; 418 } 419 nf = cf.fromInteger(q.leadingBaseCoefficient().leadingBaseCoefficient().getVal()); 420 if (nf.isZERO()) { 421 continue; 422 } 423 nf = cf.fromInteger(r.leadingBaseCoefficient().leadingBaseCoefficient().getVal()); 424 if (nf.isZERO()) { 425 continue; 426 } 427 cofac = cf; 428 break; 429 } 430 if (cofac == null) { // no lucky prime found 431 GenPolynomial<GenPolynomial<BigInteger>> T = iufd.recursiveUnivariateGcd(q, r); 432 logger.info("no lucky prime, gave up on Hensel: " + T + "= gcd(" + r + "," + q + ")"); 433 return T.abs().multiply(c); //.abs(); 434 } 435 //System.out.println("cofac = " + cofac); 436 437 // search evaluation points and evaluate 438 List<BigInteger> V = new ArrayList<BigInteger>(P.ring.nvar); 439 GenPolynomialRing<BigInteger> ckfac = dfac; 440 GenPolynomial<BigInteger> qe = qd; 441 GenPolynomial<BigInteger> re = rd; 442 GenPolynomial<BigInteger> qei; 443 GenPolynomial<BigInteger> rei; 444 for (int j = dfac.nvar; j > 1; j--) { 445 // evaluation to univariate case 446 long degq = qe.degree(ckfac.nvar - 2); 447 long degr = re.degree(ckfac.nvar - 2); 448 ckfac = ckfac.contract(1); 449 long vi = 1L; //(long)(dfac.nvar-j); // 1L; 0 not so good for small p 450 if (p.longValue() > 1000L) { 451 //vi = (long)j+1L; 452 vi = 0L; 453 } 454 // search small evaluation point 455 while (true) { 456 MOD vp = cofac.fromInteger(vi++); 457 //System.out.println("vp = " + vp); 458 if (vp.isZERO() && vi != 1L) { // all elements of Z_p exhausted 459 qe = null; 460 re = null; 461 break; 462 } 463 BigInteger vii = new BigInteger(vi - 1); 464 qei = PolyUtil.<BigInteger> evaluateMain(ckfac, qe, vii); 465 rei = PolyUtil.<BigInteger> evaluateMain(ckfac, re, vii); 466 //System.out.println("qei = " + qei); 467 //System.out.println("rei = " + rei); 468 469 // check lucky evaluation point 470 if (degq != qei.degree(ckfac.nvar - 1)) { 471 //System.out.println("degv(qe) = " + qe.degreeVector()); 472 //System.out.println("deg(qe) = " + degq + ", deg(qe) = " + qei.degree(ckfac.nvar-1)); 473 continue; 474 } 475 if (degr != rei.degree(ckfac.nvar - 1)) { 476 //System.out.println("degv(re) = " + re.degreeVector()); 477 //System.out.println("deg(re) = " + degr + ", deg(re) = " + rei.degree(ckfac.nvar-1)); 478 continue; 479 } 480 V.add(vii); 481 qe = qei; 482 re = rei; 483 break; 484 } 485 if (qe == null && re == null) { 486 break; 487 } 488 } 489 if (qe == null && re == null) { 490 continue; 491 } 492 logger.info("evaluation points = " + V); 493 494 // recursion base: 495 GenPolynomial<BigInteger> ce = ufd.baseGcd(qe, re); 496 if (ce.isConstant()) { 497 return P.ring.getONE().multiply(c); 498 } 499 logger.info("base gcd = " + ce); 500 501 // double check 502 // need qe,re,qd,rd,a,b 503 if (i == 0) { 504 //qe0 = qe; 505 //re0 = re; 506 ce0 = ce; 507 continue; 508 } 509 long d0 = ce0.degree(0); 510 long d1 = ce.degree(0); 511 //System.out.println("d0, d1 = " + d0 + ", " + d1); 512 if (d1 < d0) { 513 //qe0 = qe; 514 //re0 = re; 515 ce0 = ce; 516 continue; 517 } else if (d1 > d0) { 518 continue; 519 } 520 // d0 == d1 is ok 521 long dx = r.degree(0); 522 //System.out.println("d0, dx = " + d0 + ", " + dx); 523 if (d0 == dx) { // gcd == r ? 524 if (PolyUtil.<BigInteger> recursivePseudoRemainder(q, r).isZERO()) { 525 r = r.abs().multiply(c); //.abs(); 526 logger.info("exit with r | q : " + r); 527 return r; 528 } 529 continue; 530 } 531 // norm 532 BigInteger mn = null; //mn = mn.multiply(cc).multiply(mn.fromInteger(2)); 533 // prepare lifting, chose factor polynomials 534 GenPolynomial<BigInteger> re1 = PolyUtil.<BigInteger> basePseudoDivide(re, ce); 535 GenPolynomial<BigInteger> qe1 = PolyUtil.<BigInteger> basePseudoDivide(qe, ce); 536 GenPolynomial<BigInteger> ui, he; //, pe; 537 GenPolynomial<BigInteger> g, gi, lui; 538 GenPolynomial<BigInteger> gcr, gcq; 539 gcr = ufd.baseGcd(re1, ce); 540 gcq = ufd.baseGcd(qe1, ce); 541 if (gcr.isONE() && gcq.isONE()) { // both gcds == 1: chose smaller ldcf 542 if (la.totalDegree() > lb.totalDegree()) { 543 ui = qd; 544 //s = q; 545 he = qe1; 546 //pe = qe; 547 BigInteger bn = qd.maxNorm(); 548 mn = bn.multiply(cc).multiply(new BigInteger(2L)); 549 g = lb; 550 logger.debug("select deg: ui = qd, g = b"); //, qe1 = " + qe1); // + ", qe = " + qe); 551 } else { 552 ui = rd; 553 //s = r; 554 he = re1; 555 //pe = re; 556 BigInteger an = rd.maxNorm(); 557 mn = an.multiply(cc).multiply(new BigInteger(2L)); 558 g = la; 559 logger.debug("select deg: ui = rd, g = a"); //, re1 = " + re1); // + ", re = " + re); 560 } 561 } else if (gcr.isONE()) { 562 ui = rd; 563 //s = r; 564 he = re1; 565 //pe = re; 566 BigInteger an = rd.maxNorm(); 567 mn = an.multiply(cc).multiply(new BigInteger(2L)); 568 g = la; 569 logger.debug("select: ui = rd, g = a"); //, re1 = " + re1); // + ", re = " + re); 570 } else if (gcq.isONE()) { 571 ui = qd; 572 //s = q; 573 he = qe1; 574 //pe = qe; 575 BigInteger bn = qd.maxNorm(); 576 mn = bn.multiply(cc).multiply(new BigInteger(2L)); 577 g = lb; 578 logger.debug("select: ui = qd, g = b"); //, qe1 = " + qe1); // + ", qe = " + qe); 579 } else { // both gcds != 1: method not applicable 580 logger.info("both gcds != 1: method not applicable"); 581 break; 582 } 583 lui = lc; //s.leadingBaseCoefficient(); 584 lh = PolyUtil.<BigInteger> basePseudoDivide(g, lui); 585 BigInteger ge = PolyUtil.<BigInteger> evaluateAll(g.ring.coFac, lui, V); 586 if (ge.isZERO()) { 587 continue; 588 } 589 BigInteger geh = PolyUtil.<BigInteger> evaluateAll(g.ring.coFac, lh, V); 590 if (geh.isZERO()) { 591 continue; 592 } 593 BigInteger gg = PolyUtil.<BigInteger> evaluateAll(g.ring.coFac, g, V); 594 if (gg.isZERO()) { 595 continue; 596 } 597 //System.out.println("ge = " + ge + ", geh = " + geh + ", gg = " + gg + ", pe = " + pe); 598 // 599 //ce = ce.multiply(geh); //ge); 600 // 601 he = he.multiply(ge); //gg); //ge); //geh); 602 // 603 gi = lui.extendLower(dfac, 0, 0L); //lui. // g. 604 // 605 ui = ui.multiply(gi); // gi !.multiply(gi) 606 //System.out.println("ui = " + ui + ", deg(ui) = " + ui.degreeVector()); 607 //System.out.println("ce = " + ce + ", he = " + he + ", ge = " + ge); 608 logger.info("gcd(ldcf): " + lui + ", ldcf cofactor: " + lh + ", base cofactor: " + he); 609 610 long k = Power.logarithm(new BigInteger(p), mn); 611 //System.out.println("mn = " + mn); 612 //System.out.println("k = " + k); 613 614 BigInteger qp = cofac.getIntegerModul().power(k); 615 ModularRingFactory<MOD> muqfac; 616 if (ModLongRing.MAX_LONG.compareTo(qp.getVal()) > 0) { 617 muqfac = (ModularRingFactory) new ModLongRing(qp.getVal(), true); // nearly a field 618 } else { 619 muqfac = (ModularRingFactory) new ModIntegerRing(qp.getVal(), true); // nearly a field 620 } 621 GenPolynomialRing<MOD> mucpfac = new GenPolynomialRing<MOD>(muqfac, ckfac); 622 //System.out.println("mucpfac = " + mucpfac.toScript()); 623 if (muqfac.fromInteger(ge.getVal()).isZERO()) { 624 continue; 625 } 626 //GenPolynomial<BigInteger> xxx = invertPoly(muqfac,lui,V); 627 //System.out.println("inv(lui) = " + xxx + ", muqfac = " + muqfac + ", lui = " + lui); 628 //ce = ce.multiply(xxx); //.leadingBaseCoefficient()); 629 //xxx = invertPoly(muqfac,lh,V); 630 //System.out.println("inv(lh) = " + xxx + ", muqfac = " + muqfac + ", lh = " + lh); 631 //he = he.multiply(xxx); //.leadingBaseCoefficient()); 632 633 GenPolynomial<MOD> cm = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, ce); 634 GenPolynomial<MOD> hm = PolyUtil.<MOD> fromIntegerCoefficients(mucpfac, he); 635 if (cm.degree(0) != ce.degree(0) || hm.degree(0) != he.degree(0)) { 636 continue; 637 } 638 if (cm.isZERO() || hm.isZERO()) { 639 continue; 640 } 641 logger.info("univariate modulo p^k: " + cm + ", " + hm); 642 643 // convert C from Z[...] to Z_q[...] 644 GenPolynomialRing<MOD> qcfac = new GenPolynomialRing<MOD>(muqfac, dfac); 645 GenPolynomial<MOD> uq = PolyUtil.<MOD> fromIntegerCoefficients(qcfac, ui); 646 if (!ui.leadingExpVector().equals(uq.leadingExpVector())) { 647 logger.info("ev(ui) = " + ui.leadingExpVector() + ", ev(uq) = " + uq.leadingExpVector()); 648 continue; 649 } 650 logger.info("multivariate modulo p^k: " + uq); 651 652 List<GenPolynomial<MOD>> F = new ArrayList<GenPolynomial<MOD>>(2); 653 F.add(cm); 654 F.add(hm); 655 List<GenPolynomial<BigInteger>> G = new ArrayList<GenPolynomial<BigInteger>>(2); 656 G.add(lui.ring.getONE()); //lui: lui.ring.getONE()); // TODO 657 G.add(lui.ring.getONE()); //lh: lui); 658 List<GenPolynomial<MOD>> lift; 659 try { 660 //lift = HenselMultUtil.<MOD> liftHenselFull(ui, F, V, k, G); 661 lift = HenselMultUtil.<MOD> liftHensel(ui, uq, F, V, k, G); 662 logger.info("lift = " + lift); 663 } catch (NoLiftingException nle) { 664 logger.info("NoLiftingException"); 665 //System.out.println("exception : " + nle); 666 continue; 667 } catch (ArithmeticException ae) { 668 logger.info("ArithmeticException"); 669 //System.out.println("exception : " + ae); 670 continue; 671 } catch (NotInvertibleException ni) { 672 logger.info("NotInvertibleException"); 673 //System.out.println("exception : " + ni); 674 continue; 675 } 676 //if (!HenselMultUtil.<MOD> isHenselLift(ui, uq, F, k, lift)) { // not meaningfull test 677 // logger.info("isHenselLift: false"); 678 // //continue; 679 //} 680 681 // convert Ci from Z_{p^k}[x,y1,...,yr] to Z[x,y1,...,yr] to Z[x][y1,...,yr] to Z[y1,...,yr][x] 682 GenPolynomial<BigInteger> ci = PolyUtil.integerFromModularCoefficients(dfac, lift.get(0)); 683 ci = basePrimitivePart(ci); 684 GenPolynomial<GenPolynomial<BigInteger>> Cr = PolyUtil.<BigInteger> recursive(rfac, ci); 685 GenPolynomial<GenPolynomial<BigInteger>> Cs = PolyUtil.<BigInteger> switchVariables(Cr); 686 if (!Cs.ring.equals(P.ring)) { 687 System.out.println("Cs.ring = " + Cs.ring + ", P.ring = " + P.ring); 688 } 689 GenPolynomial<GenPolynomial<BigInteger>> Q = ufd.recursivePrimitivePart(Cs); 690 Q = ufd.baseRecursivePrimitivePart(Q); 691 Q = Q.abs().multiply(c); //.abs(); 692 GenPolynomial<GenPolynomial<BigInteger>> Pq, Sq; 693 Pq = PolyUtil.<BigInteger> recursivePseudoRemainder(P, Q); 694 Sq = PolyUtil.<BigInteger> recursivePseudoRemainder(S, Q); 695 if (Pq.isZERO() && Sq.isZERO()) { 696 logger.info("gcd normal exit: " + Q); 697 return Q; 698 } 699 logger.info("bad Q = " + Q); // + ", Pq = " + Pq + ", Sq = " + Sq); 700 } // end for meta loop 701 // Hensel gcd failed 702 GenPolynomial<GenPolynomial<BigInteger>> T = iufd.recursiveUnivariateGcd(r, q); 703 T = T.abs().multiply(c); 704 logger.info("no lucky prime or evaluation points, gave up on Hensel: " + T + "= gcd(" + r + "," + q 705 + ")"); 706 return T; 707 } 708 709 710 /* move to Ideal ? 711 GenPolynomial<BigInteger> invertPoly(ModularRingFactory<MOD> mfac, GenPolynomial<BigInteger> li, 712 List<BigInteger> V) { 713 if (li == null || li.isZERO()) { 714 throw new RuntimeException("li not invertible: " + li); 715 } 716 if (li.isONE()) { 717 return li; 718 } 719 //System.out.println("mfac = " + mfac + ", V = " + V +", li = " + li); 720 GenPolynomialRing<BigInteger> pfac = li.ring; 721 GenPolynomialRing<MOD> mpfac = new GenPolynomialRing<MOD>(mfac, pfac); 722 GenPolynomial<MOD> lm = PolyUtil.<MOD> fromIntegerCoefficients(mpfac, li); 723 //System.out.println("pfac = " + pfac + ", lm = " + lm); 724 List<GenPolynomial<MOD>> lid = new ArrayList<GenPolynomial<MOD>>(V.size()); 725 int i = 0; 726 for (BigInteger bi : V) { 727 MOD m = mfac.fromInteger(bi.getVal()); 728 GenPolynomial<MOD> mp = mpfac.univariate(i); 729 mp = mp.subtract(m); // X_i - v_i 730 lid.add(mp); 731 i++; 732 } 733 //System.out.println("lid = " + lid); 734 //Ideal<MOD> id = new Ideal<MOD>(mpfac,lid,true); // is a GB 735 //System.out.println("id = " + id); 736 GenPolynomial<MOD> mi = lm; //id.inverse(lm); 737 //System.out.println("mi = " + mi); 738 GenPolynomial<BigInteger> inv = PolyUtil.integerFromModularCoefficients(pfac, mi); 739 return inv; 740 } 741 */ 742 743}