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