001/* 002 * $Id: PolyUfdUtil.java 5997 2020-03-17 15:34:31Z 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.LogManager; 014import org.apache.logging.log4j.Logger; 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 034 * representations 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, 206 List<GenPolynomial<GenPolynomial<BigInteger>>> L) { 207 List<GenPolynomial<GenPolynomial<C>>> K = null; 208 if (L == null) { 209 return K; 210 } 211 K = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size()); 212 if (L.size() == 0) { 213 return K; 214 } 215 for (GenPolynomial<GenPolynomial<BigInteger>> a : L) { 216 GenPolynomial<GenPolynomial<C>> b = fromIntegerCoefficients(fac, a); 217 K.add(b); 218 } 219 return K; 220 } 221 222 223 //------------------------------ 224 225 /** 226 * BigInteger from BigRational coefficients. Represent as polynomial with 227 * type GenPolynomial<BigInteger> coefficients. 228 * @param fac result polynomial factory. 229 * @param A polynomial with GenPolynomial<BigRational> coefficients to 230 * be converted. 231 * @return polynomial with type GenPolynomial<BigInteger> 232 * coefficients. 233 */ 234 public static GenPolynomial<GenPolynomial<BigInteger>> integerFromRationalCoefficients( 235 GenPolynomialRing<GenPolynomial<BigInteger>> fac, 236 GenPolynomial<GenPolynomial<BigRational>> A) { 237 GenPolynomial<GenPolynomial<BigInteger>> B = fac.getZERO().copy(); 238 if (A == null || A.isZERO()) { 239 return B; 240 } 241 java.math.BigInteger gcd = null; 242 java.math.BigInteger lcm = null; 243 int sLCM = 0; 244 int sGCD = 0; 245 // lcm of all denominators 246 for (GenPolynomial<BigRational> av : A.getMap().values()) { 247 for (BigRational y : av.getMap().values()) { 248 java.math.BigInteger numerator = y.numerator(); 249 java.math.BigInteger denominator = y.denominator(); 250 // lcm = lcm(lcm,x) 251 if (lcm == null) { 252 lcm = denominator; 253 sLCM = denominator.signum(); 254 } else { 255 java.math.BigInteger d = lcm.gcd(denominator); 256 lcm = lcm.multiply(denominator.divide(d)); 257 } 258 // gcd = gcd(gcd,x) 259 if (gcd == null) { 260 gcd = numerator; 261 sGCD = numerator.signum(); 262 } else { 263 gcd = gcd.gcd(numerator); 264 } 265 } 266 //System.out.println("gcd = " + gcd + ", lcm = " + lcm); 267 } 268 if (sLCM < 0) { 269 lcm = lcm.negate(); 270 } 271 if (sGCD < 0) { 272 gcd = gcd.negate(); 273 } 274 //System.out.println("gcd** = " + gcd + ", lcm = " + lcm); 275 RingFactory<GenPolynomial<BigInteger>> cfac = fac.coFac; 276 GenPolynomialRing<BigInteger> rfac = (GenPolynomialRing<BigInteger>) cfac; 277 for (Map.Entry<ExpVector, GenPolynomial<BigRational>> y : A.getMap().entrySet()) { 278 ExpVector e = y.getKey(); 279 GenPolynomial<BigRational> a = y.getValue(); 280 // common denominator over all coefficients 281 GenPolynomial<BigInteger> p = PolyUtil.integerFromRationalCoefficients(rfac, gcd, lcm, a); 282 if (!p.isZERO()) { 283 //B = B.sum( p, e ); // inefficient 284 B.doPutToMap(e, p); 285 } 286 } 287 return B; 288 } 289 290 291 /** 292 * BigInteger from BigRational coefficients. Represent as polynomial with 293 * type GenPolynomial<BigInteger> coefficients. 294 * @param fac result polynomial factory. 295 * @param L polynomial list with GenPolynomial<BigRational> 296 * coefficients to be converted. 297 * @return polynomial list with polynomials with type 298 * GenPolynomial<BigInteger> coefficients. 299 */ 300 public static List<GenPolynomial<GenPolynomial<BigInteger>>> integerFromRationalCoefficients( 301 GenPolynomialRing<GenPolynomial<BigInteger>> fac, 302 List<GenPolynomial<GenPolynomial<BigRational>>> L) { 303 List<GenPolynomial<GenPolynomial<BigInteger>>> K = null; 304 if (L == null) { 305 return K; 306 } 307 K = new ArrayList<GenPolynomial<GenPolynomial<BigInteger>>>(L.size()); 308 if (L.isEmpty()) { 309 return K; 310 } 311 for (GenPolynomial<GenPolynomial<BigRational>> a : L) { 312 GenPolynomial<GenPolynomial<BigInteger>> b = integerFromRationalCoefficients(fac, a); 313 K.add(b); 314 } 315 return K; 316 } 317 318 319 /** 320 * Introduce lower variable. Represent as polynomial with type 321 * GenPolynomial<C> coefficients. 322 * @param rfac result polynomial factory. 323 * @param A polynomial to be extended. 324 * @return polynomial with type GenPolynomial<C> coefficients. 325 */ 326 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> introduceLowerVariable( 327 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) { 328 if (A == null || rfac == null) { 329 return null; 330 } 331 GenPolynomial<GenPolynomial<C>> Pc = rfac.getONE().multiply(A); 332 if (Pc.isZERO()) { 333 return Pc; 334 } 335 Pc = PolyUtil.<C> switchVariables(Pc); 336 return Pc; 337 } 338 339 340 /** 341 * From AlgebraicNumber coefficients. Represent as polynomial with type 342 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 343 * @param rfac result polynomial factory. 344 * @param A polynomial with AlgebraicNumber coefficients to be converted. 345 * @param k for (y-k x) substitution. 346 * @return polynomial with type GenPolynomial<C> coefficients. 347 */ 348 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> substituteFromAlgebraicCoefficients( 349 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A, long k) { 350 if (A == null || rfac == null) { 351 return null; 352 } 353 if (A.isZERO()) { 354 return rfac.getZERO(); 355 } 356 // setup x - k alpha 357 GenPolynomialRing<AlgebraicNumber<C>> apfac = A.ring; 358 GenPolynomial<AlgebraicNumber<C>> x = apfac.univariate(0); 359 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) A.ring.coFac; 360 AlgebraicNumber<C> alpha = afac.getGenerator(); 361 AlgebraicNumber<C> ka = afac.fromInteger(k); 362 GenPolynomial<AlgebraicNumber<C>> s = x.subtract(ka.multiply(alpha)); // x - k alpha 363 //System.out.println("x - k alpha = " + s); 364 //System.out.println("s.ring = " + s.ring.toScript()); 365 if (debug) { 366 logger.info("x - k alpha: " + s); 367 } 368 // substitute, convert and switch 369 //System.out.println("Asubs = " + A); 370 GenPolynomial<AlgebraicNumber<C>> B; 371 if (s.ring.nvar <= 1) { 372 B = PolyUtil.<AlgebraicNumber<C>> substituteMain(A, s); 373 } else { 374 B = PolyUtil.<AlgebraicNumber<C>> substituteUnivariateMult(A, s); 375 } 376 //System.out.println("Bsubs = " + B); 377 GenPolynomial<GenPolynomial<C>> Pc = PolyUtil.<C> fromAlgebraicCoefficients(rfac, B); // Q[alpha][x] 378 //System.out.println("Pc[a,x] = " + Pc); 379 Pc = PolyUtil.<C> switchVariables(Pc); // Q[x][alpha] 380 //System.out.println("Pc[x,a] = " + Pc); 381 return Pc; 382 } 383 384 385 /** 386 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 387 * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 388 * @param pfac result polynomial factory. 389 * @param A polynomial with GenPolynomial<BigInteger> coefficients to 390 * be converted. 391 * @param k for (y-k x) substitution. 392 * @return polynomial with AlgebraicNumber<C> coefficients. 393 */ 394 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> substituteConvertToAlgebraicCoefficients( 395 GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A, long k) { 396 if (A == null || pfac == null) { 397 return null; 398 } 399 if (A.isZERO()) { 400 return pfac.getZERO(); 401 } 402 // convert to Q(alpha)[x] 403 GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<C> convertToAlgebraicCoefficients(pfac, A); 404 // setup x .+. k alpha for back substitution 405 GenPolynomial<AlgebraicNumber<C>> x = pfac.univariate(0); 406 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 407 AlgebraicNumber<C> alpha = afac.getGenerator(); 408 AlgebraicNumber<C> ka = afac.fromInteger(k); 409 GenPolynomial<AlgebraicNumber<C>> s = x.sum(ka.multiply(alpha)); // x + k alpha 410 // substitute 411 //System.out.println("s.ring = " + s.ring.toScript()); 412 GenPolynomial<AlgebraicNumber<C>> N; 413 if (s.ring.nvar <= 1) { 414 N = PolyUtil.<AlgebraicNumber<C>> substituteMain(B, s); 415 } else { 416 N = PolyUtil.<AlgebraicNumber<C>> substituteUnivariateMult(B, s); 417 } 418 return N; 419 } 420 421 422 /** 423 * Norm of a polynomial with AlgebraicNumber coefficients. 424 * @param A uni or multivariate polynomial from 425 * GenPolynomial<AlgebraicNumber<C>>. 426 * @param k for (y - k x) substitution. 427 * @return norm(A) = res_x(A(x,y),m(x)) in GenPolynomialRing<C>. 428 */ 429 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A, 430 long k) { 431 if (A == null) { 432 return null; 433 } 434 GenPolynomialRing<AlgebraicNumber<C>> pfac = A.ring; // Q(alpha)[x] 435 //if (pfac.nvar > 1) { 436 // throw new IllegalArgumentException("only for univariate polynomials"); 437 //} 438 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 439 GenPolynomial<C> agen = afac.modul; 440 GenPolynomialRing<C> cfac = afac.ring; 441 if (A.isZERO()) { 442 return cfac.getZERO(); 443 } 444 AlgebraicNumber<C> ldcf = A.leadingBaseCoefficient(); 445 if (!ldcf.isONE()) { 446 A = A.monic(); 447 } 448 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pfac); 449 //System.out.println("rfac = " + rfac.toScript()); 450 451 // transform minimal polynomial to bi-variate polynomial 452 GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, agen); 453 454 // transform to bi-variate polynomial, 455 // switching varaible sequence from Q[alpha][x] to Q[X][alpha] 456 GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> substituteFromAlgebraicCoefficients(rfac, A, k); 457 Pc = PolyUtil.<C> monic(Pc); 458 //System.out.println("Pc = " + Pc.toScript() + " :: " + Pc.ring.toScript()); 459 460 GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>( /*cfac.coFac*/); 461 // = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getImplementation( cfac.coFac ); 462 463 GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveUnivariateResultant(Pc, Ac); 464 //System.out.println("Rc = " + Rc.toScript()); 465 GenPolynomial<C> res = Rc.leadingBaseCoefficient(); 466 res = res.monic(); 467 return res; 468 } 469 470 471 /** 472 * Norm of a polynomial with AlgebraicNumber coefficients. 473 * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. 474 * @return norm(A) = resultant_x( A(x,y), m(x) ) in K[y]. 475 */ 476 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A) { 477 return norm(A, 0L); 478 } 479 480 481 /** 482 * Ensure that the field property is determined. Checks if modul is 483 * irreducible and modifies the algebraic number ring. 484 * @param afac algebraic number ring. 485 */ 486 public static <C extends GcdRingElem<C>> void ensureFieldProperty(AlgebraicNumberRing<C> afac) { 487 if (afac.getField() != -1) { 488 return; 489 } 490 if (!afac.ring.coFac.isField()) { 491 afac.setField(false); 492 return; 493 } 494 Factorization<C> mf = FactorFactory.<C> getImplementation(afac.ring); 495 if (mf.isIrreducible(afac.modul)) { 496 afac.setField(true); 497 } else { 498 afac.setField(false); 499 } 500 } 501 502 503 /** 504 * Construct a random irreducible univariate polynomial of degree d. 505 * @param cfac coefficient ring. 506 * @param degree of random polynomial. 507 * @return irreducible univariate polynomial. 508 */ 509 public static <C extends GcdRingElem<C>> GenPolynomial<C> randomIrreduciblePolynomial(RingFactory<C> cfac, 510 int degree) { 511 if (!cfac.isField()) { 512 throw new IllegalArgumentException("coefficient ring must be a field " + cfac); 513 } 514 GenPolynomialRing<C> ring = new GenPolynomialRing<C>(cfac, 1, TermOrderByName.INVLEX); 515 Factorization<C> eng = FactorFactory.<C> getImplementation(ring); 516 GenPolynomial<C> mod = ring.getZERO(); 517 int k = cfac.characteristic().bitLength(); // log 518 if (k < 3) { 519 k = 7; 520 } 521 int l = degree / 2 + 2; 522 int d = degree + 1; 523 float q = 0.55f; 524 for (;;) { 525 mod = ring.random(k, l, d, q).monic(); 526 if (mod.degree() != degree) { 527 mod = mod.sum(ring.univariate(0, degree)); 528 } 529 if (mod.trailingBaseCoefficient().isZERO()) { 530 mod = mod.sum(ring.getONE()); 531 } 532 //System.out.println("algebriacNumberField: mod = " + mod + ", k = " + k); 533 if (eng.isIrreducible(mod)) { 534 break; 535 } 536 } 537 return mod; 538 } 539 540 541 /** 542 * Construct an algebraic number field of degree d. Uses a random 543 * irreducible polynomial of degree d as modulus of the algebraic number 544 * ring. 545 * @param cfac coefficient ring. 546 * @param degree of random polynomial. 547 * @return algebraic number field. 548 */ 549 public static <C extends GcdRingElem<C>> AlgebraicNumberRing<C> algebraicNumberField(RingFactory<C> cfac, 550 int degree) { 551 GenPolynomial<C> mod = randomIrreduciblePolynomial(cfac, degree); 552 AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(mod, true); 553 return afac; 554 } 555 556 557 /** 558 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 559 * univariate polynomial. 560 * @param A polynomial to be converted. 561 * @return a univariate polynomial. 562 */ 563 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A) { 564 if (A == null) { 565 return A; 566 } 567 long d = A.degree() + 1L; 568 return substituteKronecker(A, d); 569 } 570 571 572 /** 573 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 574 * univariate polynomial. 575 * @param A polynomial to be converted. 576 * @return a univariate polynomial. 577 */ 578 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A, 579 long d) { 580 if (A == null) { 581 return A; 582 } 583 RingFactory<C> cfac = A.ring.coFac; 584 GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1); 585 GenPolynomial<C> B = ufac.getZERO().copy(); 586 if (A.isZERO()) { 587 return B; 588 } 589 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 590 ExpVector e = y.getKey(); 591 C a = y.getValue(); 592 long f = 0L; 593 long h = 1L; 594 for (int i = 0; i < e.length(); i++) { 595 long j = e.getVal(i) * h; 596 f += j; 597 h *= d; 598 } 599 ExpVector g = ExpVector.create(1, 0, f); 600 B.doPutToMap(g, a); 601 } 602 return B; 603 } 604 605 606 /** 607 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct 608 * univariate polynomials. 609 * @param A list of polynomials to be converted. 610 * @return a list of univariate polynomials. 611 */ 612 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> substituteKronecker( 613 List<GenPolynomial<C>> A, int d) { 614 if (A == null || A.get(0) == null) { 615 return null; 616 } 617 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new SubstKronecker<C>(d)); 618 } 619 620 621 /** 622 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a 623 * multivariate polynomial. 624 * @param A polynomial to be converted. 625 * @param fac result polynomial factory. 626 * @return a multivariate polynomial. 627 */ 628 public static <C extends GcdRingElem<C>> GenPolynomial<C> backSubstituteKronecker( 629 GenPolynomialRing<C> fac, GenPolynomial<C> A, long d) { 630 if (A == null) { 631 return A; 632 } 633 if (fac == null) { 634 throw new IllegalArgumentException("null factory not allowed "); 635 } 636 int n = fac.nvar; 637 GenPolynomial<C> B = fac.getZERO().copy(); 638 if (A.isZERO()) { 639 return B; 640 } 641 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 642 ExpVector e = y.getKey(); 643 C a = y.getValue(); 644 long f = e.getVal(0); 645 ExpVector g = ExpVector.create(n); 646 for (int i = 0; i < n; i++) { 647 long j = f % d; 648 f /= d; 649 g = g.subst(i, j); 650 } 651 B.doPutToMap(g, a); 652 } 653 return B; 654 } 655 656 657 /** 658 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct 659 * multivariate polynomials. 660 * @param A list of polynomials to be converted. 661 * @param fac result polynomial factory. 662 * @return a list of multivariate polynomials. 663 */ 664 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> backSubstituteKronecker( 665 GenPolynomialRing<C> fac, List<GenPolynomial<C>> A, long d) { 666 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new BackSubstKronecker<C>(fac, d)); 667 } 668 669} 670 671 672/** 673 * Kronecker substitutuion functor. 674 */ 675class SubstKronecker<C extends GcdRingElem<C>> implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 676 677 678 final long d; 679 680 681 public SubstKronecker(long d) { 682 this.d = d; 683 } 684 685 686 public GenPolynomial<C> eval(GenPolynomial<C> c) { 687 if (c == null) { 688 return null; 689 } 690 return PolyUfdUtil.<C> substituteKronecker(c, d); 691 } 692} 693 694 695/** 696 * Kronecker back substitutuion functor. 697 */ 698class BackSubstKronecker<C extends GcdRingElem<C>> 699 implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 700 701 702 final long d; 703 704 705 final GenPolynomialRing<C> fac; 706 707 708 public BackSubstKronecker(GenPolynomialRing<C> fac, long d) { 709 this.d = d; 710 this.fac = fac; 711 } 712 713 714 public GenPolynomial<C> eval(GenPolynomial<C> c) { 715 if (c == null) { 716 return null; 717 } 718 return PolyUfdUtil.<C> backSubstituteKronecker(fac, c, d); 719 } 720}