001/* 002 * $Id: PolyUfdUtil.java 5871 2018-07-20 15:58:45Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.List; 011import java.util.Map; 012 013import org.apache.logging.log4j.Logger; 014import org.apache.logging.log4j.LogManager; 015 016import edu.jas.arith.BigInteger; 017import edu.jas.arith.BigRational; 018import edu.jas.poly.AlgebraicNumber; 019import edu.jas.poly.AlgebraicNumberRing; 020import edu.jas.poly.ExpVector; 021import edu.jas.poly.GenPolynomial; 022import edu.jas.poly.GenPolynomialRing; 023import edu.jas.poly.PolyUtil; 024import edu.jas.poly.TermOrderByName; 025import edu.jas.structure.GcdRingElem; 026import edu.jas.structure.RingElem; 027import edu.jas.structure.RingFactory; 028import edu.jas.structure.UnaryFunctor; 029import edu.jas.util.ListUtil; 030 031 032/** 033 * Polynomial ufd utilities. For example conversion between different representations 034 * and Kronecker substitution. 035 * @author Heinz Kredel 036 */ 037 038public class PolyUfdUtil { 039 040 041 private static final Logger logger = LogManager.getLogger(PolyUfdUtil.class); 042 043 044 private static final boolean debug = logger.isDebugEnabled(); 045 046 047 /** 048 * Integral polynomial from rational function coefficients. Represent as 049 * polynomial with integral polynomial coefficients by multiplication with 050 * the lcm of the numerators of the rational function coefficients. 051 * @param fac result polynomial factory. 052 * @param A polynomial with rational function coefficients to be converted. 053 * @return polynomial with integral polynomial coefficients. 054 */ 055 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> integralFromQuotientCoefficients( 056 GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<Quotient<C>> A) { 057 GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy(); 058 if (A == null || A.isZERO()) { 059 return B; 060 } 061 GenPolynomial<C> c = null; 062 GenPolynomial<C> d; 063 GenPolynomial<C> x; 064 GreatestCommonDivisor<C> ufd = new GreatestCommonDivisorSubres<C>(); 065 int s = 0; 066 // lcm of denominators 067 for (Quotient<C> y : A.getMap().values()) { 068 x = y.den; 069 // c = lcm(c,x) 070 if (c == null) { 071 c = x; 072 s = x.signum(); 073 } else { 074 d = ufd.gcd(c, x); 075 c = c.multiply(x.divide(d)); 076 } 077 } 078 if (s < 0) { 079 c = c.negate(); 080 } 081 for (Map.Entry<ExpVector, Quotient<C>> y : A.getMap().entrySet()) { 082 ExpVector e = y.getKey(); 083 Quotient<C> a = y.getValue(); 084 // p = n*(c/d) 085 GenPolynomial<C> b = c.divide(a.den); 086 GenPolynomial<C> p = a.num.multiply(b); 087 //B = B.sum( p, e ); // inefficient 088 B.doPutToMap(e, p); 089 } 090 return B; 091 } 092 093 094 /** 095 * Integral polynomial from rational function coefficients. Represent as 096 * polynomial with integral polynomial coefficients by multiplication with 097 * the lcm of the numerators of the rational function coefficients. 098 * @param fac result polynomial factory. 099 * @param L list of polynomial with rational function coefficients to be 100 * converted. 101 * @return list of polynomials with integral polynomial coefficients. 102 */ 103 public static <C extends GcdRingElem<C>> List<GenPolynomial<GenPolynomial<C>>> integralFromQuotientCoefficients( 104 GenPolynomialRing<GenPolynomial<C>> fac, Collection<GenPolynomial<Quotient<C>>> L) { 105 if (L == null) { 106 return null; 107 } 108 List<GenPolynomial<GenPolynomial<C>>> list = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size()); 109 for (GenPolynomial<Quotient<C>> p : L) { 110 list.add(integralFromQuotientCoefficients(fac, p)); 111 } 112 return list; 113 } 114 115 116 /** 117 * Rational function from integral polynomial coefficients. Represent as 118 * polynomial with type Quotient<C> coefficients. 119 * @param fac result polynomial factory. 120 * @param A polynomial with integral polynomial coefficients to be 121 * converted. 122 * @return polynomial with type Quotient<C> coefficients. 123 */ 124 public static <C extends GcdRingElem<C>> GenPolynomial<Quotient<C>> quotientFromIntegralCoefficients( 125 GenPolynomialRing<Quotient<C>> fac, GenPolynomial<GenPolynomial<C>> A) { 126 GenPolynomial<Quotient<C>> B = fac.getZERO().copy(); 127 if (A == null || A.isZERO()) { 128 return B; 129 } 130 RingFactory<Quotient<C>> cfac = fac.coFac; 131 QuotientRing<C> qfac = (QuotientRing<C>) cfac; 132 for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.getMap().entrySet()) { 133 ExpVector e = y.getKey(); 134 GenPolynomial<C> a = y.getValue(); 135 Quotient<C> p = new Quotient<C>(qfac, a); // can not be zero 136 if (!p.isZERO()) { 137 //B = B.sum( p, e ); // inefficient 138 B.doPutToMap(e, p); 139 } 140 } 141 return B; 142 } 143 144 145 /** 146 * Rational function from integral polynomial coefficients. Represent as 147 * polynomial with type Quotient<C> coefficients. 148 * @param fac result polynomial factory. 149 * @param L list of polynomials with integral polynomial coefficients to be 150 * converted. 151 * @return list of polynomials with type Quotient<C> coefficients. 152 */ 153 public static <C extends GcdRingElem<C>> List<GenPolynomial<Quotient<C>>> quotientFromIntegralCoefficients( 154 GenPolynomialRing<Quotient<C>> fac, Collection<GenPolynomial<GenPolynomial<C>>> L) { 155 if (L == null) { 156 return null; 157 } 158 List<GenPolynomial<Quotient<C>>> list = new ArrayList<GenPolynomial<Quotient<C>>>(L.size()); 159 for (GenPolynomial<GenPolynomial<C>> p : L) { 160 list.add(quotientFromIntegralCoefficients(fac, p)); 161 } 162 return list; 163 } 164 165 166 /** 167 * From BigInteger coefficients. Represent as polynomial with type 168 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 169 * @param fac result polynomial factory. 170 * @param A polynomial with GenPolynomial<BigInteger> coefficients to 171 * be converted. 172 * @return polynomial with type GenPolynomial<C> coefficients. 173 */ 174 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> fromIntegerCoefficients( 175 GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<GenPolynomial<BigInteger>> A) { 176 GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy(); 177 if (A == null || A.isZERO()) { 178 return B; 179 } 180 RingFactory<GenPolynomial<C>> cfac = fac.coFac; 181 GenPolynomialRing<C> rfac = (GenPolynomialRing<C>) cfac; 182 for (Map.Entry<ExpVector, GenPolynomial<BigInteger>> y : A.getMap().entrySet()) { 183 ExpVector e = y.getKey(); 184 GenPolynomial<BigInteger> a = y.getValue(); 185 GenPolynomial<C> p = PolyUtil.<C> fromIntegerCoefficients(rfac, a); 186 if (!p.isZERO()) { 187 //B = B.sum( p, e ); // inefficient 188 B.doPutToMap(e, p); 189 } 190 } 191 return B; 192 } 193 194 195 /** 196 * From BigInteger coefficients. Represent as polynomial with type 197 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 198 * @param fac result polynomial factory. 199 * @param L polynomial list with GenPolynomial<BigInteger> 200 * coefficients to be converted. 201 * @return polynomial list with polynomials with type GenPolynomial<C> 202 * coefficients. 203 */ 204 public static <C extends RingElem<C>> List<GenPolynomial<GenPolynomial<C>>> fromIntegerCoefficients( 205 GenPolynomialRing<GenPolynomial<C>> fac, List<GenPolynomial<GenPolynomial<BigInteger>>> L) { 206 List<GenPolynomial<GenPolynomial<C>>> K = null; 207 if (L == null) { 208 return K; 209 } 210 K = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size()); 211 if (L.size() == 0) { 212 return K; 213 } 214 for (GenPolynomial<GenPolynomial<BigInteger>> a : L) { 215 GenPolynomial<GenPolynomial<C>> b = fromIntegerCoefficients(fac, a); 216 K.add(b); 217 } 218 return K; 219 } 220 221 //------------------------------ 222 223 /** 224 * BigInteger from BigRational coefficients. Represent as polynomial with type 225 * GenPolynomial<BigInteger> coefficients. 226 * @param fac result polynomial factory. 227 * @param A polynomial with GenPolynomial<BigRational> coefficients to 228 * be converted. 229 * @return polynomial with type GenPolynomial<BigInteger> coefficients. 230 */ 231 public static GenPolynomial<GenPolynomial<BigInteger>> integerFromRationalCoefficients( 232 GenPolynomialRing<GenPolynomial<BigInteger>> fac, GenPolynomial<GenPolynomial<BigRational>> A) { 233 GenPolynomial<GenPolynomial<BigInteger>> B = fac.getZERO().copy(); 234 if (A == null || A.isZERO()) { 235 return B; 236 } 237 java.math.BigInteger gcd = null; 238 java.math.BigInteger lcm = null; 239 int sLCM = 0; 240 int sGCD = 0; 241 // lcm of all denominators 242 for (GenPolynomial<BigRational> av : A.getMap().values()) { 243 for (BigRational y : av.getMap().values()) { 244 java.math.BigInteger numerator = y.numerator(); 245 java.math.BigInteger denominator = y.denominator(); 246 // lcm = lcm(lcm,x) 247 if (lcm == null) { 248 lcm = denominator; 249 sLCM = denominator.signum(); 250 } else { 251 java.math.BigInteger d = lcm.gcd(denominator); 252 lcm = lcm.multiply(denominator.divide(d)); 253 } 254 // gcd = gcd(gcd,x) 255 if (gcd == null) { 256 gcd = numerator; 257 sGCD = numerator.signum(); 258 } else { 259 gcd = gcd.gcd(numerator); 260 } 261 } 262 //System.out.println("gcd = " + gcd + ", lcm = " + lcm); 263 } 264 if (sLCM < 0) { 265 lcm = lcm.negate(); 266 } 267 if (sGCD < 0) { 268 gcd = gcd.negate(); 269 } 270 //System.out.println("gcd** = " + gcd + ", lcm = " + lcm); 271 RingFactory<GenPolynomial<BigInteger>> cfac = fac.coFac; 272 GenPolynomialRing<BigInteger> rfac = (GenPolynomialRing<BigInteger>) cfac; 273 for (Map.Entry<ExpVector, GenPolynomial<BigRational>> y : A.getMap().entrySet()) { 274 ExpVector e = y.getKey(); 275 GenPolynomial<BigRational> a = y.getValue(); 276 // common denominator over all coefficients 277 GenPolynomial<BigInteger> p = PolyUtil.integerFromRationalCoefficients(rfac, gcd, lcm, a); 278 if (!p.isZERO()) { 279 //B = B.sum( p, e ); // inefficient 280 B.doPutToMap(e, p); 281 } 282 } 283 return B; 284 } 285 286 287 /** 288 * BigInteger from BigRational coefficients. Represent as polynomial with type 289 * GenPolynomial<BigInteger> coefficients. 290 * @param fac result polynomial factory. 291 * @param L polynomial list with GenPolynomial<BigRational> 292 * coefficients to be converted. 293 * @return polynomial list with polynomials with type GenPolynomial<BigInteger> 294 * coefficients. 295 */ 296 public static List<GenPolynomial<GenPolynomial<BigInteger>>> integerFromRationalCoefficients( 297 GenPolynomialRing<GenPolynomial<BigInteger>> fac, List<GenPolynomial<GenPolynomial<BigRational>>> L) { 298 List<GenPolynomial<GenPolynomial<BigInteger>>> K = null; 299 if (L == null) { 300 return K; 301 } 302 K = new ArrayList<GenPolynomial<GenPolynomial<BigInteger>>>(L.size()); 303 if (L.isEmpty()) { 304 return K; 305 } 306 for (GenPolynomial<GenPolynomial<BigRational>> a : L) { 307 GenPolynomial<GenPolynomial<BigInteger>> b = integerFromRationalCoefficients(fac, a); 308 K.add(b); 309 } 310 return K; 311 } 312 313 314 /** 315 * Introduce lower variable. Represent as polynomial with type 316 * GenPolynomial<C> coefficients. 317 * @param rfac result polynomial factory. 318 * @param A polynomial to be extended. 319 * @return polynomial with type GenPolynomial<C> coefficients. 320 */ 321 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> introduceLowerVariable( 322 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) { 323 if (A == null || rfac == null) { 324 return null; 325 } 326 GenPolynomial<GenPolynomial<C>> Pc = rfac.getONE().multiply(A); 327 if (Pc.isZERO()) { 328 return Pc; 329 } 330 Pc = PolyUtil.<C> switchVariables(Pc); 331 return Pc; 332 } 333 334 335 /** 336 * From AlgebraicNumber coefficients. Represent as polynomial with type 337 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 338 * @param rfac result polynomial factory. 339 * @param A polynomial with AlgebraicNumber coefficients to be converted. 340 * @param k for (y-k x) substitution. 341 * @return polynomial with type GenPolynomial<C> coefficients. 342 */ 343 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> substituteFromAlgebraicCoefficients( 344 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A, long k) { 345 if (A == null || rfac == null) { 346 return null; 347 } 348 if (A.isZERO()) { 349 return rfac.getZERO(); 350 } 351 // setup x - k alpha 352 GenPolynomialRing<AlgebraicNumber<C>> apfac = A.ring; 353 GenPolynomial<AlgebraicNumber<C>> x = apfac.univariate(0); 354 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) A.ring.coFac; 355 AlgebraicNumber<C> alpha = afac.getGenerator(); 356 AlgebraicNumber<C> ka = afac.fromInteger(k); 357 GenPolynomial<AlgebraicNumber<C>> s = x.subtract(ka.multiply(alpha)); // x - k alpha 358 if (debug) { 359 logger.info("x - k alpha: " + s); 360 } 361 // substitute, convert and switch 362 GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<AlgebraicNumber<C>> substituteMain(A, s); 363 GenPolynomial<GenPolynomial<C>> Pc = PolyUtil.<C> fromAlgebraicCoefficients(rfac, B); // Q[alpha][x] 364 Pc = PolyUtil.<C> switchVariables(Pc); // Q[x][alpha] 365 return Pc; 366 } 367 368 369 /** 370 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 371 * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 372 * @param pfac result polynomial factory. 373 * @param A polynomial with GenPolynomial<BigInteger> coefficients to 374 * be converted. 375 * @param k for (y-k x) substitution. 376 * @return polynomial with AlgebraicNumber<C> coefficients. 377 */ 378 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> substituteConvertToAlgebraicCoefficients( 379 GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A, long k) { 380 if (A == null || pfac == null) { 381 return null; 382 } 383 if (A.isZERO()) { 384 return pfac.getZERO(); 385 } 386 // convert to Q(alpha)[x] 387 GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<C> convertToAlgebraicCoefficients(pfac, A); 388 // setup x .+. k alpha for back substitution 389 GenPolynomial<AlgebraicNumber<C>> x = pfac.univariate(0); 390 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 391 AlgebraicNumber<C> alpha = afac.getGenerator(); 392 AlgebraicNumber<C> ka = afac.fromInteger(k); 393 GenPolynomial<AlgebraicNumber<C>> s = x.sum(ka.multiply(alpha)); // x + k alpha 394 // substitute 395 GenPolynomial<AlgebraicNumber<C>> N = PolyUtil.<AlgebraicNumber<C>> substituteMain(B, s); 396 return N; 397 } 398 399 400 /** 401 * Norm of a polynomial with AlgebraicNumber coefficients. 402 * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. 403 * @param k for (y - k x) substitution. 404 * @return norm(A) = res_x(A(x,y),m(x)) in GenPolynomialRing<C>. 405 */ 406 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A, long k) { 407 if (A == null) { 408 return null; 409 } 410 GenPolynomialRing<AlgebraicNumber<C>> pfac = A.ring; // Q(alpha)[x] 411 if (pfac.nvar > 1) { 412 throw new IllegalArgumentException("only for univariate polynomials"); 413 } 414 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 415 GenPolynomial<C> agen = afac.modul; 416 GenPolynomialRing<C> cfac = afac.ring; 417 if (A.isZERO()) { 418 return cfac.getZERO(); 419 } 420 AlgebraicNumber<C> ldcf = A.leadingBaseCoefficient(); 421 if (!ldcf.isONE()) { 422 A = A.monic(); 423 } 424 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pfac); 425 426 // transform minimal polynomial to bi-variate polynomial 427 GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, agen); 428 //System.out.println("Ac = " + Ac.toScript()); 429 430 // transform to bi-variate polynomial, 431 // switching varaible sequence from Q[alpha][x] to Q[X][alpha] 432 GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> substituteFromAlgebraicCoefficients(rfac, A, k); 433 Pc = PolyUtil.<C> monic(Pc); 434 //System.out.println("Pc = " + Pc.toScript()); 435 436 GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>( /*cfac.coFac*/); 437 // = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getImplementation( cfac.coFac ); 438 439 GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveUnivariateResultant(Pc, Ac); 440 //System.out.println("Rc = " + Rc.toScript()); 441 GenPolynomial<C> res = Rc.leadingBaseCoefficient(); 442 res = res.monic(); 443 return res; 444 } 445 446 447 /** 448 * Norm of a polynomial with AlgebraicNumber coefficients. 449 * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. 450 * @return norm(A) = resultant_x( A(x,y), m(x) ) in K[y]. 451 */ 452 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A) { 453 return norm(A, 0L); 454 } 455 456 457 /** 458 * Ensure that the field property is determined. Checks if modul is 459 * irreducible and modifies the algebraic number ring. 460 * @param afac algebraic number ring. 461 */ 462 public static <C extends GcdRingElem<C>> void ensureFieldProperty(AlgebraicNumberRing<C> afac) { 463 if (afac.getField() != -1) { 464 return; 465 } 466 if (!afac.ring.coFac.isField()) { 467 afac.setField(false); 468 return; 469 } 470 Factorization<C> mf = FactorFactory.<C> getImplementation(afac.ring); 471 if (mf.isIrreducible(afac.modul)) { 472 afac.setField(true); 473 } else { 474 afac.setField(false); 475 } 476 } 477 478 479 /** 480 * Construct a random irreducible univariate polynomial of degree d. 481 * @param cfac coefficient ring. 482 * @param degree of random polynomial. 483 * @return irreducible univariate polynomial. 484 */ 485 public static <C extends GcdRingElem<C>> 486 GenPolynomial<C> randomIrreduciblePolynomial(RingFactory<C> cfac, int degree) { 487 if (!cfac.isField()) { 488 throw new IllegalArgumentException("coefficient ring must be a field " + cfac); 489 } 490 GenPolynomialRing<C> ring = new GenPolynomialRing<C>(cfac, 1, TermOrderByName.INVLEX); 491 Factorization<C> eng = FactorFactory.<C> getImplementation(ring); 492 GenPolynomial<C> mod = ring.getZERO(); 493 int k = cfac.characteristic().bitLength(); // log 494 if (k < 3) { 495 k = 7; 496 } 497 int l = degree/2 + 2; 498 int d = degree + 1; 499 float q = 0.55f; 500 for (;;) { 501 mod = ring.random(k, l, d, q).monic(); 502 if (mod.degree() != degree) { 503 mod = mod.sum(ring.univariate(0, degree)); 504 } 505 if (mod.trailingBaseCoefficient().isZERO()) { 506 mod = mod.sum(ring.getONE()); 507 } 508 //System.out.println("algebriacNumberField: mod = " + mod + ", k = " + k); 509 if (eng.isIrreducible(mod)) { 510 break; 511 } 512 } 513 return mod; 514 } 515 516 517 /** 518 * Construct an algebraic number field of degree d. Uses a random 519 * irreducible polynomial of degree d as modulus of the algebraic number ring. 520 * @param cfac coefficient ring. 521 * @param degree of random polynomial. 522 * @return algebraic number field. 523 */ 524 public static <C extends GcdRingElem<C>> 525 AlgebraicNumberRing<C> algebriacNumberField(RingFactory<C> cfac, int degree) { 526 GenPolynomial<C> mod = randomIrreduciblePolynomial(cfac, degree); 527 AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(mod, true); 528 return afac; 529 } 530 531 532 /** 533 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 534 * univariate polynomial. 535 * @param A polynomial to be converted. 536 * @return a univariate polynomial. 537 */ 538 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A) { 539 if (A == null) { 540 return A; 541 } 542 long d = A.degree() + 1L; 543 return substituteKronecker(A, d); 544 } 545 546 547 /** 548 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 549 * univariate polynomial. 550 * @param A polynomial to be converted. 551 * @return a univariate polynomial. 552 */ 553 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A, long d) { 554 if (A == null) { 555 return A; 556 } 557 RingFactory<C> cfac = A.ring.coFac; 558 GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1); 559 GenPolynomial<C> B = ufac.getZERO().copy(); 560 if (A.isZERO()) { 561 return B; 562 } 563 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 564 ExpVector e = y.getKey(); 565 C a = y.getValue(); 566 long f = 0L; 567 long h = 1L; 568 for (int i = 0; i < e.length(); i++) { 569 long j = e.getVal(i) * h; 570 f += j; 571 h *= d; 572 } 573 ExpVector g = ExpVector.create(1, 0, f); 574 B.doPutToMap(g, a); 575 } 576 return B; 577 } 578 579 580 /** 581 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct 582 * univariate polynomials. 583 * @param A list of polynomials to be converted. 584 * @return a list of univariate polynomials. 585 */ 586 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> substituteKronecker( 587 List<GenPolynomial<C>> A, int d) { 588 if (A == null || A.get(0) == null) { 589 return null; 590 } 591 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new SubstKronecker<C>(d)); 592 } 593 594 595 /** 596 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a 597 * multivariate polynomial. 598 * @param A polynomial to be converted. 599 * @param fac result polynomial factory. 600 * @return a multivariate polynomial. 601 */ 602 public static <C extends GcdRingElem<C>> GenPolynomial<C> backSubstituteKronecker( 603 GenPolynomialRing<C> fac, GenPolynomial<C> A, long d) { 604 if (A == null) { 605 return A; 606 } 607 if (fac == null) { 608 throw new IllegalArgumentException("null factory not allowed "); 609 } 610 int n = fac.nvar; 611 GenPolynomial<C> B = fac.getZERO().copy(); 612 if (A.isZERO()) { 613 return B; 614 } 615 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 616 ExpVector e = y.getKey(); 617 C a = y.getValue(); 618 long f = e.getVal(0); 619 ExpVector g = ExpVector.create(n); 620 for (int i = 0; i < n; i++) { 621 long j = f % d; 622 f /= d; 623 g = g.subst(i, j); 624 } 625 B.doPutToMap(g, a); 626 } 627 return B; 628 } 629 630 631 /** 632 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct 633 * multivariate polynomials. 634 * @param A list of polynomials to be converted. 635 * @param fac result polynomial factory. 636 * @return a list of multivariate polynomials. 637 */ 638 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> backSubstituteKronecker( 639 GenPolynomialRing<C> fac, List<GenPolynomial<C>> A, long d) { 640 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new BackSubstKronecker<C>(fac, d)); 641 } 642 643} 644 645 646/** 647 * Kronecker substitutuion functor. 648 */ 649class SubstKronecker<C extends GcdRingElem<C>> implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 650 651 652 final long d; 653 654 655 public SubstKronecker(long d) { 656 this.d = d; 657 } 658 659 660 public GenPolynomial<C> eval(GenPolynomial<C> c) { 661 if (c == null) { 662 return null; 663 } 664 return PolyUfdUtil.<C> substituteKronecker(c, d); 665 } 666} 667 668 669/** 670 * Kronecker back substitutuion functor. 671 */ 672class BackSubstKronecker<C extends GcdRingElem<C>> implements 673 UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 674 675 676 final long d; 677 678 679 final GenPolynomialRing<C> fac; 680 681 682 public BackSubstKronecker(GenPolynomialRing<C> fac, long d) { 683 this.d = d; 684 this.fac = fac; 685 } 686 687 688 public GenPolynomial<C> eval(GenPolynomial<C> c) { 689 if (c == null) { 690 return null; 691 } 692 return PolyUfdUtil.<C> backSubstituteKronecker(fac, c, d); 693 } 694}