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