001/* 002 * $Id: HenselMultUtil.java 4111 2012-08-19 12:30:30Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.arith.BigInteger; 014import edu.jas.arith.ModIntegerRing; 015import edu.jas.arith.ModLongRing; 016import edu.jas.arith.Modular; 017import edu.jas.arith.ModularRingFactory; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenPolynomialRing; 020import edu.jas.poly.PolyUtil; 021import edu.jas.ps.PolynomialTaylorFunction; 022import edu.jas.ps.TaylorFunction; 023import edu.jas.ps.UnivPowerSeries; 024import edu.jas.ps.UnivPowerSeriesRing; 025import edu.jas.structure.GcdRingElem; 026import edu.jas.structure.Power; 027import edu.jas.structure.RingFactory; 028 029 030/** 031 * Hensel multivariate lifting utilities. 032 * @author Heinz Kredel 033 */ 034 035public class HenselMultUtil { 036 037 038 private static final Logger logger = Logger.getLogger(HenselMultUtil.class); 039 040 041 private static final boolean debug = logger.isInfoEnabled(); 042 043 044 /** 045 * Modular diophantine equation solution and lifting algorithm. Let p = 046 * A_i.ring.coFac.modul() and assume ggt(A,B) == 1 mod p. 047 * @param A modular GenPolynomial, mod p^k 048 * @param B modular GenPolynomial, mod p^k 049 * @param C modular GenPolynomial, mod p^k 050 * @param V list of substitution values, mod p^k 051 * @param d desired approximation exponent (x_i-v_i)^d. 052 * @param k desired approximation exponent p^k. 053 * @return [s, t] with s A' + t B' = C mod p^k, with A' = B, B' = A. 054 */ 055 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftDiophant( 056 GenPolynomial<MOD> A, GenPolynomial<MOD> B, GenPolynomial<MOD> C, List<MOD> V, long d, 057 long k) throws NoLiftingException { 058 GenPolynomialRing<MOD> pkfac = C.ring; 059 if (pkfac.nvar == 1) { // V, d ignored 060 return HenselUtil.<MOD> liftDiophant(A, B, C, k); 061 } 062 if (!pkfac.equals(A.ring)) { 063 throw new IllegalArgumentException("A.ring != pkfac: " + A.ring + " != " + pkfac); 064 } 065 066 // evaluate at v_n: 067 List<MOD> Vp = new ArrayList<MOD>(V); 068 MOD v = Vp.remove(Vp.size() - 1); 069 //GenPolynomial<MOD> zero = pkfac.getZERO(); 070 // (x_n - v) 071 GenPolynomial<MOD> mon = pkfac.getONE(); 072 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 073 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 074 //System.out.println("xv = " + xv); 075 // A(v), B(v), C(v) 076 ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 077 MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 078 //System.out.println("v = " + v + ", vp = " + vp); 079 GenPolynomialRing<MOD> ckfac = pkfac.contract(1); 080 GenPolynomial<MOD> Ap = PolyUtil.<MOD> evaluateMain(ckfac, A, vp); 081 GenPolynomial<MOD> Bp = PolyUtil.<MOD> evaluateMain(ckfac, B, vp); 082 GenPolynomial<MOD> Cp = PolyUtil.<MOD> evaluateMain(ckfac, C, vp); 083 //System.out.println("Ap = " + Ap); 084 //System.out.println("Bp = " + Bp); 085 //System.out.println("Cp = " + Cp); 086 087 // recursion: 088 List<GenPolynomial<MOD>> su = HenselMultUtil.<MOD> liftDiophant(Ap, Bp, Cp, Vp, d, k); 089 //System.out.println("su@p^" + k + " = " + su); 090 //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); 091 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Bp, Ap, su.get(0), su.get(1), Cp)) { 092 System.out.println("isDiophantLift: false"); 093 } 094 if (!ckfac.equals(su.get(0).ring)) { 095 throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); 096 } 097 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 098 //GenPolynomialRing<BigInteger> cifac = new GenPolynomialRing<BigInteger>(new BigInteger(), ckfac); 099 //System.out.println("ifac = " + ifac.toScript()); 100 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 101 GenPolynomialRing<GenPolynomial<MOD>> qrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 1, mn); 102 //System.out.println("qrfac = " + qrfac); 103 104 List<GenPolynomial<MOD>> sup = new ArrayList<GenPolynomial<MOD>>(su.size()); 105 List<GenPolynomial<BigInteger>> supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 106 for (GenPolynomial<MOD> s : su) { 107 GenPolynomial<MOD> sp = s.extend(pkfac, 0, 0L); 108 sup.add(sp); 109 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, sp); 110 supi.add(spi); 111 } 112 //System.out.println("sup = " + sup); 113 //System.out.println("supi = " + supi); 114 GenPolynomial<BigInteger> Ai = PolyUtil.integerFromModularCoefficients(ifac, A); 115 GenPolynomial<BigInteger> Bi = PolyUtil.integerFromModularCoefficients(ifac, B); 116 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, C); 117 //System.out.println("Ai = " + Ai); 118 //System.out.println("Bi = " + Bi); 119 //System.out.println("Ci = " + Ci); 120 //GenPolynomial<MOD> aq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, Ai); 121 //GenPolynomial<MOD> bq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, Bi); 122 //System.out.println("aq = " + aq); 123 //System.out.println("bq = " + bq); 124 125 // compute error: 126 GenPolynomial<BigInteger> E = Ci; // - sum_i s_i b_i 127 E = E.subtract(Bi.multiply(supi.get(0))); 128 E = E.subtract(Ai.multiply(supi.get(1))); 129 //System.out.println("E = " + E); 130 if (E.isZERO()) { 131 logger.info("liftDiophant leaving on zero E"); 132 return sup; 133 } 134 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 135 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 136 logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); 137 if (Ep.isZERO()) { 138 logger.info("liftDiophant leaving on zero Ep mod p^k"); 139 return sup; 140 } 141 for (int e = 1; e <= d; e++) { 142 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 143 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(qrfac, Ep); 144 //System.out.println("Epr = " + Epr); 145 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>(qrfac); 146 //System.out.println("psfac = " + psfac); 147 TaylorFunction<GenPolynomial<MOD>> F = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 148 //System.out.println("F = " + F); 149 List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 150 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 151 Vs.add(vq); 152 //System.out.println("Vs = " + Vs); 153 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(F, vq); 154 //System.out.println("Epst = " + Epst); 155 GenPolynomial<MOD> cm = Epst.coefficient(e); 156 //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); 157 158 // recursion: 159 List<GenPolynomial<MOD>> S = HenselMultUtil.<MOD> liftDiophant(Ap, Bp, cm, Vp, d, k); 160 //System.out.println("S = " + S); 161 if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { 162 throw new IllegalArgumentException("ckfac != pkfac: " + ckfac.coFac + " != " 163 + S.get(0).ring.coFac); 164 } 165 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, Bp, S.get(1), S.get(0), cm)) { 166 System.out.println("isDiophantLift: false"); 167 } 168 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 169 //System.out.println("mon = " + mon); 170 List<GenPolynomial<MOD>> Sp = new ArrayList<GenPolynomial<MOD>>(S.size()); 171 int i = 0; 172 supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 173 for (GenPolynomial<MOD> dd : S) { 174 //System.out.println("dd = " + dd); 175 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 176 GenPolynomial<MOD> dm = de.multiply(mon); 177 Sp.add(dm); 178 de = sup.get(i).sum(dm); 179 //System.out.println("dd = " + dd); 180 sup.set(i++, de); 181 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, dm); 182 supi.add(spi); 183 } 184 //System.out.println("Sp = " + Sp); 185 //System.out.println("sup = " + sup); 186 //System.out.println("supi = " + supi); 187 // compute new error 188 //E = E; // - sum_i s_i b_i 189 E = E.subtract(Bi.multiply(supi.get(0))); 190 E = E.subtract(Ai.multiply(supi.get(1))); 191 //System.out.println("E = " + E); 192 if (E.isZERO()) { 193 logger.info("liftDiophant leaving on zero E"); 194 return sup; 195 } 196 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 197 //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 198 logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 199 if (Ep.isZERO()) { 200 logger.info("liftDiophant leaving on zero Ep mod p^k"); 201 return sup; 202 } 203 } 204 //System.out.println("*** done: " + pkfac.nvar); 205 return sup; 206 } 207 208 209 /** 210 * Modular diophantine equation solution and lifting algorithm. Let p = 211 * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. 212 * @param A list of modular GenPolynomials, mod p^k 213 * @param C modular GenPolynomial, mod p^k 214 * @param V list of substitution values, mod p^k 215 * @param d desired approximation exponent (x_i-v_i)^d. 216 * @param k desired approximation exponent p^k. 217 * @return [s_1,..., s_n] with sum_i s_i A_i' = C mod p^k, with Ai' = 218 * prod_{j!=i} A_j. 219 */ 220 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftDiophant( 221 List<GenPolynomial<MOD>> A, GenPolynomial<MOD> C, List<MOD> V, long d, long k) 222 throws NoLiftingException { 223 GenPolynomialRing<MOD> pkfac = C.ring; 224 if (pkfac.nvar == 1) { // V, d ignored 225 return HenselUtil.<MOD> liftDiophant(A, C, k); 226 } 227 if (!pkfac.equals(A.get(0).ring)) { 228 throw new IllegalArgumentException("A.ring != pkfac: " + A.get(0).ring + " != " + pkfac); 229 } 230 // co-products 231 GenPolynomial<MOD> As = pkfac.getONE(); 232 for (GenPolynomial<MOD> a : A) { 233 As = As.multiply(a); 234 } 235 List<GenPolynomial<MOD>> Bp = new ArrayList<GenPolynomial<MOD>>(A.size()); 236 for (GenPolynomial<MOD> a : A) { 237 GenPolynomial<MOD> b = PolyUtil.<MOD> basePseudoDivide(As, a); 238 Bp.add(b); 239 } 240 241 // evaluate at v_n: 242 List<MOD> Vp = new ArrayList<MOD>(V); 243 MOD v = Vp.remove(Vp.size() - 1); 244 // (x_n - v) 245 GenPolynomial<MOD> mon = pkfac.getONE(); 246 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 247 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 248 //System.out.println("xv = " + xv); 249 // A(v), B(v), C(v) 250 ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 251 MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 252 //System.out.println("v = " + v + ", vp = " + vp); 253 GenPolynomialRing<MOD> ckfac = pkfac.contract(1); 254 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(A.size()); 255 for (GenPolynomial<MOD> a : A) { 256 GenPolynomial<MOD> ap = PolyUtil.<MOD> evaluateMain(ckfac, a, vp); 257 Ap.add(ap); 258 } 259 GenPolynomial<MOD> Cp = PolyUtil.<MOD> evaluateMain(ckfac, C, vp); 260 //System.out.println("Ap = " + Ap); 261 //System.out.println("Cp = " + Cp); 262 263 // recursion: 264 List<GenPolynomial<MOD>> su = HenselMultUtil.<MOD> liftDiophant(Ap, Cp, Vp, d, k); 265 //System.out.println("su@p^" + k + " = " + su); 266 //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); 267 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, su, Cp)) { 268 System.out.println("isDiophantLift: false"); 269 } 270 if (!ckfac.equals(su.get(0).ring)) { 271 throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); 272 } 273 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 274 //GenPolynomialRing<BigInteger> cifac = new GenPolynomialRing<BigInteger>(new BigInteger(), ckfac); 275 //System.out.println("ifac = " + ifac.toScript()); 276 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 277 GenPolynomialRing<GenPolynomial<MOD>> qrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 1, mn); 278 //System.out.println("qrfac = " + qrfac); 279 280 List<GenPolynomial<MOD>> sup = new ArrayList<GenPolynomial<MOD>>(su.size()); 281 List<GenPolynomial<BigInteger>> supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 282 for (GenPolynomial<MOD> s : su) { 283 GenPolynomial<MOD> sp = s.extend(pkfac, 0, 0L); 284 sup.add(sp); 285 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, sp); 286 supi.add(spi); 287 } 288 //System.out.println("sup = " + sup); 289 //System.out.println("supi = " + supi); 290 List<GenPolynomial<BigInteger>> Ai = new ArrayList<GenPolynomial<BigInteger>>(A.size()); 291 for (GenPolynomial<MOD> a : A) { 292 GenPolynomial<BigInteger> ai = PolyUtil.integerFromModularCoefficients(ifac, a); 293 Ai.add(ai); 294 } 295 List<GenPolynomial<BigInteger>> Bi = new ArrayList<GenPolynomial<BigInteger>>(A.size()); 296 for (GenPolynomial<MOD> b : Bp) { 297 GenPolynomial<BigInteger> bi = PolyUtil.integerFromModularCoefficients(ifac, b); 298 Bi.add(bi); 299 } 300 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, C); 301 //System.out.println("Ai = " + Ai); 302 //System.out.println("Ci = " + Ci); 303 304 List<GenPolynomial<MOD>> Aq = new ArrayList<GenPolynomial<MOD>>(A.size()); 305 for (GenPolynomial<BigInteger> ai : Ai) { 306 GenPolynomial<MOD> aq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, ai); 307 Aq.add(aq); 308 } 309 //System.out.println("Aq = " + Aq); 310 311 // compute error: 312 GenPolynomial<BigInteger> E = Ci; // - sum_i s_i b_i 313 int i = 0; 314 for (GenPolynomial<BigInteger> bi : Bi) { 315 E = E.subtract(bi.multiply(supi.get(i++))); 316 } 317 //System.out.println("E = " + E); 318 if (E.isZERO()) { 319 logger.info("liftDiophant leaving on zero E"); 320 return sup; 321 } 322 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 323 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 324 logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); 325 if (Ep.isZERO()) { 326 logger.info("liftDiophant leaving on zero Ep mod p^k"); 327 return sup; 328 } 329 for (int e = 1; e <= d; e++) { 330 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 331 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(qrfac, Ep); 332 //System.out.println("Epr = " + Epr); 333 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>(qrfac); 334 //System.out.println("psfac = " + psfac); 335 TaylorFunction<GenPolynomial<MOD>> F = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 336 //System.out.println("F = " + F); 337 List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 338 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 339 Vs.add(vq); 340 //System.out.println("Vs = " + Vs); 341 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(F, vq); 342 //System.out.println("Epst = " + Epst); 343 GenPolynomial<MOD> cm = Epst.coefficient(e); 344 //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); 345 if (cm.isZERO()) { 346 continue; 347 } 348 // recursion: 349 List<GenPolynomial<MOD>> S = HenselMultUtil.<MOD> liftDiophant(Ap, cm, Vp, d, k); 350 //System.out.println("S = " + S); 351 if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { 352 throw new IllegalArgumentException("ckfac != pkfac: " + ckfac.coFac + " != " 353 + S.get(0).ring.coFac); 354 } 355 if (pkfac.nvar == 2 && !HenselUtil.<MOD> isDiophantLift(Ap, S, cm)) { 356 System.out.println("isDiophantLift: false"); 357 } 358 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 359 //System.out.println("mon = " + mon); 360 List<GenPolynomial<MOD>> Sp = new ArrayList<GenPolynomial<MOD>>(S.size()); 361 i = 0; 362 supi = new ArrayList<GenPolynomial<BigInteger>>(su.size()); 363 for (GenPolynomial<MOD> dd : S) { 364 //System.out.println("dd = " + dd); 365 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 366 GenPolynomial<MOD> dm = de.multiply(mon); 367 Sp.add(dm); 368 de = sup.get(i).sum(dm); 369 //System.out.println("dd = " + dd); 370 sup.set(i++, de); 371 GenPolynomial<BigInteger> spi = PolyUtil.integerFromModularCoefficients(ifac, dm); 372 supi.add(spi); 373 } 374 //System.out.println("Sp = " + Sp); 375 //System.out.println("sup = " + sup); 376 //System.out.println("supi = " + supi); 377 // compute new error 378 //E = E; // - sum_i s_i b_i 379 i = 0; 380 for (GenPolynomial<BigInteger> bi : Bi) { 381 E = E.subtract(bi.multiply(supi.get(i++))); 382 } 383 //System.out.println("E = " + E); 384 if (E.isZERO()) { 385 logger.info("liftDiophant leaving on zero E"); 386 return sup; 387 } 388 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 389 //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 390 logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); 391 if (Ep.isZERO()) { 392 logger.info("liftDiophant leaving on zero Ep mod p^k"); 393 return sup; 394 } 395 } 396 //System.out.println("*** done: " + pkfac.nvar); 397 return sup; 398 } 399 400 401 /** 402 * Modular Hensel lifting algorithm on coefficients test. Let p = 403 * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with 404 * gcd(f_i,f_j) == 1 mod p for i != j 405 * @param C integer polynomial 406 * @param Cp GenPolynomial mod p^k 407 * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. 408 * @param k approximation exponent. 409 * @param L = [g_0,...,g_{n-1}] list of lifted modular polynomials. 410 * @return true if C = prod_{0,...,n-1} g_i mod p^k, else false. 411 */ 412 public static <MOD extends GcdRingElem<MOD> & Modular> boolean isHenselLift(GenPolynomial<BigInteger> C, 413 GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, long k, List<GenPolynomial<MOD>> L) { 414 boolean t = true; 415 GenPolynomialRing<MOD> qfac = L.get(0).ring; 416 GenPolynomial<MOD> q = qfac.getONE(); 417 for (GenPolynomial<MOD> fi : L) { 418 q = q.multiply(fi); 419 } 420 t = Cp.equals(q); 421 if (!t) { 422 System.out.println("Cp = " + Cp); 423 System.out.println("q = " + q); 424 System.out.println("Cp != q: " + Cp.subtract(q)); 425 return t; 426 } 427 GenPolynomialRing<BigInteger> dfac = C.ring; 428 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(dfac, q); 429 t = C.equals(Ci); 430 if (!t) { 431 System.out.println("C = " + C); 432 System.out.println("Ci = " + Ci); 433 System.out.println("C != Ci: " + C.subtract(Ci)); 434 return t; 435 } 436 // test L mod id(V) == F 437 return t; 438 } 439 440 441 /** 442 * Modular Hensel lifting algorithm, monic case. Let p = 443 * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. 444 * @param C monic GenPolynomial with integer coefficients 445 * @param Cp GenPolynomial mod p^k 446 * @param F list of modular GenPolynomials, mod (I_v, p^k ) 447 * @param V list of substitution values, mod p^k 448 * @param k desired approximation exponent p^k. 449 * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. 450 */ 451 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHenselMonic( 452 GenPolynomial<BigInteger> C, GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, 453 List<MOD> V, long k) throws NoLiftingException { 454 GenPolynomialRing<MOD> pkfac = Cp.ring; 455 //if (pkfac.nvar == 1) { // V ignored 456 // return HenselUtil.<MOD> liftHenselMonic(C,F,k); 457 //} 458 long d = C.degree(); 459 //System.out.println("d = " + d); 460 // prepare stack of polynomial rings and polynomials 461 List<GenPolynomialRing<MOD>> Pfac = new ArrayList<GenPolynomialRing<MOD>>(); 462 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(); 463 List<MOD> Vb = new ArrayList<MOD>(); 464 MOD v = V.get(0); 465 Pfac.add(pkfac); 466 Ap.add(Cp); 467 Vb.add(v); 468 GenPolynomialRing<MOD> pf = pkfac; 469 GenPolynomial<MOD> ap = Cp; 470 for (int j = pkfac.nvar; j > 2; j--) { 471 pf = pf.contract(1); 472 Pfac.add(0, pf); 473 MOD vp = pkfac.coFac.fromInteger(V.get(j - 2).getSymmetricInteger().getVal()); 474 //System.out.println("vp = " + vp); 475 Vb.add(1, vp); 476 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 477 Ap.add(0, ap); 478 } 479 //System.out.println("Pfac = " + Pfac); 480 if (debug) { 481 logger.debug("Pfac = " + Pfac); 482 } 483 //System.out.println("Ap = " + Ap); 484 //System.out.println("V = " + V); 485 //System.out.println("Vb = " + Vb); 486 // setup bi-variate base case 487 GenPolynomialRing<MOD> pk1fac = F.get(0).ring; 488 if (!pkfac.coFac.equals(pk1fac.coFac)) { 489 throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); 490 } 491 // TODO: adjust leading coefficients 492 pkfac = Pfac.get(0); 493 //Cp = Ap.get(0); 494 //System.out.println("pkfac = " + pkfac.toScript()); 495 //System.out.println("pk1fac = " + pk1fac.toScript()); 496 GenPolynomialRing<BigInteger> i1fac = new GenPolynomialRing<BigInteger>(new BigInteger(), pk1fac); 497 //System.out.println("i1fac = " + i1fac.toScript()); 498 List<GenPolynomial<BigInteger>> Bi = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 499 for (GenPolynomial<MOD> b : F) { 500 GenPolynomial<BigInteger> bi = PolyUtil.integerFromModularCoefficients(i1fac, b); 501 Bi.add(bi); 502 } 503 //System.out.println("Bi = " + Bi); 504 // evaluate Cp at v_n: 505 //ModularRingFactory<MOD> cf = (ModularRingFactory<MOD>) pkfac.coFac; 506 //MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); 507 //System.out.println("v = " + v + ", vp = " + vp); 508 GenPolynomialRing<MOD> ckfac; // = pkfac.contract(1); 509 //GenPolynomial<MOD> Cs = PolyUtil.<MOD> evaluateMain(ckfac, Cp, vp); 510 //System.out.println("Cp = " + Cp); 511 //System.out.println("Cs = " + Cs); 512 513 List<GenPolynomial<MOD>> U = new ArrayList<GenPolynomial<MOD>>(F.size()); 514 for (GenPolynomial<MOD> b : F) { 515 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 516 U.add(bi); 517 } 518 //System.out.println("U = " + U); 519 List<GenPolynomial<MOD>> U1 = F; 520 //System.out.println("U1 = " + U1); 521 522 GenPolynomial<BigInteger> E = C.ring.getZERO(); 523 List<MOD> Vh = new ArrayList<MOD>(); 524 525 while (Pfac.size() > 0) { // loop through stack of polynomial rings 526 pkfac = Pfac.remove(0); 527 Cp = Ap.remove(0); 528 v = Vb.remove(0); 529 //Vh.add(0,v); 530 //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + Vh); 531 532 // (x_n - v) 533 GenPolynomial<MOD> mon = pkfac.getONE(); 534 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 535 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 536 //System.out.println("xv = " + xv); 537 538 long deg = Cp.degree(pkfac.nvar - 1); 539 //System.out.println("deg = " + deg); 540 541 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 542 //System.out.println("ifac = " + ifac.toScript()); 543 List<GenPolynomial<BigInteger>> Bip = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 544 for (GenPolynomial<BigInteger> b : Bi) { 545 GenPolynomial<BigInteger> bi = b.extend(ifac, 0, 0L); 546 Bip.add(bi); 547 } 548 Bi = Bip; 549 //System.out.println("Bi = " + Bi); 550 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); 551 //System.out.println("Ci = " + Ci); 552 553 // compute error: 554 E = ifac.getONE(); 555 for (GenPolynomial<BigInteger> bi : Bi) { 556 E = E.multiply(bi); 557 } 558 E = Ci.subtract(E); 559 //System.out.println("E = " + E); 560 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 561 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 562 logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); 563 564 String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; 565 ckfac = pkfac.contract(1); 566 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = new GenPolynomialRing<GenPolynomial<MOD>>(ckfac, 567 1, mn); 568 //System.out.println("pkrfac = " + pkrfac.toScript()); 569 570 for (int e = 1; e <= deg && !Ep.isZERO(); e++) { 571 //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); 572 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(pkrfac, Ep); 573 //System.out.println("Epr = " + Epr); 574 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 575 pkrfac); 576 //System.out.println("psfac = " + psfac); 577 TaylorFunction<GenPolynomial<MOD>> T = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 578 //System.out.println("T = " + T); 579 List<GenPolynomial<MOD>> Vs = new ArrayList<GenPolynomial<MOD>>(1); 580 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 581 Vs.add(vq); 582 //System.out.println("Vs = " + Vs + ", Vh = " + Vh); 583 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(T, vq); 584 //System.out.println("Epst = " + Epst); 585 logger.info("Epst(" + e + "," + deg + ", " + pkfac.nvar + ") = " + Epst); 586 GenPolynomial<MOD> cm = Epst.coefficient(e); 587 //System.out.println("cm = " + cm); 588 if (cm.isZERO()) { 589 continue; 590 } 591 List<GenPolynomial<MOD>> Ud = HenselMultUtil.<MOD> liftDiophant(U1, cm, Vh, d, k); 592 //System.out.println("Ud = " + Ud); 593 594 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 595 //System.out.println("mon = " + mon); 596 List<GenPolynomial<MOD>> Sd = new ArrayList<GenPolynomial<MOD>>(Ud.size()); 597 int i = 0; 598 List<GenPolynomial<BigInteger>> Si = new ArrayList<GenPolynomial<BigInteger>>(Ud.size()); 599 for (GenPolynomial<MOD> dd : Ud) { 600 //System.out.println("dd = " + dd); 601 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 602 GenPolynomial<MOD> dm = de.multiply(mon); 603 Sd.add(dm); 604 de = U.get(i).sum(dm); 605 //System.out.println("de = " + de); 606 U.set(i++, de); 607 GenPolynomial<BigInteger> si = PolyUtil.integerFromModularCoefficients(ifac, de); 608 Si.add(si); 609 } 610 //System.out.println("Sd = " + Sd); 611 //System.out.println("U = " + U); 612 //System.out.println("Si = " + Si); 613 614 // compute new error: 615 E = ifac.getONE(); 616 for (GenPolynomial<BigInteger> bi : Si) { 617 E = E.multiply(bi); 618 } 619 E = Ci.subtract(E); 620 //System.out.println("E = " + E); 621 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 622 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 623 logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); 624 } 625 Vh.add(v); 626 U1 = U; 627 if (Pfac.size() > 0) { 628 List<GenPolynomial<MOD>> U2 = new ArrayList<GenPolynomial<MOD>>(U.size()); 629 pkfac = Pfac.get(0); 630 for (GenPolynomial<MOD> b : U) { 631 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 632 U2.add(bi); 633 } 634 U = U2; 635 //System.out.println("U = " + U); 636 } 637 } 638 if (E.isZERO()) { 639 logger.info("liftHensel leaving with zero E"); 640 } 641 return U; 642 } 643 644 645 /** 646 * Modular Hensel lifting algorithm. Let p = A_i.ring.coFac.modul() and 647 * assume ggt(a,b) == 1 mod p, for a, b in A. 648 * @param C GenPolynomial with integer coefficients 649 * @param Cp GenPolynomial C mod p^k 650 * @param F list of modular GenPolynomials, mod (I_v, p^k ) 651 * @param V list of substitution values, mod p^k 652 * @param k desired approximation exponent p^k. 653 * @param G list of leading coefficients of the factors of C. 654 * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. 655 */ 656 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHensel( 657 GenPolynomial<BigInteger> C, GenPolynomial<MOD> Cp, List<GenPolynomial<MOD>> F, 658 List<MOD> V, long k, List<GenPolynomial<BigInteger>> G) throws NoLiftingException { 659 GenPolynomialRing<MOD> pkfac = Cp.ring; 660 long d = C.degree(); 661 //System.out.println("C = " + C); 662 //System.out.println("Cp = " + Cp); 663 //System.out.println("G = " + G); 664 665 //GenPolynomial<BigInteger> cd = G.get(0); // 1 666 //System.out.println("cd = " + cd + ", ring = " + C.ring); 667 //if ( cd.equals(C.ring.univariate(0)) ) { 668 // System.out.println("cd == G[1]"); 669 //} 670 // G mod p^k, in all variables 671 GenPolynomialRing<MOD> pkfac1 = new GenPolynomialRing<MOD>(pkfac.coFac, G.get(0).ring); 672 List<GenPolynomial<MOD>> Lp = new ArrayList<GenPolynomial<MOD>>(G.size()); 673 for (GenPolynomial<BigInteger> cd1 : G) { 674 GenPolynomial<MOD> cdq = PolyUtil.<MOD> fromIntegerCoefficients(pkfac1, cd1); 675 cdq = cdq.extendLower(pkfac, 0, 0L); // reintroduce lower variable 676 Lp.add(cdq); 677 } 678 logger.info("G modulo p^k: " + Lp); // + ", ring = " + pkfac1); 679 680 // prepare stack of polynomial rings, polynomials and evaluated leading coefficients 681 List<GenPolynomialRing<MOD>> Pfac = new ArrayList<GenPolynomialRing<MOD>>(); 682 List<GenPolynomial<MOD>> Ap = new ArrayList<GenPolynomial<MOD>>(); 683 List<List<GenPolynomial<MOD>>> Gp = new ArrayList<List<GenPolynomial<MOD>>>(); 684 List<MOD> Vb = new ArrayList<MOD>(); 685 //MOD v = V.get(0); 686 Pfac.add(pkfac); 687 Ap.add(Cp); 688 Gp.add(Lp); 689 GenPolynomialRing<MOD> pf = pkfac; 690 //GenPolynomialRing<MOD> pf1 = pkfac1; 691 GenPolynomial<MOD> ap = Cp; 692 List<GenPolynomial<MOD>> Lpp = Lp; 693 for (int j = pkfac.nvar; j > 2; j--) { 694 pf = pf.contract(1); 695 Pfac.add(0, pf); 696 MOD vp = pkfac.coFac.fromInteger(V.get(pkfac.nvar - j).getSymmetricInteger().getVal()); 697 //System.out.println("vp = " + vp); 698 Vb.add(vp); 699 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 700 Ap.add(0, ap); 701 List<GenPolynomial<MOD>> Lps = new ArrayList<GenPolynomial<MOD>>(Lpp.size()); 702 for (GenPolynomial<MOD> qp : Lpp) { 703 GenPolynomial<MOD> qpe = PolyUtil.<MOD> evaluateMain(pf, qp, vp); 704 Lps.add(qpe); 705 } 706 //System.out.println("Lps = " + Lps); 707 Lpp = Lps; 708 Gp.add(0, Lpp); 709 } 710 Vb.add(V.get(pkfac.nvar - 2)); 711 //System.out.println("Pfac = " + Pfac); 712 if (debug) { 713 logger.debug("Pfac = " + Pfac); 714 } 715 //System.out.println("Ap = " + Ap); 716 //System.out.println("Gp = " + Gp); 717 //System.out.println("Gp[0] = " + Gp.get(0) + ", Gp[0].ring = " + Gp.get(0).get(0).ring); 718 //System.out.println("V = " + V); 719 //System.out.println("Vb = " + Vb + ", V == Vb: " + V.equals(Vb)); 720 721 // check bi-variate base case 722 GenPolynomialRing<MOD> pk1fac = F.get(0).ring; 723 if (!pkfac.coFac.equals(pk1fac.coFac)) { 724 throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); 725 } 726 727 // init recursion 728 List<GenPolynomial<MOD>> U = F; 729 //logger.info("to lift U = " + U); // + ", U1.ring = " + U1.get(0).ring); 730 GenPolynomial<BigInteger> E = C.ring.getZERO(); 731 List<MOD> Vh = new ArrayList<MOD>(); 732 List<GenPolynomial<BigInteger>> Si; // = new ArrayList<GenPolynomial<BigInteger>>(F.size()); 733 MOD v = null; 734 735 while (Pfac.size() > 0) { // loop through stack of polynomial rings 736 pkfac = Pfac.remove(0); 737 Cp = Ap.remove(0); 738 Lpp = Gp.remove(0); 739 v = Vb.remove(Vb.size() - 1); // last in stack 740 //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + v); 741 logger.info("stack loop: pkfac = " + pkfac.toScript() + " v = " + v); 742 743 List<GenPolynomial<MOD>> U1 = U; 744 logger.info("to lift U1 = " + U1); // + ", U1.ring = " + U1.get(0).ring); 745 U = new ArrayList<GenPolynomial<MOD>>(U1.size()); 746 747 // update U, replace leading coefficient if required 748 int j = 0; 749 for (GenPolynomial<MOD> b : U1) { 750 //System.out.println("b = " + b + ", b.ring = " + b.ring); 751 GenPolynomial<MOD> bi = b.extend(pkfac, 0, 0L); 752 GenPolynomial<MOD> li = Lpp.get(j); 753 if (!li.isONE()) { 754 //System.out.println("li = " + li + ", li.ring = " + li.ring); 755 //System.out.println("bi = " + bi); 756 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = pkfac.recursive(pkfac.nvar - 1); 757 //System.out.println("pkrfac = " + pkrfac); 758 GenPolynomial<GenPolynomial<MOD>> br = PolyUtil.<MOD> recursive(pkrfac, bi); 759 //System.out.println("br = " + br); 760 GenPolynomial<GenPolynomial<MOD>> bs = PolyUtil.<MOD> switchVariables(br); 761 //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); 762 763 GenPolynomial<GenPolynomial<MOD>> lr = PolyUtil.<MOD> recursive(pkrfac, li); 764 //System.out.println("lr = " + lr); 765 GenPolynomial<GenPolynomial<MOD>> ls = PolyUtil.<MOD> switchVariables(lr); 766 //System.out.println("ls = " + ls + ", ls.ring = " + ls.ring); 767 if (!ls.isConstant()) { 768 throw new RuntimeException("ls not constant " + ls); 769 } 770 bs.doPutToMap(bs.leadingExpVector(), ls.leadingBaseCoefficient()); 771 //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); 772 br = PolyUtil.<MOD> switchVariables(bs); 773 //System.out.println("br = " + br); 774 bi = PolyUtil.<MOD> distribute(pkfac, br); 775 //System.out.println("bi = " + bi); 776 } 777 U.add(bi); 778 j++; 779 } 780 logger.info("U with leading coefficient replaced = " + U); // + ", U.ring = " + U.get(0).ring); 781 782 // (x_n - v) 783 GenPolynomial<MOD> mon = pkfac.getONE(); 784 GenPolynomial<MOD> xv = pkfac.univariate(0, 1); 785 xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); 786 //System.out.println("xv = " + xv); 787 788 long deg = Cp.degree(pkfac.nvar - 1); 789 //System.out.println("deg = " + deg + ", degv = " + Cp.degreeVector()); 790 791 // convert to integer polynomials 792 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pkfac); 793 //System.out.println("ifac = " + ifac.toScript()); 794 List<GenPolynomial<BigInteger>> Bi = PolyUtil.integerFromModularCoefficients(ifac, U); 795 //System.out.println("Bi = " + Bi); 796 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); 797 //System.out.println("Ci = " + Ci); 798 799 // compute error: 800 E = ifac.getONE(); 801 for (GenPolynomial<BigInteger> bi : Bi) { 802 E = E.multiply(bi); 803 } 804 //System.out.println("E = " + E); 805 E = Ci.subtract(E); 806 //System.out.println("E = " + E); 807 GenPolynomial<MOD> Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 808 logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); 809 810 GenPolynomialRing<GenPolynomial<MOD>> pkrfac = pkfac.recursive(1); 811 GenPolynomialRing<MOD> ckfac = (GenPolynomialRing<MOD>) pkrfac.coFac; 812 //System.out.println("pkrfac = " + pkrfac.toScript()); 813 814 for (int e = 1; e <= deg && !Ep.isZERO(); e++) { 815 //System.out.println("\ne = " + e + " -------------------------------------- " + deg); 816 logger.info("approximation loop: e = " + e + " of deg = " + deg); 817 GenPolynomial<GenPolynomial<MOD>> Epr = PolyUtil.<MOD> recursive(pkrfac, Ep); 818 //System.out.println("Epr = " + Epr); 819 UnivPowerSeriesRing<GenPolynomial<MOD>> psfac = new UnivPowerSeriesRing<GenPolynomial<MOD>>( 820 pkrfac); 821 //System.out.println("psfac = " + psfac); 822 TaylorFunction<GenPolynomial<MOD>> T = new PolynomialTaylorFunction<GenPolynomial<MOD>>(Epr); 823 //System.out.println("T = " + T); 824 GenPolynomial<MOD> vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); 825 //System.out.println("vq = " + vq + ", Vh = " + Vh); 826 UnivPowerSeries<GenPolynomial<MOD>> Epst = psfac.seriesOfTaylor(T, vq); 827 //System.out.println("Epst = " + Epst); 828 logger.info("Epst(" + e + "," + deg + "," + pkfac.nvar + ") = " + Epst); 829 GenPolynomial<MOD> cm = Epst.coefficient(e); 830 if (cm.isZERO()) { 831 //System.out.println("cm = " + cm); 832 continue; 833 } 834 List<GenPolynomial<MOD>> Ud = HenselMultUtil.<MOD> liftDiophant(U1, cm, Vh, d, k); 835 //System.out.println("Ud = " + Ud); 836 837 mon = mon.multiply(xv); // Power.<GenPolynomial<MOD>> power(pkfac,xv,e); 838 //System.out.println("mon = " + mon); 839 List<GenPolynomial<MOD>> Sd = new ArrayList<GenPolynomial<MOD>>(Ud.size()); 840 int i = 0; 841 Si = new ArrayList<GenPolynomial<BigInteger>>(Ud.size()); 842 for (GenPolynomial<MOD> dd : Ud) { 843 //System.out.println("dd = " + dd); 844 GenPolynomial<MOD> de = dd.extend(pkfac, 0, 0L); 845 GenPolynomial<MOD> dm = de.multiply(mon); 846 Sd.add(dm); 847 de = U.get(i).sum(dm); 848 //System.out.println("de = " + de); 849 U.set(i++, de); 850 GenPolynomial<BigInteger> si = PolyUtil.integerFromModularCoefficients(ifac, de); 851 Si.add(si); 852 } 853 //System.out.println("Sd = " + Sd); 854 //System.out.println("U = " + U + ", U.ring = " + U.get(0).ring); 855 //System.out.println("Si = " + Si); 856 857 // compute new error: 858 E = ifac.getONE(); 859 for (GenPolynomial<BigInteger> bi : Si) { 860 E = E.multiply(bi); 861 } 862 E = Ci.subtract(E); 863 //System.out.println("E = " + E); 864 Ep = PolyUtil.<MOD> fromIntegerCoefficients(pkfac, E); 865 //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); 866 logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); 867 } 868 Vh.add(v); 869 GenPolynomial<MOD> Uf = U.get(0).ring.getONE(); 870 for (GenPolynomial<MOD> Upp : U) { 871 Uf = Uf.multiply(Upp); 872 } 873 if (false && !Cp.equals(Uf)) { 874 System.out.println("\nU = " + U); 875 System.out.println("Cp = " + Cp); 876 System.out.println("Uf = " + Uf); 877 System.out.println("isFactorization: " + Cp.equals(Uf) + ", Cp.ring = " + Cp.ring 878 + ", Uf.ring = " + Uf.ring); 879 throw new RuntimeException("no factorization, something is wrong"); 880 } 881 } 882 if (E.isZERO()) { 883 logger.info("liftHensel leaving with zero E, Ep"); 884 } 885 if (false && debug) { 886 // remove normalization required ?? 887 GreatestCommonDivisorAbstract<BigInteger> ufd = GCDFactory.getImplementation(new BigInteger()); 888 List<GenPolynomial<BigInteger>> Fii = new ArrayList<GenPolynomial<BigInteger>>(U.size()); 889 for (GenPolynomial<BigInteger> bi : Si) { 890 GenPolynomial<BigInteger> ci = ufd.content(bi); //ufd.primitivePart(bi); // ?? 891 if (!ci.isONE()) { 892 System.out.println("bi = " + bi + ", cont(bi) = " + ci); 893 } 894 //Fii.add(ci); 895 } 896 //Si = Fii; 897 //System.out.println("Si = " + Si); 898 } 899 logger.info("multivariate lift = " + U + ", of " + F); 900 return U; 901 } 902 903 904 /** 905 * Modular Hensel full lifting algorithm. Let p = A_i.ring.coFac.modul() and 906 * assume ggt(a,b) == 1 mod p, for a, b in A. 907 * @param C GenPolynomial with integer coefficients 908 * @param F list of modular GenPolynomials, mod (I_v, p ) 909 * @param V list of substitution values, mod p^k 910 * @param k desired approximation exponent p^k. 911 * @param G = [g_1,...,g_n] list of factors of leading coefficients. 912 * @return [c_1,..., c_n] with prod_i c_i = C mod p^k. 913 */ 914 public static <MOD extends GcdRingElem<MOD> & Modular> List<GenPolynomial<MOD>> liftHenselFull( 915 GenPolynomial<BigInteger> C, List<GenPolynomial<MOD>> F, List<MOD> V, long k, 916 List<GenPolynomial<BigInteger>> G) throws NoLiftingException { 917 if (F == null || F.size() == 0) { 918 return new ArrayList<GenPolynomial<MOD>>(); 919 } 920 GenPolynomialRing<MOD> pkfac = F.get(0).ring; 921 //long d = C.degree(); 922 // setup q = p^k 923 RingFactory<MOD> cfac = pkfac.coFac; 924 ModularRingFactory<MOD> pcfac = (ModularRingFactory<MOD>) cfac; 925 //System.out.println("pcfac = " + pcfac); 926 BigInteger p = pcfac.getIntegerModul(); 927 BigInteger q = Power.positivePower(p, k); 928 ModularRingFactory<MOD> mcfac; 929 if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { 930 mcfac = (ModularRingFactory) new ModLongRing(q.getVal()); 931 } else { 932 mcfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); 933 } 934 //System.out.println("mcfac = " + mcfac); 935 936 // convert C from Z[...] to Z_q[...] 937 GenPolynomialRing<MOD> qcfac = new GenPolynomialRing<MOD>(mcfac, C.ring); 938 GenPolynomial<MOD> Cq = PolyUtil.<MOD> fromIntegerCoefficients(qcfac, C); 939 //System.out.println("C = " + C); 940 //System.out.println("Cq = " + Cq); 941 942 // convert g_i from Z[...] to Z_q[...] 943 GenPolynomialRing<MOD> gcfac = new GenPolynomialRing<MOD>(mcfac, G.get(0).ring); 944 List<GenPolynomial<MOD>> GQ = new ArrayList<GenPolynomial<MOD>>(); 945 boolean allOnes = true; 946 for (GenPolynomial<BigInteger> g : G) { 947 if (!g.isONE()) { 948 allOnes = false; 949 } 950 GenPolynomial<MOD> gq = PolyUtil.<MOD> fromIntegerCoefficients(gcfac, g); 951 GQ.add(gq); 952 } 953 //System.out.println("G = " + G); 954 //System.out.println("GQ = " + GQ); 955 956 // evaluate C to Z_q[x] 957 GenPolynomialRing<MOD> pf = qcfac; 958 GenPolynomial<MOD> ap = Cq; 959 for (int j = C.ring.nvar; j > 1; j--) { 960 pf = pf.contract(1); 961 MOD vp = mcfac.fromInteger(V.get(C.ring.nvar - j).getSymmetricInteger().getVal()); 962 //System.out.println("vp = " + vp); 963 ap = PolyUtil.<MOD> evaluateMain(pf, ap, vp); 964 //System.out.println("ap = " + ap); 965 } 966 GenPolynomial<MOD> Cq1 = ap; 967 //System.out.println("Cq1 = " + Cq1); 968 if (Cq1.isZERO()) { 969 throw new NoLiftingException("C mod (I, p^k) == 0: " + C); 970 } 971 GenPolynomialRing<BigInteger> ifac = new GenPolynomialRing<BigInteger>(new BigInteger(), pf); 972 GenPolynomial<BigInteger> Ci = PolyUtil.integerFromModularCoefficients(ifac, Cq1); 973 //System.out.println("Ci = " + Ci); 974 GreatestCommonDivisorAbstract<BigInteger> ufd = GCDFactory.getImplementation(new BigInteger()); 975 Ci = Ci.abs(); 976 BigInteger cCi = ufd.baseContent(Ci); 977 Ci = Ci.divide(cCi); 978 //System.out.println("cCi = " + cCi); 979 //System.out.println("Ci = " + Ci); 980 ////System.out.println("F.fac = " + F.get(0).ring); 981 982 // evaluate G to Z_q 983 List<GenPolynomial<MOD>> GP = new ArrayList<GenPolynomial<MOD>>(); 984 for (GenPolynomial<MOD> gq : GQ) { 985 GenPolynomialRing<MOD> gf = gcfac; 986 GenPolynomial<MOD> gp = gq; 987 for (int j = gcfac.nvar; j > 1; j--) { 988 gf = gf.contract(1); 989 MOD vp = mcfac.fromInteger(V.get(gcfac.nvar - j).getSymmetricInteger().getVal()); 990 //System.out.println("vp = " + vp); 991 gp = PolyUtil.<MOD> evaluateMain(gf, gp, vp); 992 //System.out.println("gp = " + gp); 993 } 994 GP.add(gp); 995 } 996 //System.out.println("GP = " + GP); // + ", GP.ring = " + GP.get(0).ring); 997 998 // leading coefficient for recursion base, for Cq1 and list GP 999 BigInteger gi0 = Ci.leadingBaseCoefficient(); // gq0.getSymmetricInteger(); 1000 //System.out.println("gi0 = " + gi0); 1001 1002 // lift F to Z_{p^k}[x] 1003 //System.out.println("Ci = " + Ci + ", F = " + F + ", k = " + k + ", p = " + F.get(0).ring + ", gi0 = " + gi0); 1004 List<GenPolynomial<MOD>> U1 = null; 1005 if (gi0.isONE()) { 1006 U1 = HenselUtil.<MOD> liftHenselMonic(Ci, F, k); 1007 } else { 1008 U1 = HenselUtil.<MOD> liftHensel(Ci, F, k, gi0); // GI0 TODO ?? 1009 } 1010 logger.info("univariate lift: Ci = " + Ci + ", F = " + F + ", U1 = " + U1); 1011 //System.out.println("U1.fac = " + U1.get(0).ring); 1012 1013 // adjust leading coefficients of U1 with F 1014 List<GenPolynomial<BigInteger>> U1i = PolyUtil.<MOD> integerFromModularCoefficients(Ci.ring, U1); 1015 //System.out.println("U1i = " + U1i); 1016 boolean t = HenselUtil.isHenselLift(Ci, q, p, U1i); 1017 //System.out.println("isLift(U1) = " + t); 1018 if (!t) { 1019 //System.out.println("NoLiftingException, Ci = " + Ci + ", U1i = " + U1i); 1020 throw new NoLiftingException("Ci = " + Ci + ", U1i = " + U1i); 1021 } 1022 MOD cC = mcfac.fromInteger(cCi.getVal()); 1023 List<GenPolynomial<MOD>> U1f = PolyUtil.<MOD> fromIntegerCoefficients(F.get(0).ring, U1i); 1024 //System.out.println("U1f = " + U1f); 1025 List<GenPolynomial<MOD>> U1s = new ArrayList<GenPolynomial<MOD>>(U1.size()); 1026 int j = 0; 1027 int s = 0; 1028 for (GenPolynomial<MOD> u : U1) { 1029 GenPolynomial<MOD> uf = U1f.get(j); 1030 GenPolynomial<MOD> f = F.get(j); 1031 GenPolynomial<BigInteger> ui = U1i.get(j); 1032 GenPolynomial<BigInteger> gi = G.get(j); 1033 if (ui.signum() != gi.signum()) { 1034 //System.out.println("ui = " + ui + ", gi = " + gi); 1035 u = u.negate(); 1036 uf = uf.negate(); 1037 s++; 1038 } 1039 j++; 1040 if (uf.isConstant()) { 1041 //System.out.println("u = " + u); 1042 u = u.monic(); 1043 //System.out.println("u = " + u); 1044 u = u.multiply(cC); 1045 cC = cC.divide(cC); 1046 //System.out.println("u = " + u); 1047 } else { 1048 MOD x = f.leadingBaseCoefficient().divide(uf.leadingBaseCoefficient()); 1049 //System.out.println("x = " + x + ", xi = " + x.getSymmetricInteger()); 1050 if (!x.isONE()) { 1051 MOD xq = mcfac.fromInteger(x.getSymmetricInteger().getVal()); 1052 //System.out.println("xq = " + xq); 1053 u = u.multiply(xq); 1054 cC = cC.divide(xq); 1055 //System.out.println("cC = " + cC); 1056 } 1057 } 1058 U1s.add(u); 1059 } 1060 //if ( s % 2 != 0 || !cC.isONE()) { 1061 if (!cC.isONE()) { 1062 throw new NoLiftingException("s = " + s + ", Ci = " + Ci + ", U1i = " + U1i + ", cC = " + cC); 1063 } 1064 U1 = U1s; 1065 U1i = PolyUtil.<MOD> integerFromModularCoefficients(Ci.ring, U1); 1066 //System.out.println("U1i = " + U1i); 1067 U1f = PolyUtil.<MOD> fromIntegerCoefficients(F.get(0).ring, U1i); 1068 if (!F.equals(U1f)) { // evtl loop until reached 1069 System.out.println("F = " + F); 1070 System.out.println("U1f = " + U1f); 1071 throw new NoLiftingException("F = " + F + ", U1f = " + U1f); 1072 } 1073 logger.info("multivariate lift: U1 = " + U1); 1074 1075 // lift U to Z_{p^k}[x,...] 1076 //System.out.println("C = " + C + ", U1 = " + U1 + ", V = " + V + ", k = " + k + ", q = " + U1.get(0).ring + ", G = " + G); 1077 List<GenPolynomial<MOD>> U = null; 1078 if (allOnes) { 1079 U = HenselMultUtil.<MOD> liftHenselMonic(C, Cq, U1, V, k); 1080 } else { 1081 U = HenselMultUtil.<MOD> liftHensel(C, Cq, U1, V, k, G); 1082 } 1083 logger.info("multivariate lift: C = " + C + ", U1 = " + U1 + ", U = " + U); 1084 //System.out.println("U = " + U); 1085 //System.out.println("U.fac = " + U.get(0).ring); 1086 return U; 1087 } 1088 1089}