001/* 002 * $Id$ 003 */ 004 005package edu.jas.poly; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011import java.util.SortedMap; 012import java.util.TreeMap; 013 014import org.apache.logging.log4j.LogManager; 015import org.apache.logging.log4j.Logger; 016 017import edu.jas.arith.BigComplex; 018import edu.jas.arith.BigDecimal; 019import edu.jas.arith.BigDecimalComplex; 020import edu.jas.arith.BigInteger; 021import edu.jas.arith.BigRational; 022import edu.jas.arith.ModInteger; 023import edu.jas.arith.ModIntegerRing; 024import edu.jas.arith.Modular; 025import edu.jas.arith.ModularRingFactory; 026import edu.jas.arith.Product; 027import edu.jas.arith.ProductRing; 028import edu.jas.arith.Rational; 029import edu.jas.arith.Roots; 030import edu.jas.structure.Element; 031import edu.jas.structure.GcdRingElem; 032import edu.jas.structure.RingElem; 033import edu.jas.structure.RingFactory; 034import edu.jas.structure.StarRingElem; 035import edu.jas.structure.UnaryFunctor; 036import edu.jas.util.ListUtil; 037 038 039/** 040 * Polynomial utilities, for example conversion between different 041 * representations, evaluation and interpolation. 042 * @author Heinz Kredel 043 */ 044 045public class PolyUtil { 046 047 048 private static final Logger logger = LogManager.getLogger(PolyUtil.class); 049 050 051 private static final boolean debug = logger.isDebugEnabled(); 052 053 054 /** 055 * Recursive representation. Represent as polynomial in i variables with 056 * coefficients in n-i variables. Works for arbitrary term orders. 057 * @param <C> coefficient type. 058 * @param rfac recursive polynomial ring factory. 059 * @param A polynomial to be converted. 060 * @return Recursive representations of this in the ring rfac. 061 */ 062 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursive( 063 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) { 064 065 GenPolynomial<GenPolynomial<C>> B = rfac.getZERO().copy(); 066 if (A.isZERO()) { 067 return B; 068 } 069 int i = rfac.nvar; 070 GenPolynomial<C> zero = rfac.getZEROCoefficient(); 071 Map<ExpVector, GenPolynomial<C>> Bv = B.val; //getMap(); 072 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 073 ExpVector e = y.getKey(); 074 C a = y.getValue(); 075 ExpVector f = e.contract(0, i); 076 ExpVector g = e.contract(i, e.length() - i); 077 GenPolynomial<C> p = Bv.get(f); 078 if (p == null) { 079 p = zero; 080 } 081 p = p.sum(a, g); 082 Bv.put(f, p); 083 } 084 return B; 085 } 086 087 088 /** 089 * Distribute a recursive polynomial to a generic polynomial. Works for 090 * arbitrary term orders. 091 * @param <C> coefficient type. 092 * @param dfac combined polynomial ring factory of coefficients and this. 093 * @param B polynomial to be converted. 094 * @return distributed polynomial. 095 */ 096 public static <C extends RingElem<C>> GenPolynomial<C> distribute(GenPolynomialRing<C> dfac, 097 GenPolynomial<GenPolynomial<C>> B) { 098 GenPolynomial<C> C = dfac.getZERO().copy(); 099 if (B.isZERO()) { 100 return C; 101 } 102 Map<ExpVector, C> Cm = C.val; //getMap(); 103 for (Map.Entry<ExpVector, GenPolynomial<C>> y : B.getMap().entrySet()) { 104 ExpVector e = y.getKey(); 105 GenPolynomial<C> A = y.getValue(); 106 for (Map.Entry<ExpVector, C> x : A.val.entrySet()) { 107 ExpVector f = x.getKey(); 108 C b = x.getValue(); 109 ExpVector g = e.combine(f); 110 assert (Cm.get(g) == null); 111 Cm.put(g, b); 112 } 113 } 114 return C; 115 } 116 117 118 /** 119 * Recursive representation. Represent as polynomials in i variables with 120 * coefficients in n-i variables. Works for arbitrary term orders. 121 * @param <C> coefficient type. 122 * @param rfac recursive polynomial ring factory. 123 * @param L list of polynomials to be converted. 124 * @return Recursive representations of the list in the ring rfac. 125 */ 126 public static <C extends RingElem<C>> List<GenPolynomial<GenPolynomial<C>>> recursive( 127 GenPolynomialRing<GenPolynomial<C>> rfac, List<GenPolynomial<C>> L) { 128 return ListUtil.<GenPolynomial<C>, GenPolynomial<GenPolynomial<C>>> map(L, new DistToRec<C>(rfac)); 129 } 130 131 132 /** 133 * Distribute a recursive polynomial list to a generic polynomial list. 134 * Works for arbitrary term orders. 135 * @param <C> coefficient type. 136 * @param dfac combined polynomial ring factory of coefficients and this. 137 * @param L list of polynomials to be converted. 138 * @return distributed polynomial list. 139 */ 140 public static <C extends RingElem<C>> List<GenPolynomial<C>> distribute(GenPolynomialRing<C> dfac, 141 List<GenPolynomial<GenPolynomial<C>>> L) { 142 return ListUtil.<GenPolynomial<GenPolynomial<C>>, GenPolynomial<C>> map(L, new RecToDist<C>(dfac)); 143 } 144 145 146 /** 147 * BigInteger from ModInteger coefficients, symmetric. Represent as 148 * polynomial with BigInteger coefficients by removing the modules and 149 * making coefficients symmetric to 0. 150 * @param fac result polynomial factory. 151 * @param A polynomial with ModInteger coefficients to be converted. 152 * @return polynomial with BigInteger coefficients. 153 */ 154 public static <C extends RingElem<C> & Modular> GenPolynomial<BigInteger> integerFromModularCoefficients( 155 GenPolynomialRing<BigInteger> fac, GenPolynomial<C> A) { 156 return PolyUtil.<C, BigInteger> map(fac, A, new ModSymToInt<C>()); 157 } 158 159 160 /** 161 * BigInteger from ModInteger coefficients, symmetric. Represent as 162 * polynomial with BigInteger coefficients by removing the modules and 163 * making coefficients symmetric to 0. 164 * @param fac result polynomial factory. 165 * @param L list of polynomials with ModInteger coefficients to be 166 * converted. 167 * @return list of polynomials with BigInteger coefficients. 168 */ 169 public static <C extends RingElem<C> & Modular> List<GenPolynomial<BigInteger>> integerFromModularCoefficients( 170 final GenPolynomialRing<BigInteger> fac, List<GenPolynomial<C>> L) { 171 return ListUtil.<GenPolynomial<C>, GenPolynomial<BigInteger>> map(L, 172 new UnaryFunctor<GenPolynomial<C>, GenPolynomial<BigInteger>>() { 173 174 175 public GenPolynomial<BigInteger> eval(GenPolynomial<C> c) { 176 return PolyUtil.<C> integerFromModularCoefficients(fac, c); 177 } 178 }); 179 } 180 181 182 /** 183 * BigInteger from ModInteger coefficients, positive. Represent as 184 * polynomial with BigInteger coefficients by removing the modules. 185 * @param fac result polynomial factory. 186 * @param A polynomial with ModInteger coefficients to be converted. 187 * @return polynomial with BigInteger coefficients. 188 */ 189 public static <C extends RingElem<C> & Modular> GenPolynomial<BigInteger> integerFromModularCoefficientsPositive( 190 GenPolynomialRing<BigInteger> fac, GenPolynomial<C> A) { 191 return PolyUtil.<C, BigInteger> map(fac, A, new ModToInt<C>()); 192 } 193 194 195 /** 196 * BigInteger from BigRational coefficients. Represent as polynomial with 197 * BigInteger coefficients by multiplication with the lcm of the numerators 198 * of the BigRational coefficients. 199 * @param fac result polynomial factory. 200 * @param A polynomial with BigRational coefficients to be converted. 201 * @return polynomial with BigInteger coefficients. 202 */ 203 public static GenPolynomial<BigInteger> integerFromRationalCoefficients(GenPolynomialRing<BigInteger> fac, 204 GenPolynomial<BigRational> A) { 205 if (A == null || A.isZERO()) { 206 return fac.getZERO(); 207 } 208 java.math.BigInteger c = null; 209 int s = 0; 210 // lcm of denominators 211 for (BigRational y : A.val.values()) { 212 java.math.BigInteger x = y.denominator(); 213 // c = lcm(c,x) 214 if (c == null) { 215 c = x; 216 s = x.signum(); 217 } else { 218 java.math.BigInteger d = c.gcd(x); 219 c = c.multiply(x.divide(d)); 220 } 221 } 222 if (s < 0) { 223 c = c.negate(); 224 } 225 return PolyUtil.<BigRational, BigInteger> map(fac, A, new RatToInt(c)); 226 } 227 228 229 /** 230 * BigInteger from BigRational coefficients. Represent as polynomial with 231 * BigInteger coefficients by multiplication with the gcd of the numerators 232 * and the lcm of the denominators of the BigRational coefficients. <br /> 233 * <b>Author:</b> Axel Kramer 234 * @param fac result polynomial factory. 235 * @param A polynomial with BigRational coefficients to be converted. 236 * @return Object[] with 3 entries: [0]=gcd [1]=lcm and [2]=polynomial with 237 * BigInteger coefficients. 238 */ 239 public static Object[] integerFromRationalCoefficientsFactor(GenPolynomialRing<BigInteger> fac, 240 GenPolynomial<BigRational> A) { 241 Object[] result = new Object[3]; 242 if (A == null || A.isZERO()) { 243 result[0] = java.math.BigInteger.ONE; 244 result[1] = java.math.BigInteger.ZERO; 245 result[2] = fac.getZERO(); 246 return result; 247 } 248 java.math.BigInteger gcd = null; 249 java.math.BigInteger lcm = null; 250 int sLCM = 0; 251 int sGCD = 0; 252 // lcm of denominators 253 for (BigRational y : A.val.values()) { 254 java.math.BigInteger numerator = y.numerator(); 255 java.math.BigInteger denominator = y.denominator(); 256 // lcm = lcm(lcm,x) 257 if (lcm == null) { 258 lcm = denominator; 259 sLCM = denominator.signum(); 260 } else { 261 java.math.BigInteger d = lcm.gcd(denominator); 262 lcm = lcm.multiply(denominator.divide(d)); 263 } 264 // gcd = gcd(gcd,x) 265 if (gcd == null) { 266 gcd = numerator; 267 sGCD = numerator.signum(); 268 } else { 269 gcd = gcd.gcd(numerator); 270 } 271 } 272 if (sLCM < 0) { 273 lcm = lcm.negate(); 274 } 275 if (sGCD < 0) { 276 gcd = gcd.negate(); 277 } 278 //System.out.println("gcd* = " + gcd + ", lcm = " + lcm); 279 result[0] = gcd; 280 result[1] = lcm; 281 result[2] = PolyUtil.<BigRational, BigInteger> map(fac, A, new RatToIntFactor(gcd, lcm)); 282 return result; 283 } 284 285 286 /** 287 * BigInteger from BigRational coefficients. Represent as polynomial with 288 * BigInteger coefficients by multiplication with the gcd of the numerators 289 * and the lcm of the denominators of the BigRational coefficients. <br /> 290 * @param fac result polynomial factory. 291 * @param gcd of rational coefficient numerators. 292 * @param lcm of rational coefficient denominators. 293 * @param A polynomial with BigRational coefficients to be converted. 294 * @return polynomial with BigInteger coefficients. 295 */ 296 public static GenPolynomial<BigInteger> integerFromRationalCoefficients(GenPolynomialRing<BigInteger> fac, 297 java.math.BigInteger gcd, java.math.BigInteger lcm, GenPolynomial<BigRational> A) { 298 //System.out.println("gcd = " + gcd + ", lcm = " + lcm); 299 GenPolynomial<BigInteger> Ai = PolyUtil.<BigRational, BigInteger> map(fac, A, 300 new RatToIntFactor(gcd, lcm)); 301 return Ai; 302 } 303 304 305 /** 306 * BigInteger from BigRational coefficients. Represent as list of 307 * polynomials with BigInteger coefficients by multiplication with the lcm 308 * of the numerators of the BigRational coefficients of each polynomial. 309 * @param fac result polynomial factory. 310 * @param L list of polynomials with BigRational coefficients to be 311 * converted. 312 * @return polynomial list with BigInteger coefficients. 313 */ 314 public static List<GenPolynomial<BigInteger>> integerFromRationalCoefficients( 315 GenPolynomialRing<BigInteger> fac, List<GenPolynomial<BigRational>> L) { 316 return ListUtil.<GenPolynomial<BigRational>, GenPolynomial<BigInteger>> map(L, new RatToIntPoly(fac)); 317 } 318 319 320 /** 321 * From BigInteger coefficients. Represent as polynomial with type C 322 * coefficients, e.g. ModInteger or BigRational. 323 * @param <C> coefficient type. 324 * @param fac result polynomial factory. 325 * @param A polynomial with BigInteger coefficients to be converted. 326 * @return polynomial with type C coefficients. 327 */ 328 public static <C extends RingElem<C>> GenPolynomial<C> fromIntegerCoefficients(GenPolynomialRing<C> fac, 329 GenPolynomial<BigInteger> A) { 330 return PolyUtil.<BigInteger, C> map(fac, A, new FromInteger<C>(fac.coFac)); 331 } 332 333 334 /** 335 * From BigInteger coefficients. Represent as list of polynomials with type 336 * C coefficients, e.g. ModInteger or BigRational. 337 * @param <C> coefficient type. 338 * @param fac result polynomial factory. 339 * @param L list of polynomials with BigInteger coefficients to be 340 * converted. 341 * @return list of polynomials with type C coefficients. 342 */ 343 public static <C extends RingElem<C>> List<GenPolynomial<C>> fromIntegerCoefficients( 344 GenPolynomialRing<C> fac, List<GenPolynomial<BigInteger>> L) { 345 return ListUtil.<GenPolynomial<BigInteger>, GenPolynomial<C>> map(L, new FromIntegerPoly<C>(fac)); 346 } 347 348 349 /** 350 * Convert to decimal coefficients. 351 * @param fac result polynomial factory. 352 * @param A polynomial with Rational coefficients to be converted. 353 * @return polynomial with BigDecimal coefficients. 354 */ 355 public static <C extends RingElem<C> & Rational> GenPolynomial<BigDecimal> decimalFromRational( 356 GenPolynomialRing<BigDecimal> fac, GenPolynomial<C> A) { 357 return PolyUtil.<C, BigDecimal> map(fac, A, new RatToDec<C>()); 358 } 359 360 361 /** 362 * Convert to complex decimal coefficients. 363 * @param fac result polynomial factory. 364 * @param A polynomial with complex Rational coefficients to be converted. 365 * @return polynomial with Complex BigDecimal coefficients. 366 */ 367 public static <C extends RingElem<C> & Rational> GenPolynomial<Complex<BigDecimal>> complexDecimalFromRational( 368 GenPolynomialRing<Complex<BigDecimal>> fac, GenPolynomial<Complex<C>> A) { 369 return PolyUtil.<Complex<C>, Complex<BigDecimal>> map(fac, A, new CompRatToDec<C>(fac.coFac)); 370 } 371 372 373 /** 374 * Real part. 375 * @param fac result polynomial factory. 376 * @param A polynomial with BigComplex coefficients to be converted. 377 * @return polynomial with real part of the coefficients. 378 */ 379 public static GenPolynomial<BigRational> realPart(GenPolynomialRing<BigRational> fac, 380 GenPolynomial<BigComplex> A) { 381 return PolyUtil.<BigComplex, BigRational> map(fac, A, new RealPart()); 382 } 383 384 385 /** 386 * Imaginary part. 387 * @param fac result polynomial factory. 388 * @param A polynomial with BigComplex coefficients to be converted. 389 * @return polynomial with imaginary part of coefficients. 390 */ 391 public static GenPolynomial<BigRational> imaginaryPart(GenPolynomialRing<BigRational> fac, 392 GenPolynomial<BigComplex> A) { 393 return PolyUtil.<BigComplex, BigRational> map(fac, A, new ImagPart()); 394 } 395 396 397 /** 398 * Real part. 399 * @param fac result polynomial factory. 400 * @param A polynomial with BigComplex coefficients to be converted. 401 * @return polynomial with real part of the coefficients. 402 */ 403 public static <C extends RingElem<C>> GenPolynomial<C> realPartFromComplex(GenPolynomialRing<C> fac, 404 GenPolynomial<Complex<C>> A) { 405 return PolyUtil.<Complex<C>, C> map(fac, A, new RealPartComplex<C>()); 406 } 407 408 409 /** 410 * Imaginary part. 411 * @param fac result polynomial factory. 412 * @param A polynomial with BigComplex coefficients to be converted. 413 * @return polynomial with imaginary part of coefficients. 414 */ 415 public static <C extends RingElem<C>> GenPolynomial<C> imaginaryPartFromComplex(GenPolynomialRing<C> fac, 416 GenPolynomial<Complex<C>> A) { 417 return PolyUtil.<Complex<C>, C> map(fac, A, new ImagPartComplex<C>()); 418 } 419 420 421 /** 422 * Complex from real polynomial. 423 * @param fac result polynomial factory. 424 * @param A polynomial with C coefficients to be converted. 425 * @return polynomial with Complex<C> coefficients. 426 */ 427 public static <C extends RingElem<C>> GenPolynomial<Complex<C>> toComplex( 428 GenPolynomialRing<Complex<C>> fac, GenPolynomial<C> A) { 429 return PolyUtil.<C, Complex<C>> map(fac, A, new ToComplex<C>(fac.coFac)); 430 } 431 432 433 /** 434 * Complex from rational coefficients. 435 * @param fac result polynomial factory. 436 * @param A polynomial with BigRational coefficients to be converted. 437 * @return polynomial with BigComplex coefficients. 438 */ 439 public static GenPolynomial<BigComplex> complexFromRational(GenPolynomialRing<BigComplex> fac, 440 GenPolynomial<BigRational> A) { 441 return PolyUtil.<BigRational, BigComplex> map(fac, A, new RatToCompl()); 442 } 443 444 445 /** 446 * Complex from ring element coefficients. 447 * @param fac result polynomial factory. 448 * @param A polynomial with RingElem coefficients to be converted. 449 * @return polynomial with Complex coefficients. 450 */ 451 public static <C extends GcdRingElem<C>> GenPolynomial<Complex<C>> complexFromAny( 452 GenPolynomialRing<Complex<C>> fac, GenPolynomial<C> A) { 453 ComplexRing<C> cr = (ComplexRing<C>) fac.coFac; 454 return PolyUtil.<C, Complex<C>> map(fac, A, new AnyToComplex<C>(cr)); 455 } 456 457 458 /** 459 * From AlgebraicNumber coefficients. Represent as polynomial with type 460 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 461 * @param rfac result polynomial factory. 462 * @param A polynomial with AlgebraicNumber coefficients to be converted. 463 * @return polynomial with type GenPolynomial<C> coefficients. 464 */ 465 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> fromAlgebraicCoefficients( 466 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A) { 467 return PolyUtil.<AlgebraicNumber<C>, GenPolynomial<C>> map(rfac, A, new AlgToPoly<C>()); 468 } 469 470 471 /** 472 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 473 * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 474 * @param pfac result polynomial factory. 475 * @param A polynomial with C coefficients to be converted. 476 * @return polynomial with AlgebraicNumber<C> coefficients. 477 */ 478 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> convertToAlgebraicCoefficients( 479 GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 480 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 481 return PolyUtil.<C, AlgebraicNumber<C>> map(pfac, A, new CoeffToAlg<C>(afac)); 482 } 483 484 485 /** 486 * Convert to recursive AlgebraicNumber coefficients. Represent as 487 * polynomial with recursive AlgebraicNumber<C> coefficients, C is e.g. 488 * ModInteger or BigRational. 489 * @param depth recursion depth of AlgebraicNumber coefficients. 490 * @param pfac result polynomial factory. 491 * @param A polynomial with C coefficients to be converted. 492 * @return polynomial with AlgebraicNumber<C> coefficients. 493 */ 494 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> convertToRecAlgebraicCoefficients( 495 int depth, GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A) { 496 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 497 return PolyUtil.<C, AlgebraicNumber<C>> map(pfac, A, new CoeffToRecAlg<C>(depth, afac)); 498 } 499 500 501 /** 502 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 503 * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 504 * @param pfac result polynomial factory. 505 * @param A recursive polynomial with GenPolynomial<BigInteger> 506 * coefficients to be converted. 507 * @return polynomial with AlgebraicNumber<C> coefficients. 508 */ 509 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> convertRecursiveToAlgebraicCoefficients( 510 GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<GenPolynomial<C>> A) { 511 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 512 return PolyUtil.<GenPolynomial<C>, AlgebraicNumber<C>> map(pfac, A, new PolyToAlg<C>(afac)); 513 } 514 515 516 /** 517 * Complex from algebraic coefficients. 518 * @param fac result polynomial factory. 519 * @param A polynomial with AlgebraicNumber coefficients Q(i) to be 520 * converted. 521 * @return polynomial with Complex coefficients. 522 */ 523 public static <C extends GcdRingElem<C>> GenPolynomial<Complex<C>> complexFromAlgebraic( 524 GenPolynomialRing<Complex<C>> fac, GenPolynomial<AlgebraicNumber<C>> A) { 525 ComplexRing<C> cfac = (ComplexRing<C>) fac.coFac; 526 return PolyUtil.<AlgebraicNumber<C>, Complex<C>> map(fac, A, new AlgebToCompl<C>(cfac)); 527 } 528 529 530 /** 531 * AlgebraicNumber from complex coefficients. 532 * @param fac result polynomial factory over Q(i). 533 * @param A polynomial with Complex coefficients to be converted. 534 * @return polynomial with AlgebraicNumber coefficients. 535 */ 536 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> algebraicFromComplex( 537 GenPolynomialRing<AlgebraicNumber<C>> fac, GenPolynomial<Complex<C>> A) { 538 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) fac.coFac; 539 return PolyUtil.<Complex<C>, AlgebraicNumber<C>> map(fac, A, new ComplToAlgeb<C>(afac)); 540 } 541 542 543 /** 544 * ModInteger chinese remainder algorithm on coefficients. 545 * @param fac GenPolynomial<ModInteger> result factory with 546 * A.coFac.modul*B.coFac.modul = C.coFac.modul. 547 * @param A GenPolynomial<ModInteger>. 548 * @param B other GenPolynomial<ModInteger>. 549 * @param mi inverse of A.coFac.modul in ring B.coFac. 550 * @return S = cra(A,B), with S mod A.coFac.modul == A and S mod 551 * B.coFac.modul == B. 552 */ 553 public static <C extends RingElem<C> & Modular> GenPolynomial<C> chineseRemainder( 554 GenPolynomialRing<C> fac, GenPolynomial<C> A, C mi, GenPolynomial<C> B) { 555 ModularRingFactory<C> cfac = (ModularRingFactory<C>) fac.coFac; // get RingFactory 556 GenPolynomial<C> S = fac.getZERO().copy(); 557 GenPolynomial<C> Ap = A.copy(); 558 SortedMap<ExpVector, C> av = Ap.val; //getMap(); 559 SortedMap<ExpVector, C> bv = B.getMap(); 560 SortedMap<ExpVector, C> sv = S.val; //getMap(); 561 C c = null; 562 for (Map.Entry<ExpVector, C> me : bv.entrySet()) { 563 ExpVector e = me.getKey(); 564 C y = me.getValue(); //bv.get(e); // assert y != null 565 C x = av.get(e); 566 if (x != null) { 567 av.remove(e); 568 c = cfac.chineseRemainder(x, mi, y); 569 if (!c.isZERO()) { // 0 cannot happen 570 sv.put(e, c); 571 } 572 } else { 573 //c = cfac.fromInteger( y.getVal() ); 574 c = cfac.chineseRemainder(A.ring.coFac.getZERO(), mi, y); 575 if (!c.isZERO()) { // 0 cannot happen 576 sv.put(e, c); // c != null 577 } 578 } 579 } 580 // assert bv is empty = done 581 for (Map.Entry<ExpVector, C> me : av.entrySet()) { // rest of av 582 ExpVector e = me.getKey(); 583 C x = me.getValue(); // av.get(e); // assert x != null 584 //c = cfac.fromInteger( x.getVal() ); 585 c = cfac.chineseRemainder(x, mi, B.ring.coFac.getZERO()); 586 if (!c.isZERO()) { // 0 cannot happen 587 sv.put(e, c); // c != null 588 } 589 } 590 return S; 591 } 592 593 594 /** 595 * GenPolynomial monic, i.e. leadingBaseCoefficient == 1. If 596 * leadingBaseCoefficient is not invertible returns this unmodified. 597 * @param <C> coefficient type. 598 * @param p recursive GenPolynomial<GenPolynomial<C>>. 599 * @return monic(p). 600 */ 601 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> monic( 602 GenPolynomial<GenPolynomial<C>> p) { 603 if (p == null || p.isZERO()) { 604 return p; 605 } 606 C lc = p.leadingBaseCoefficient().leadingBaseCoefficient(); 607 if (!lc.isUnit()) { 608 return p; 609 } 610 C lm = lc.inverse(); 611 GenPolynomial<C> L = p.ring.coFac.getONE(); 612 L = L.multiply(lm); 613 return p.multiplyLeft(L); 614 } 615 616 617 /** 618 * GenSolvablePolynomial monic, i.e. leadingBaseCoefficient == 1. If 619 * leadingBaseCoefficient is not invertible returns this unmodified. 620 * @param <C> coefficient type. 621 * @param p recursive GenSolvablePolynomial<GenPolynomial<C>>. 622 * @return monic(p). 623 */ 624 public static <C extends RingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> monic( 625 GenSolvablePolynomial<GenPolynomial<C>> p) { 626 if (p == null || p.isZERO()) { 627 return p; 628 } 629 C lc = p.leadingBaseCoefficient().leadingBaseCoefficient(); 630 if (!lc.isUnit()) { 631 return p; 632 } 633 C lm = lc.inverse(); 634 GenPolynomial<C> L = p.ring.coFac.getONE(); 635 L = L.multiply(lm); 636 return p.multiplyLeft(L); 637 } 638 639 640 /** 641 * Polynomial list monic. 642 * @param <C> coefficient type. 643 * @param L list of polynomials with field coefficients. 644 * @return list of polynomials with leading coefficient 1. 645 */ 646 public static <C extends RingElem<C>> List<GenPolynomial<C>> monic(List<GenPolynomial<C>> L) { 647 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(L, 648 new UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>>() { 649 650 651 public GenPolynomial<C> eval(GenPolynomial<C> c) { 652 if (c == null) { 653 return null; 654 } 655 return c.monic(); 656 } 657 }); 658 } 659 660 661 /** 662 * Word polynomial list monic. 663 * @param <C> coefficient type. 664 * @param L list of word polynomials with field coefficients. 665 * @return list of word polynomials with leading coefficient 1. 666 */ 667 public static <C extends RingElem<C>> List<GenWordPolynomial<C>> wordMonic(List<GenWordPolynomial<C>> L) { 668 return ListUtil.<GenWordPolynomial<C>, GenWordPolynomial<C>> map(L, 669 new UnaryFunctor<GenWordPolynomial<C>, GenWordPolynomial<C>>() { 670 671 672 public GenWordPolynomial<C> eval(GenWordPolynomial<C> c) { 673 if (c == null) { 674 return null; 675 } 676 return c.monic(); 677 } 678 }); 679 } 680 681 682 /** 683 * Recursive polynomial list monic. 684 * @param <C> coefficient type. 685 * @param L list of recursive polynomials with field coefficients. 686 * @return list of polynomials with leading base coefficient 1. 687 */ 688 public static <C extends RingElem<C>> List<GenPolynomial<GenPolynomial<C>>> monicRec( 689 List<GenPolynomial<GenPolynomial<C>>> L) { 690 return ListUtil.<GenPolynomial<GenPolynomial<C>>, GenPolynomial<GenPolynomial<C>>> map(L, 691 new UnaryFunctor<GenPolynomial<GenPolynomial<C>>, GenPolynomial<GenPolynomial<C>>>() { 692 693 694 public GenPolynomial<GenPolynomial<C>> eval(GenPolynomial<GenPolynomial<C>> c) { 695 if (c == null) { 696 return null; 697 } 698 return PolyUtil.<C> monic(c); 699 } 700 }); 701 } 702 703 704 /** 705 * Polynomial list leading exponent vectors. 706 * @param <C> coefficient type. 707 * @param L list of polynomials. 708 * @return list of leading exponent vectors. 709 */ 710 public static <C extends RingElem<C>> List<ExpVector> leadingExpVector(List<GenPolynomial<C>> L) { 711 return ListUtil.<GenPolynomial<C>, ExpVector> map(L, new UnaryFunctor<GenPolynomial<C>, ExpVector>() { 712 713 714 public ExpVector eval(GenPolynomial<C> c) { 715 if (c == null) { 716 return null; 717 } 718 return c.leadingExpVector(); 719 } 720 }); 721 } 722 723 724 /** 725 * Extend coefficient variables. Extend all coefficient ExpVectors by i 726 * elements and multiply by x_j^k. 727 * @param pfac extended polynomial ring factory (by i variables in the 728 * coefficients). 729 * @param j index of variable to be used for multiplication. 730 * @param k exponent for x_j. 731 * @return extended polynomial. 732 */ 733 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> extendCoefficients( 734 GenPolynomialRing<GenPolynomial<C>> pfac, GenPolynomial<GenPolynomial<C>> A, int j, 735 long k) { 736 GenPolynomial<GenPolynomial<C>> Cp = pfac.getZERO().copy(); 737 if (A.isZERO()) { 738 return Cp; 739 } 740 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac; 741 //GenPolynomialRing<C> acfac = (GenPolynomialRing<C>) A.ring.coFac; 742 //int i = cfac.nvar - acfac.nvar; 743 Map<ExpVector, GenPolynomial<C>> CC = Cp.val; //getMap(); 744 for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.val.entrySet()) { 745 ExpVector e = y.getKey(); 746 GenPolynomial<C> a = y.getValue(); 747 GenPolynomial<C> f = a.extend(cfac, j, k); 748 CC.put(e, f); 749 } 750 return Cp; 751 } 752 753 754 /** 755 * Extend coefficient variables. Extend all coefficient ExpVectors by i 756 * elements and multiply by x_j^k. 757 * @param pfac extended polynomial ring factory (by i variables in the 758 * coefficients). 759 * @param j index of variable to be used for multiplication. 760 * @param k exponent for x_j. 761 * @return extended polynomial. 762 */ 763 public static <C extends RingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> extendCoefficients( 764 GenSolvablePolynomialRing<GenPolynomial<C>> pfac, 765 GenSolvablePolynomial<GenPolynomial<C>> A, int j, long k) { 766 GenSolvablePolynomial<GenPolynomial<C>> Cp = pfac.getZERO().copy(); 767 if (A.isZERO()) { 768 return Cp; 769 } 770 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac; 771 //GenPolynomialRing<C> acfac = (GenPolynomialRing<C>) A.ring.coFac; 772 //int i = cfac.nvar - acfac.nvar; 773 Map<ExpVector, GenPolynomial<C>> CC = Cp.val; //getMap(); 774 for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.val.entrySet()) { 775 ExpVector e = y.getKey(); 776 GenPolynomial<C> a = y.getValue(); 777 GenPolynomial<C> f = a.extend(cfac, j, k); 778 CC.put(e, f); 779 } 780 return Cp; 781 } 782 783 784 /** 785 * To recursive representation. Represent as polynomial in i+r variables 786 * with coefficients in i variables. Works for arbitrary term orders. 787 * @param <C> coefficient type. 788 * @param rfac recursive polynomial ring factory. 789 * @param A polynomial to be converted. 790 * @return Recursive representations of A in the ring rfac. 791 */ 792 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> toRecursive( 793 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) { 794 795 GenPolynomial<GenPolynomial<C>> B = rfac.getZERO().copy(); 796 if (A.isZERO()) { 797 return B; 798 } 799 //int i = rfac.nvar; 800 //GenPolynomial<C> zero = rfac.getZEROCoefficient(); 801 GenPolynomial<C> one = rfac.getONECoefficient(); 802 Map<ExpVector, GenPolynomial<C>> Bv = B.val; //getMap(); 803 for (Monomial<C> m : A) { 804 ExpVector e = m.e; 805 C a = m.c; 806 GenPolynomial<C> p = one.multiply(a); 807 Bv.put(e, p); 808 } 809 return B; 810 } 811 812 813 /** 814 * To recursive representation. Represent as solvable polynomial in i+r 815 * variables with coefficients in i variables. Works for arbitrary term 816 * orders. 817 * @param <C> coefficient type. 818 * @param rfac recursive solvable polynomial ring factory. 819 * @param A solvable polynomial to be converted. 820 * @return Recursive representations of A in the ring rfac. 821 */ 822 public static <C extends RingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> toRecursive( 823 GenSolvablePolynomialRing<GenPolynomial<C>> rfac, GenSolvablePolynomial<C> A) { 824 825 GenSolvablePolynomial<GenPolynomial<C>> B = rfac.getZERO().copy(); 826 if (A.isZERO()) { 827 return B; 828 } 829 //int i = rfac.nvar; 830 //GenPolynomial<C> zero = rfac.getZEROCoefficient(); 831 GenPolynomial<C> one = rfac.getONECoefficient(); 832 Map<ExpVector, GenPolynomial<C>> Bv = B.val; //getMap(); 833 for (Monomial<C> m : A) { 834 ExpVector e = m.e; 835 C a = m.c; 836 GenPolynomial<C> p = one.multiply(a); 837 Bv.put(e, p); 838 } 839 return B; 840 } 841 842 843 /** 844 * GenPolynomial coefficient wise remainder. 845 * @param <C> coefficient type. 846 * @param P GenPolynomial. 847 * @param s nonzero coefficient. 848 * @return coefficient wise remainder. 849 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 850 */ 851 public static <C extends RingElem<C>> GenPolynomial<C> baseRemainderPoly(GenPolynomial<C> P, C s) { 852 if (s == null || s.isZERO()) { 853 throw new ArithmeticException(P + " division by zero " + s); 854 } 855 GenPolynomial<C> h = P.ring.getZERO().copy(); 856 Map<ExpVector, C> hm = h.val; //getMap(); 857 for (Map.Entry<ExpVector, C> m : P.getMap().entrySet()) { 858 ExpVector f = m.getKey(); 859 C a = m.getValue(); 860 C x = a.remainder(s); 861 hm.put(f, x); 862 } 863 return h; 864 } 865 866 867 /** 868 * GenPolynomial sparse pseudo remainder. For univariate polynomials. 869 * @param <C> coefficient type. 870 * @param P GenPolynomial. 871 * @param S nonzero GenPolynomial. 872 * @return remainder with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 873 * m' ≤ deg(P)-deg(S) 874 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 875 * @deprecated(forRemoval=true) Use 876 * {@link #baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} 877 * instead 878 */ 879 @Deprecated 880 public static <C extends RingElem<C>> GenPolynomial<C> basePseudoRemainder(GenPolynomial<C> P, 881 GenPolynomial<C> S) { 882 return baseSparsePseudoRemainder(P, S); 883 } 884 885 886 /** 887 * GenPolynomial sparse pseudo remainder. For univariate polynomials. 888 * @param <C> coefficient type. 889 * @param P GenPolynomial. 890 * @param S nonzero GenPolynomial. 891 * @return remainder with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 892 * m' ≤ deg(P)-deg(S) 893 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 894 */ 895 public static <C extends RingElem<C>> GenPolynomial<C> baseSparsePseudoRemainder(GenPolynomial<C> P, 896 GenPolynomial<C> S) { 897 if (S == null || S.isZERO()) { 898 throw new ArithmeticException(P.toString() + " division by zero " + S); 899 } 900 if (P.isZERO()) { 901 return P; 902 } 903 if (S.isConstant()) { 904 return P.ring.getZERO(); 905 } 906 C c = S.leadingBaseCoefficient(); 907 ExpVector e = S.leadingExpVector(); 908 GenPolynomial<C> h; 909 GenPolynomial<C> r = P; 910 while (!r.isZERO()) { 911 ExpVector f = r.leadingExpVector(); 912 if (f.multipleOf(e)) { 913 C a = r.leadingBaseCoefficient(); 914 ExpVector fe = f.subtract(e); 915 C x = a.remainder(c); 916 if (x.isZERO()) { 917 C y = a.divide(c); 918 h = S.multiply(y, fe); // coeff a 919 } else { 920 r = r.multiply(c); // coeff ac 921 h = S.multiply(a, fe); // coeff ac 922 } 923 r = r.subtract(h); 924 } else { 925 break; 926 } 927 } 928 return r; 929 } 930 931 932 /** 933 * GenPolynomial dense pseudo remainder. For univariate polynomials. 934 * @param P GenPolynomial. 935 * @param S nonzero GenPolynomial. 936 * @return remainder with ldcf(S)<sup>m</sup> P = quotient * S + remainder. 937 * m == deg(P)-deg(S) 938 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 939 */ 940 public static <C extends RingElem<C>> GenPolynomial<C> baseDensePseudoRemainder(GenPolynomial<C> P, 941 GenPolynomial<C> S) { 942 if (S == null || S.isZERO()) { 943 throw new ArithmeticException(P + " division by zero " + S); 944 } 945 if (P.isZERO()) { 946 return P; 947 } 948 if (S.isConstant()) { 949 return P.ring.getZERO(); 950 } 951 long m = P.degree(0); 952 long n = S.degree(0); 953 C c = S.leadingBaseCoefficient(); 954 ExpVector e = S.leadingExpVector(); 955 GenPolynomial<C> h; 956 GenPolynomial<C> r = P; 957 for (long i = m; i >= n; i--) { 958 if (r.isZERO()) { 959 return r; 960 } 961 long k = r.degree(0); 962 if (i == k) { 963 ExpVector f = r.leadingExpVector(); 964 C a = r.leadingBaseCoefficient(); 965 f = f.subtract(e); // EVDIF( f, e ); 966 //System.out.println("red div = " + f); 967 r = r.multiply(c); // coeff ac 968 h = S.multiply(a, f); // coeff ac 969 r = r.subtract(h); 970 } else { 971 r = r.multiply(c); 972 } 973 } 974 return r; 975 } 976 977 978 /** 979 * GenPolynomial dense pseudo quotient. For univariate polynomials. 980 * @param P GenPolynomial. 981 * @param S nonzero GenPolynomial. 982 * @return quotient with ldcf(S)<sup>m</sup> P = quotient * S + remainder. m 983 * == deg(P)-deg(S) 984 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 985 */ 986 public static <C extends RingElem<C>> GenPolynomial<C> baseDensePseudoQuotient(GenPolynomial<C> P, 987 GenPolynomial<C> S) { 988 if (S == null || S.isZERO()) { 989 throw new ArithmeticException(P + " division by zero " + S); 990 } 991 if (P.isZERO()) { 992 return P; 993 } 994 //if (S.degree() <= 0) { 995 // return l^n P; //P.ring.getZERO(); 996 //} 997 long m = P.degree(0); 998 long n = S.degree(0); 999 C c = S.leadingBaseCoefficient(); 1000 ExpVector e = S.leadingExpVector(); 1001 GenPolynomial<C> q = P.ring.getZERO(); 1002 GenPolynomial<C> h; 1003 GenPolynomial<C> r = P; 1004 for (long i = m; i >= n; i--) { 1005 if (r.isZERO()) { 1006 return q; 1007 } 1008 long k = r.degree(0); 1009 if (i == k) { 1010 ExpVector f = r.leadingExpVector(); 1011 C a = r.leadingBaseCoefficient(); 1012 f = f.subtract(e); // EVDIF( f, e ); 1013 //System.out.println("red div = " + f); 1014 r = r.multiply(c); // coeff ac 1015 h = S.multiply(a, f); // coeff ac 1016 r = r.subtract(h); 1017 q = q.multiply(c); 1018 q = q.sum(a, f); 1019 } else { 1020 q = q.multiply(c); 1021 r = r.multiply(c); 1022 } 1023 } 1024 return q; 1025 } 1026 1027 1028 /** 1029 * GenPolynomial sparse pseudo divide. For univariate polynomials or exact 1030 * division. 1031 * @param <C> coefficient type. 1032 * @param P GenPolynomial. 1033 * @param S nonzero GenPolynomial. 1034 * @return quotient with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 1035 * m' ≤ deg(P)-deg(S) 1036 * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial). 1037 */ 1038 public static <C extends RingElem<C>> GenPolynomial<C> basePseudoDivide(GenPolynomial<C> P, 1039 GenPolynomial<C> S) { 1040 if (S == null || S.isZERO()) { 1041 throw new ArithmeticException(P.toString() + " division by zero " + S); 1042 } 1043 //if (S.ring.nvar != 1) { 1044 // ok if exact division 1045 // throw new RuntimeException(this.getClass().getName() 1046 // + " univariate polynomials only"); 1047 //} 1048 if (P.isZERO() || S.isONE()) { 1049 return P; 1050 } 1051 C c = S.leadingBaseCoefficient(); 1052 ExpVector e = S.leadingExpVector(); 1053 GenPolynomial<C> h; 1054 GenPolynomial<C> r = P; 1055 GenPolynomial<C> q = S.ring.getZERO().copy(); 1056 1057 while (!r.isZERO()) { 1058 ExpVector f = r.leadingExpVector(); 1059 if (f.multipleOf(e)) { 1060 C a = r.leadingBaseCoefficient(); 1061 f = f.subtract(e); 1062 C x = a.remainder(c); 1063 if (x.isZERO()) { 1064 C y = a.divide(c); 1065 q = q.sum(y, f); 1066 h = S.multiply(y, f); // coeff a 1067 } else { 1068 q = q.multiply(c); 1069 q = q.sum(a, f); 1070 r = r.multiply(c); // coeff ac 1071 h = S.multiply(a, f); // coeff ac 1072 } 1073 r = r.subtract(h); 1074 } else { 1075 break; 1076 } 1077 } 1078 return q; 1079 } 1080 1081 1082 /** 1083 * GenPolynomial sparse pseudo quotient and remainder. For univariate 1084 * polynomials or exact division. 1085 * @param <C> coefficient type. 1086 * @param P GenPolynomial. 1087 * @param S nonzero GenPolynomial. 1088 * @return [ quotient, remainder ] with ldcf(S)<sup>m'</sup> P = quotient * 1089 * S + remainder. m' ≤ deg(P)-deg(S) 1090 * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial). 1091 */ 1092 @SuppressWarnings("unchecked") 1093 public static <C extends RingElem<C>> GenPolynomial<C>[] basePseudoQuotientRemainder( 1094 final GenPolynomial<C> P, final GenPolynomial<C> S) { 1095 if (S == null || S.isZERO()) { 1096 throw new ArithmeticException(P.toString() + " division by zero " + S); 1097 } 1098 //if (S.ring.nvar != 1) { 1099 // ok if exact division 1100 // throw new RuntimeException(this.getClass().getName() 1101 // + " univariate polynomials only"); 1102 //} 1103 GenPolynomial<C>[] ret = new GenPolynomial[2]; 1104 ret[0] = null; 1105 ret[1] = null; 1106 if (P.isZERO() || S.isONE()) { 1107 ret[0] = P; 1108 ret[1] = S.ring.getZERO(); 1109 return ret; 1110 } 1111 //logger.debug("P, S = " + P + ", " + S); 1112 final C c = S.leadingBaseCoefficient(); 1113 final ExpVector e = S.leadingExpVector(); 1114 GenPolynomial<C> h; 1115 GenPolynomial<C> r = P; 1116 GenPolynomial<C> q = S.ring.getZERO().copy(); 1117 1118 while (!r.isZERO()) { 1119 ExpVector f = r.leadingExpVector(); 1120 if (f.multipleOf(e)) { 1121 C a = r.leadingBaseCoefficient(); 1122 f = f.subtract(e); 1123 C x = a.remainder(c); 1124 if (x.isZERO()) { 1125 C y = a.divide(c); 1126 q = q.sum(y, f); 1127 h = S.multiply(y, f); // coeff a 1128 } else { 1129 q = q.multiply(c); 1130 q = q.sum(a, f); 1131 r = r.multiply(c); // coeff a c 1132 h = S.multiply(a, f); // coeff c a 1133 } 1134 r = r.subtract(h); 1135 //logger.debug("q, r = " + q + ", " + r); 1136 } else { 1137 break; 1138 } 1139 } 1140 //GenPolynomial<C> rhs = q.multiply(S).sum(r); 1141 //GenPolynomial<C> lhs = P; 1142 ret[0] = q; 1143 ret[1] = r; 1144 return ret; 1145 } 1146 1147 1148 /** 1149 * Is GenPolynomial pseudo quotient and remainder. For univariate 1150 * polynomials. 1151 * @param <C> coefficient type. 1152 * @param P base GenPolynomial. 1153 * @param S nonzero base GenPolynomial. 1154 * @return true, if P = q * S + r, else false. 1155 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1156 * <b>Note:</b> not always meaningful and working 1157 */ 1158 public static <C extends RingElem<C>> boolean isBasePseudoQuotientRemainder(GenPolynomial<C> P, 1159 GenPolynomial<C> S, GenPolynomial<C> q, GenPolynomial<C> r) { 1160 GenPolynomial<C> rhs = q.multiply(S).sum(r); 1161 //System.out.println("rhs,1 = " + rhs); 1162 GenPolynomial<C> lhs = P; 1163 C ldcf = S.leadingBaseCoefficient(); 1164 long d = P.degree(0) - S.degree(0) + 1; 1165 d = (d > 0 ? d : -d + 2); 1166 for (long i = 0; i <= d; i++) { 1167 //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); 1168 if (lhs.equals(rhs) || lhs.negate().equals(rhs)) { 1169 //System.out.println("lhs,1 = " + lhs); 1170 return true; 1171 } 1172 lhs = lhs.multiply(ldcf); 1173 } 1174 GenPolynomial<C> Pp = P; 1175 rhs = q.multiply(S); 1176 //System.out.println("rhs,2 = " + rhs); 1177 for (long i = 0; i <= d; i++) { 1178 lhs = Pp.subtract(r); 1179 //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); 1180 if (lhs.equals(rhs) || lhs.negate().equals(rhs)) { 1181 //System.out.println("lhs,2 = " + lhs); 1182 return true; 1183 } 1184 Pp = Pp.multiply(ldcf); 1185 } 1186 C a = P.leadingBaseCoefficient(); 1187 rhs = q.multiply(S).sum(r); 1188 C b = rhs.leadingBaseCoefficient(); 1189 C gcd = a.gcd(b); 1190 C p = a.multiply(b); 1191 C lcm = p.divide(gcd); 1192 C ap = lcm.divide(a); 1193 C bp = lcm.divide(b); 1194 if (P.multiply(ap).equals(rhs.multiply(bp))) { 1195 return true; 1196 } 1197 return false; 1198 } 1199 1200 1201 /** 1202 * GenPolynomial divide. For recursive polynomials. Division by coefficient 1203 * ring element. 1204 * @param <C> coefficient type. 1205 * @param P recursive GenPolynomial. 1206 * @param s GenPolynomial. 1207 * @return this/s. 1208 */ 1209 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursiveDivide( 1210 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<C> s) { 1211 if (s == null || s.isZERO()) { 1212 throw new ArithmeticException("division by zero " + P + ", " + s); 1213 } 1214 if (P.isZERO()) { 1215 return P; 1216 } 1217 if (s.isONE()) { 1218 return P; 1219 } 1220 GenPolynomial<GenPolynomial<C>> p = P.ring.getZERO().copy(); 1221 SortedMap<ExpVector, GenPolynomial<C>> pv = p.val; //getMap(); 1222 for (Map.Entry<ExpVector, GenPolynomial<C>> m1 : P.getMap().entrySet()) { 1223 GenPolynomial<C> c1 = m1.getValue(); 1224 ExpVector e1 = m1.getKey(); 1225 GenPolynomial<C> c = PolyUtil.<C> basePseudoDivide(c1, s); 1226 if (!c.isZERO()) { 1227 pv.put(e1, c); // or m1.setValue( c ) 1228 } else { 1229 logger.warn("rDiv, P = {}", P); 1230 logger.warn("rDiv, c1 = {}", c1); 1231 logger.warn("rDiv, s = {}", s); 1232 logger.warn("rDiv, c = {}", c); 1233 throw new RuntimeException("something is wrong"); 1234 } 1235 } 1236 return p; 1237 } 1238 1239 1240 /** 1241 * GenPolynomial divide. For recursive polynomials. Division by coefficient 1242 * ring element. 1243 * @param <C> coefficient type. 1244 * @param P recursive GenPolynomial. 1245 * @param s GenPolynomial. 1246 * @return this/s. 1247 */ 1248 public static <C extends RingElem<C>> GenWordPolynomial<GenPolynomial<C>> recursiveDivide( 1249 GenWordPolynomial<GenPolynomial<C>> P, GenPolynomial<C> s) { 1250 if (s == null || s.isZERO()) { 1251 throw new ArithmeticException("division by zero " + P + ", " + s); 1252 } 1253 if (P.isZERO()) { 1254 return P; 1255 } 1256 if (s.isONE()) { 1257 return P; 1258 } 1259 GenWordPolynomial<GenPolynomial<C>> p = P.ring.getZERO().copy(); 1260 SortedMap<Word, GenPolynomial<C>> pv = p.val; //getMap(); 1261 for (Map.Entry<Word, GenPolynomial<C>> m1 : P.getMap().entrySet()) { 1262 GenPolynomial<C> c1 = m1.getValue(); 1263 Word e1 = m1.getKey(); 1264 GenPolynomial<C> c = PolyUtil.<C> basePseudoDivide(c1, s); 1265 if (!c.isZERO()) { 1266 pv.put(e1, c); // or m1.setValue( c ) 1267 } else { 1268 logger.warn("rDiv, P = {}", P); 1269 logger.warn("rDiv, c1 = {}", c1); 1270 logger.warn("rDiv, s = {}", s); 1271 logger.warn("rDiv, c = {}", c); 1272 throw new RuntimeException("something is wrong"); 1273 } 1274 } 1275 return p; 1276 } 1277 1278 1279 /** 1280 * GenPolynomial base divide. For recursive polynomials. Division by 1281 * coefficient ring element. 1282 * @param <C> coefficient type. 1283 * @param P recursive GenPolynomial. 1284 * @param s coefficient. 1285 * @return this/s. 1286 */ 1287 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> baseRecursiveDivide( 1288 GenPolynomial<GenPolynomial<C>> P, C s) { 1289 if (s == null || s.isZERO()) { 1290 throw new ArithmeticException("division by zero " + P + ", " + s); 1291 } 1292 if (P.isZERO()) { 1293 return P; 1294 } 1295 if (s.isONE()) { 1296 return P; 1297 } 1298 GenPolynomial<GenPolynomial<C>> p = P.ring.getZERO().copy(); 1299 SortedMap<ExpVector, GenPolynomial<C>> pv = p.val; //getMap(); 1300 for (Map.Entry<ExpVector, GenPolynomial<C>> m1 : P.getMap().entrySet()) { 1301 GenPolynomial<C> c1 = m1.getValue(); 1302 ExpVector e1 = m1.getKey(); 1303 GenPolynomial<C> c = PolyUtil.<C> coefficientBasePseudoDivide(c1, s); 1304 if (!c.isZERO()) { 1305 pv.put(e1, c); // or m1.setValue( c ) 1306 } else { 1307 logger.warn("pu, c1 = {}", c1); 1308 logger.warn("pu, s = {}", s); 1309 logger.warn("pu, c = {}", c); 1310 throw new RuntimeException("something is wrong"); 1311 } 1312 } 1313 return p; 1314 } 1315 1316 1317 /** 1318 * GenPolynomial sparse pseudo remainder. For recursive polynomials. 1319 * @param <C> coefficient type. 1320 * @param P recursive GenPolynomial. 1321 * @param S nonzero recursive GenPolynomial. 1322 * @return remainder with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 1323 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1324 * @deprecated(forRemoval=true) Use 1325 * {@link #recursiveSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} 1326 * instead 1327 */ 1328 @Deprecated 1329 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursivePseudoRemainder( 1330 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S) { 1331 return recursiveSparsePseudoRemainder(P, S); 1332 } 1333 1334 1335 /** 1336 * GenPolynomial sparse pseudo remainder. For recursive polynomials. 1337 * @param <C> coefficient type. 1338 * @param P recursive GenPolynomial. 1339 * @param S nonzero recursive GenPolynomial. 1340 * @return remainder with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 1341 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1342 */ 1343 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursiveSparsePseudoRemainder( 1344 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S) { 1345 if (S == null || S.isZERO()) { 1346 throw new ArithmeticException(P + " division by zero " + S); 1347 } 1348 if (P == null || P.isZERO()) { 1349 return P; 1350 } 1351 if (S.isConstant()) { 1352 return P.ring.getZERO(); 1353 } 1354 GenPolynomial<C> c = S.leadingBaseCoefficient(); 1355 ExpVector e = S.leadingExpVector(); 1356 GenPolynomial<GenPolynomial<C>> h; 1357 GenPolynomial<GenPolynomial<C>> r = P; 1358 while (!r.isZERO()) { 1359 ExpVector f = r.leadingExpVector(); 1360 if (f.multipleOf(e)) { 1361 GenPolynomial<C> a = r.leadingBaseCoefficient(); 1362 f = f.subtract(e); 1363 GenPolynomial<C> x = c; //test basePseudoRemainder(a,c); 1364 if (x.isZERO()) { 1365 GenPolynomial<C> y = PolyUtil.<C> basePseudoDivide(a, c); 1366 h = S.multiply(y, f); // coeff a 1367 } else { 1368 r = r.multiply(c); // coeff a c 1369 h = S.multiply(a, f); // coeff c a 1370 } 1371 r = r.subtract(h); 1372 } else { 1373 break; 1374 } 1375 } 1376 return r; 1377 } 1378 1379 1380 /** 1381 * GenPolynomial dense pseudo remainder. For recursive polynomials. 1382 * @param P recursive GenPolynomial. 1383 * @param S nonzero recursive GenPolynomial. 1384 * @return remainder with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 1385 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1386 */ 1387 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursiveDensePseudoRemainder( 1388 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S) { 1389 if (S == null || S.isZERO()) { 1390 throw new ArithmeticException(P + " division by zero " + S); 1391 } 1392 if (P == null || P.isZERO()) { 1393 return P; 1394 } 1395 if (S.isConstant()) { 1396 return P.ring.getZERO(); 1397 } 1398 long m = P.degree(0); 1399 long n = S.degree(0); 1400 GenPolynomial<C> c = S.leadingBaseCoefficient(); 1401 ExpVector e = S.leadingExpVector(); 1402 GenPolynomial<GenPolynomial<C>> h; 1403 GenPolynomial<GenPolynomial<C>> r = P; 1404 for (long i = m; i >= n; i--) { 1405 if (r.isZERO()) { 1406 return r; 1407 } 1408 long k = r.degree(0); 1409 if (i == k) { 1410 ExpVector f = r.leadingExpVector(); 1411 GenPolynomial<C> a = r.leadingBaseCoefficient(); 1412 f = f.subtract(e); //EVDIF( f, e ); 1413 //System.out.println("red div = " + f); 1414 r = r.multiply(c); // coeff ac 1415 h = S.multiply(a, f); // coeff ac 1416 r = r.subtract(h); 1417 } else { 1418 r = r.multiply(c); 1419 } 1420 } 1421 return r; 1422 } 1423 1424 1425 /** 1426 * GenPolynomial recursive pseudo divide. For recursive polynomials. 1427 * @param <C> coefficient type. 1428 * @param P recursive GenPolynomial. 1429 * @param S nonzero recursive GenPolynomial. 1430 * @return quotient with ldcf(S)<sup>m'</sup> P = quotient * S + remainder. 1431 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1432 */ 1433 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursivePseudoDivide( 1434 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S) { 1435 if (S == null || S.isZERO()) { 1436 throw new ArithmeticException(P + " division by zero " + S); 1437 } 1438 //if (S.ring.nvar != 1) { 1439 // ok if exact division 1440 // throw new RuntimeException(this.getClass().getName() 1441 // + " univariate polynomials only"); 1442 //} 1443 if (P == null || P.isZERO()) { 1444 return P; 1445 } 1446 if (S.isONE()) { 1447 return P; 1448 } 1449 GenPolynomial<C> c = S.leadingBaseCoefficient(); 1450 ExpVector e = S.leadingExpVector(); 1451 GenPolynomial<GenPolynomial<C>> h; 1452 GenPolynomial<GenPolynomial<C>> r = P; 1453 GenPolynomial<GenPolynomial<C>> q = S.ring.getZERO().copy(); 1454 while (!r.isZERO()) { 1455 ExpVector f = r.leadingExpVector(); 1456 if (f.multipleOf(e)) { 1457 GenPolynomial<C> a = r.leadingBaseCoefficient(); 1458 f = f.subtract(e); 1459 GenPolynomial<C> x = PolyUtil.<C> baseSparsePseudoRemainder(a, c); 1460 if (x.isZERO() && !c.isConstant()) { 1461 GenPolynomial<C> y = PolyUtil.<C> basePseudoDivide(a, c); 1462 q = q.sum(y, f); 1463 h = S.multiply(y, f); // coeff a 1464 } else { 1465 q = q.multiply(c); 1466 q = q.sum(a, f); 1467 r = r.multiply(c); // coeff ac 1468 h = S.multiply(a, f); // coeff ac 1469 } 1470 r = r.subtract(h); 1471 } else { 1472 break; 1473 } 1474 } 1475 return q; 1476 } 1477 1478 1479 /** 1480 * Is recursive GenPolynomial pseudo quotient and remainder. For recursive 1481 * polynomials. 1482 * @param <C> coefficient type. 1483 * @param P recursive GenPolynomial. 1484 * @param S nonzero recursive GenPolynomial. 1485 * @return true, if P ~= q * S + r, else false. 1486 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1487 * <b>Note:</b> not always meaningful and working 1488 */ 1489 public static <C extends RingElem<C>> boolean isRecursivePseudoQuotientRemainder( 1490 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S, 1491 GenPolynomial<GenPolynomial<C>> q, GenPolynomial<GenPolynomial<C>> r) { 1492 GenPolynomial<GenPolynomial<C>> rhs = q.multiply(S).sum(r); 1493 GenPolynomial<GenPolynomial<C>> lhs = P; 1494 GenPolynomial<C> ldcf = S.leadingBaseCoefficient(); 1495 long d = P.degree(0) - S.degree(0) + 1; 1496 d = (d > 0 ? d : -d + 2); 1497 for (long i = 0; i <= d; i++) { 1498 //System.out.println("lhs = " + lhs); 1499 //System.out.println("rhs = " + rhs); 1500 //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); 1501 if (lhs.equals(rhs)) { 1502 return true; 1503 } 1504 lhs = lhs.multiply(ldcf); 1505 } 1506 GenPolynomial<GenPolynomial<C>> Pp = P; 1507 rhs = q.multiply(S); 1508 //System.out.println("rhs,2 = " + rhs); 1509 for (long i = 0; i <= d; i++) { 1510 lhs = Pp.subtract(r); 1511 //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); 1512 if (lhs.equals(rhs)) { 1513 //System.out.println("lhs,2 = " + lhs); 1514 return true; 1515 } 1516 Pp = Pp.multiply(ldcf); 1517 } 1518 GenPolynomial<C> a = P.leadingBaseCoefficient(); 1519 rhs = q.multiply(S).sum(r); 1520 GenPolynomial<C> b = rhs.leadingBaseCoefficient(); 1521 GenPolynomial<GenPolynomial<C>> Pb = P.multiply(b); 1522 GenPolynomial<GenPolynomial<C>> rhsa = rhs.multiply(a); 1523 if (Pb.equals(rhsa)) { 1524 return true; 1525 } 1526 //System.out.println("b = " + b); 1527 //System.out.println("a = " + a); 1528 //System.out.println("P*b = " + Pb); 1529 //System.out.println("rhs*a = " + rhsa); 1530 if (Pb.degree() != rhsa.degree() 1531 || !Pb.leadingBaseCoefficient().equals(rhsa.leadingBaseCoefficient())) { 1532 return false; 1533 } 1534 return false; 1535 } 1536 1537 1538 /** 1539 * GenPolynomial pseudo divide. For recursive polynomials. 1540 * @param <C> coefficient type. 1541 * @param P recursive GenPolynomial. 1542 * @param s nonzero GenPolynomial. 1543 * @return quotient with ldcf(s)<sup>m</sup> P = quotient * s + remainder. 1544 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1545 */ 1546 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> coefficientPseudoDivide( 1547 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<C> s) { 1548 if (s == null || s.isZERO()) { 1549 throw new ArithmeticException(P + " division by zero " + s); 1550 } 1551 if (P.isZERO()) { 1552 return P; 1553 } 1554 GenPolynomial<GenPolynomial<C>> p = P.ring.getZERO().copy(); 1555 SortedMap<ExpVector, GenPolynomial<C>> pv = p.val; 1556 for (Map.Entry<ExpVector, GenPolynomial<C>> m : P.getMap().entrySet()) { 1557 ExpVector e = m.getKey(); 1558 GenPolynomial<C> c1 = m.getValue(); 1559 GenPolynomial<C> c = basePseudoDivide(c1, s); 1560 if (debug) { 1561 GenPolynomial<C> x = c1.remainder(s); 1562 if (!x.isZERO()) { 1563 logger.info("divide x = {}", x); 1564 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1565 } 1566 } 1567 if (c.isZERO()) { 1568 //logger.warn("no exact division: {}/{}", c1, s); 1569 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1570 } 1571 pv.put(e, c); // or m1.setValue( c ) 1572 } 1573 return p; 1574 } 1575 1576 1577 /** 1578 * GenPolynomial pseudo divide. For polynomials. 1579 * @param <C> coefficient type. 1580 * @param P GenPolynomial. 1581 * @param s nonzero coefficient. 1582 * @return quotient with ldcf(s)<sup>m</sup> P = quotient * s + remainder. 1583 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 1584 */ 1585 public static <C extends RingElem<C>> GenPolynomial<C> coefficientBasePseudoDivide(GenPolynomial<C> P, 1586 C s) { 1587 if (s == null || s.isZERO()) { 1588 throw new ArithmeticException(P + " division by zero " + s); 1589 } 1590 if (P.isZERO()) { 1591 return P; 1592 } 1593 GenPolynomial<C> p = P.ring.getZERO().copy(); 1594 SortedMap<ExpVector, C> pv = p.val; 1595 for (Map.Entry<ExpVector, C> m : P.getMap().entrySet()) { 1596 ExpVector e = m.getKey(); 1597 C c1 = m.getValue(); 1598 C c = c1.divide(s); 1599 if (debug) { 1600 C x = c1.remainder(s); 1601 if (!x.isZERO()) { 1602 logger.info("divide x = {}", x); 1603 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1604 } 1605 } 1606 if (c.isZERO()) { 1607 //logger.warn("no exact division: {}/{}", c1, s); 1608 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1609 } 1610 pv.put(e, c); // or m1.setValue( c ) 1611 } 1612 return p; 1613 } 1614 1615 1616 /** 1617 * GenExteriorPolynomial polynomial exterior derivative. 1618 * @param <C> coefficient type. 1619 * @param P GenExteriorPolynomial. 1620 * @return exteriorDerivative(P). 1621 */ 1622 public static <C extends RingElem<C>> GenExteriorPolynomial<C> exteriorDerivative( 1623 GenExteriorPolynomial<C> P) { 1624 if (P == null || P.isZERO()) { 1625 return P; 1626 } 1627 GenExteriorPolynomialRing<C> pfac = P.ring; 1628 IndexFactory ifac = pfac.ixfac; 1629 int im = ifac.imaxlength; 1630 if (im == 0) { 1631 return pfac.getZERO(); 1632 } 1633 //RingFactory<C> rf = pfac.coFac; 1634 GenExteriorPolynomial<C> d = pfac.getZERO().copy(); 1635 Map<IndexList, C> dm = d.val; 1636 for (Map.Entry<IndexList, C> m : P.getMap().entrySet()) { 1637 //if (P.length() == 1) { 1638 //Map.Entry<IndexList, C> m = P.leadingMonomial(); 1639 C a = m.getValue(); 1640 IndexList il = m.getKey(); 1641 C b; 1642 IndexList bi; 1643 for (int i = 1; i <= im; i++) { 1644 IndexList di = new IndexList(ifac, new int[] { i }); 1645 bi = di.multiply(il); 1646 if (bi.signum() == 0) { 1647 continue; 1648 } 1649 b = a; // b = a.derivative(); 1650 if (bi.signum() < 0) { 1651 bi = bi.negate(); 1652 b = b.negate(); 1653 } 1654 dm.put(bi, b); 1655 } 1656 } 1657 return d; 1658 } 1659 1660 1661 /** 1662 * GenExteriorPolynomial over polynomial exterior derivative. 1663 * @param <C> coefficient type. 1664 * @param P GenExteriorPolynomial<GenPolynomial>. 1665 * @return exteriorDerivativePoly(P). 1666 */ 1667 public static <C extends RingElem<C>> GenExteriorPolynomial<GenPolynomial<C>> exteriorDerivativePoly( 1668 GenExteriorPolynomial<GenPolynomial<C>> P) { 1669 if (P == null || P.isZERO()) { 1670 return P; 1671 } 1672 GenExteriorPolynomialRing<GenPolynomial<C>> pfac = P.ring; 1673 IndexFactory ifac = pfac.ixfac; 1674 int im = ifac.imaxlength; 1675 if (im == 0) { 1676 return pfac.getZERO(); 1677 } 1678 //RingFactory<GenPolynomial<C>> rf = pfac.coFac; 1679 GenExteriorPolynomial<GenPolynomial<C>> d = pfac.getZERO().copy(); 1680 Map<IndexList, GenPolynomial<C>> dm = d.val; 1681 for (Map.Entry<IndexList, GenPolynomial<C>> m : P.getMap().entrySet()) { 1682 //if (P.length() == 1) { 1683 //Map.Entry<IndexList, C> m = P.leadingMonomial(); 1684 GenPolynomial<C> a = m.getValue(); 1685 IndexList il = m.getKey(); 1686 GenPolynomial<C> b; 1687 IndexList bi; 1688 for (int i = 1; i <= im; i++) { 1689 IndexList di = new IndexList(ifac, new int[] { i }); 1690 bi = di.multiply(il); 1691 if (bi.signum() == 0) { 1692 continue; 1693 } 1694 b = PolyUtil.<C> baseDerivative(a, i - 1); //a.derivative(); 1695 //System.out.println("baseDerivative a = " + a + ", i-1 = " + (i-1) + ", b = " + b); 1696 if (b.isZERO()) { 1697 continue; 1698 } 1699 if (bi.signum() < 0) { 1700 bi = bi.negate(); 1701 b = b.negate(); 1702 } 1703 dm.put(bi, b); 1704 } 1705 } 1706 return d; 1707 } 1708 1709 1710 /** 1711 * GenPolynomial polynomial derivative main variable. 1712 * @param <C> coefficient type. 1713 * @param P GenPolynomial. 1714 * @return derivative(P). 1715 */ 1716 public static <C extends RingElem<C>> GenPolynomial<C> baseDerivative(GenPolynomial<C> P) { 1717 if (P == null || P.isZERO()) { 1718 return P; 1719 } 1720 GenPolynomialRing<C> pfac = P.ring; 1721 if (pfac.nvar == 0) { 1722 return pfac.getZERO(); 1723 } 1724 if (pfac.nvar > 1) { 1725 // baseContent not possible by return type 1726 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 1727 } 1728 RingFactory<C> rf = pfac.coFac; 1729 GenPolynomial<C> d = pfac.getZERO().copy(); 1730 Map<ExpVector, C> dm = d.val; //getMap(); 1731 for (Map.Entry<ExpVector, C> m : P.getMap().entrySet()) { 1732 ExpVector f = m.getKey(); 1733 long fl = f.getVal(0); 1734 if (fl > 0) { 1735 C cf = rf.fromInteger(fl); 1736 C a = m.getValue(); 1737 C x = a.multiply(cf); 1738 if (x != null && !x.isZERO()) { 1739 ExpVector e = ExpVector.create(1, 0, fl - 1L); 1740 dm.put(e, x); 1741 } 1742 } 1743 } 1744 return d; 1745 } 1746 1747 1748 /** 1749 * GenPolynomial polynomial partial derivative variable r. 1750 * @param <C> coefficient type. 1751 * @param P GenPolynomial. 1752 * @param r variable for partial deriviate. 1753 * @return derivative(P,r). 1754 */ 1755 public static <C extends RingElem<C>> GenPolynomial<C> baseDerivative(GenPolynomial<C> P, int r) { 1756 if (P == null || P.isZERO()) { 1757 return P; 1758 } 1759 GenPolynomialRing<C> pfac = P.ring; 1760 if (r < 0 || pfac.nvar <= r) { 1761 throw new IllegalArgumentException( 1762 P.getClass().getName() + " derivative variable out of bound " + r); 1763 } 1764 int rp = pfac.nvar - 1 - r; 1765 RingFactory<C> rf = pfac.coFac; 1766 GenPolynomial<C> d = pfac.getZERO().copy(); 1767 Map<ExpVector, C> dm = d.val; //getMap(); 1768 for (Map.Entry<ExpVector, C> m : P.getMap().entrySet()) { 1769 ExpVector f = m.getKey(); 1770 long fl = f.getVal(rp); 1771 if (fl > 0) { 1772 C cf = rf.fromInteger(fl); 1773 C a = m.getValue(); 1774 C x = a.multiply(cf); 1775 if (x != null && !x.isZERO()) { 1776 ExpVector e = f.subst(rp, fl - 1L); 1777 dm.put(e, x); 1778 } 1779 } 1780 } 1781 return d; 1782 } 1783 1784 1785 /** 1786 * GenPolynomial polynomial integral main variable. 1787 * @param <C> coefficient type. 1788 * @param P GenPolynomial. 1789 * @return integral(P). 1790 */ 1791 public static <C extends RingElem<C>> GenPolynomial<C> baseIntegral(GenPolynomial<C> P) { 1792 if (P == null || P.isZERO()) { 1793 return P; 1794 } 1795 GenPolynomialRing<C> pfac = P.ring; 1796 if (pfac.nvar == 0) { 1797 return pfac.getONE(); 1798 } 1799 if (pfac.nvar > 1) { 1800 // baseContent not possible by return type 1801 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 1802 } 1803 RingFactory<C> rf = pfac.coFac; 1804 GenPolynomial<C> d = pfac.getZERO().copy(); 1805 Map<ExpVector, C> dm = d.val; //getMap(); 1806 for (Map.Entry<ExpVector, C> m : P.getMap().entrySet()) { 1807 ExpVector f = m.getKey(); 1808 long fl = f.getVal(0); 1809 fl++; 1810 C cf = rf.fromInteger(fl); 1811 C a = m.getValue(); 1812 C x = a.divide(cf); 1813 if (x != null && !x.isZERO()) { 1814 ExpVector e = ExpVector.create(1, 0, fl); 1815 dm.put(e, x); 1816 } 1817 } 1818 return d; 1819 } 1820 1821 1822 /** 1823 * GenPolynomial recursive polynomial derivative main variable. 1824 * @param <C> coefficient type. 1825 * @param P recursive GenPolynomial. 1826 * @return derivative(P). 1827 */ 1828 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> recursiveDerivative( 1829 GenPolynomial<GenPolynomial<C>> P) { 1830 if (P == null || P.isZERO()) { 1831 return P; 1832 } 1833 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 1834 if (pfac.nvar == 0) { 1835 return pfac.getZERO(); 1836 } 1837 if (pfac.nvar > 1) { 1838 // baseContent not possible by return type 1839 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 1840 } 1841 GenPolynomialRing<C> pr = (GenPolynomialRing<C>) pfac.coFac; 1842 RingFactory<C> rf = pr.coFac; 1843 GenPolynomial<GenPolynomial<C>> d = pfac.getZERO().copy(); 1844 Map<ExpVector, GenPolynomial<C>> dm = d.val; //getMap(); 1845 for (Map.Entry<ExpVector, GenPolynomial<C>> m : P.getMap().entrySet()) { 1846 ExpVector f = m.getKey(); 1847 long fl = f.getVal(0); 1848 if (fl > 0) { 1849 C cf = rf.fromInteger(fl); 1850 GenPolynomial<C> a = m.getValue(); 1851 GenPolynomial<C> x = a.multiply(cf); 1852 if (x != null && !x.isZERO()) { 1853 ExpVector e = ExpVector.create(1, 0, fl - 1L); 1854 dm.put(e, x); 1855 } 1856 } 1857 } 1858 return d; 1859 } 1860 1861 1862 /** 1863 * Factor coefficient bound. The product of all maxNorms of potential 1864 * factors is less than or equal to 2**b times the maxNorm of A. Gelfonds 1865 * bound is used. 1866 * @param e degree vector of a GenPolynomial A. 1867 * @return 2**b. 1868 * @see "maspoly.SACIPOL.mi#IPFCB from SAC2/MAS" 1869 */ 1870 public static BigInteger factorBound(ExpVector e) { 1871 long n = 0; 1872 java.math.BigInteger p = java.math.BigInteger.ONE; 1873 java.math.BigInteger v; 1874 if (e == null || e.isZERO()) { 1875 return BigInteger.ONE; 1876 } 1877 for (int i = 0; i < e.length(); i++) { 1878 if (e.getVal(i) > 0L) { 1879 n += (2 * e.getVal(i) - 1); 1880 v = new java.math.BigInteger("" + (e.getVal(i) - 1)); 1881 p = p.multiply(v); 1882 } 1883 } 1884 n += (p.bitCount() + 1); // log2(p) 1885 n /= 2; 1886 v = new java.math.BigInteger("" + 2); 1887 while (n >= 16) { 1888 n -= 16; 1889 v = v.shiftLeft(16); 1890 } 1891 if (n > 0) { 1892 v = v.shiftLeft((int) n); // n < 16 1893 } 1894 BigInteger N = new BigInteger(v); 1895 return N; 1896 } 1897 1898 1899 /** 1900 * Absolute norm. Square root of the sum of the squared coefficients. 1901 * @param p GenPolynomial 1902 * @return sqrt( sum<sub>i</sub> |c<sub>i</sub>|<sup>2</sup> ). 1903 */ 1904 @SuppressWarnings("unchecked") 1905 public static <C extends RingElem<C>> C absNorm(GenPolynomial<C> p) { 1906 if (p == null) { 1907 return null; 1908 } 1909 C a = p.ring.getZEROCoefficient(); 1910 if (a instanceof StarRingElem) { 1911 //System.out.println("StarRingElem case"); 1912 for (C c : p.val.values()) { 1913 C n = (C) ((StarRingElem) c).norm(); 1914 a = a.sum(n); 1915 } 1916 } else { 1917 for (C c : p.val.values()) { 1918 C n = c.multiply(c); 1919 a = a.sum(n); 1920 } 1921 } 1922 // compute square root if possible 1923 // refactor for sqrt in RingElem ? 1924 if (a instanceof BigRational) { 1925 BigRational b = (BigRational) a; 1926 a = (C) Roots.sqrt(b); 1927 } else if (a instanceof BigComplex) { 1928 BigComplex b = (BigComplex) a; 1929 a = (C) Roots.sqrt(b); 1930 } else if (a instanceof BigInteger) { 1931 BigInteger b = (BigInteger) a; 1932 a = (C) Roots.sqrt(b); 1933 } else if (a instanceof BigDecimal) { 1934 BigDecimal b = (BigDecimal) a; 1935 a = (C) Roots.sqrt(b); 1936 } else if (a instanceof BigDecimalComplex) { 1937 BigDecimalComplex b = (BigDecimalComplex) a; 1938 a = (C) Roots.sqrt(b); 1939 } else { 1940 logger.error("no square root implemented for {}", a.toScriptFactory()); 1941 } 1942 return a; 1943 } 1944 1945 1946 /** 1947 * Polynomial reciprocal transformation. 1948 * @param <C> coefficient type. 1949 * @param A is a non-zero polynomial, with n=DEG(A). 1950 * @return B with B(x) = x**n*A(1/x), where x is the main variable of A. 1951 * @see "maspoly.SACPOL.mi#PRT from SAC2/MAS" 1952 */ 1953 public static <C extends RingElem<C>> GenPolynomial<C> reciprocalTransformation(GenPolynomial<C> A) { 1954 return reciprocalTransformation(A, 0); 1955 } 1956 1957 1958 /** 1959 * Polynomial reciprocal transformation. 1960 * @param <C> coefficient type. 1961 * @param A is a non-zero polynomial, with n=DEG(A,i), A(x_r, ..., x_0). 1962 * @param i variable to be transformed, 0 is the main variable. 1963 * @return B with B(x) = x_i**n*A(1/x_i), where x_i is the i-th variable of 1964 * A. 1965 * @see "maspoly.SACPOL.mi#PRT from SAC2/MAS" 1966 */ 1967 public static <C extends RingElem<C>> GenPolynomial<C> reciprocalTransformation(GenPolynomial<C> A, 1968 int i) { 1969 if (A == null) { 1970 return null; 1971 } 1972 GenPolynomialRing<C> pfac = A.ring; 1973 GenPolynomial<C> B = pfac.getZERO().copy(); 1974 if (A.isZERO()) { 1975 return B; 1976 } 1977 int m = i; 1978 long d = A.degree(m); 1979 //System.out.println("d = " + d + ", m = " + m); 1980 Map<ExpVector, C> val = A.val; 1981 Map<ExpVector, C> valb = B.val; 1982 for (Map.Entry<ExpVector, C> me : val.entrySet()) { 1983 ExpVector e = me.getKey(); 1984 long de = d - e.getVal(m); 1985 ExpVector f = e.subst(m, de); 1986 C c = me.getValue(); 1987 valb.put(f, c); 1988 } 1989 return B; 1990 } 1991 1992 1993 /** 1994 * Polynomial translation, main variable. 1995 * @param <C> coefficient type. 1996 * @param A is a non-zero polynomial in r variables, A(x_1, ..., x(r-1), 1997 * x_r). 1998 * @param h is a coefficient ring element. 1999 * @return B with B(x1, ..., x(r-1), xr) = A(x1, ..., x(r-1), xr+h). 2000 * @see "maspoly.SACIPOL.mi#IPTRAN from SAC2/MAS" 2001 */ 2002 public static <C extends RingElem<C>> GenPolynomial<C> translationMain(GenPolynomial<C> A, C h) { 2003 if (A == null) { 2004 return null; 2005 } 2006 if (A.isZERO() || h.isZERO()) { 2007 return A; 2008 } 2009 GenPolynomialRing<C> pfac = A.ring; 2010 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 2011 GenPolynomial<GenPolynomial<C>> Ar = recursive(rfac, A); 2012 GenPolynomial<GenPolynomial<C>> Br = translationMainRecursive(Ar, h); 2013 GenPolynomial<C> B = distribute(pfac, Br); 2014 return B; 2015 } 2016 2017 2018 /** 2019 * Polynomial translation, main variable. 2020 * @param <C> coefficient type. 2021 * @param A is a non-zero recursive polynomial in r variables, A(x_1, ..., 2022 * x(r-1))(x_r). 2023 * @param h is a coefficient ring element. 2024 * @return B with B(x1, ..., x(r-1))(xr) = A(x1, ..., x(r-1))(xr+h). 2025 * @see "maspoly.SACIPOL.mi#IPTRAN from SAC2/MAS" 2026 */ 2027 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> translationMainRecursive( 2028 GenPolynomial<GenPolynomial<C>> A, C h) { 2029 if (A == null) { 2030 return null; 2031 } 2032 GenPolynomialRing<GenPolynomial<C>> pfac = A.ring; 2033 if (pfac.nvar != 1) { 2034 throw new IllegalArgumentException("translationMainRecursive no univariate polynomial"); 2035 } 2036 if (A.isZERO() || h.isZERO()) { 2037 return A; 2038 } 2039 // assert descending exponents, i.e. compatible term order 2040 Map<ExpVector, GenPolynomial<C>> val = A.val; 2041 GenPolynomial<GenPolynomial<C>> c = null; 2042 ExpVector z = pfac.evzero; 2043 ExpVector x = pfac.evzero.subst(0, 1L); 2044 GenPolynomial<C> H = pfac.getONECoefficient().multiply(h); 2045 long el1 = -1; // undefined 2046 long el2 = -1; 2047 for (Map.Entry<ExpVector, GenPolynomial<C>> me : val.entrySet()) { 2048 ExpVector e = me.getKey(); 2049 el2 = e.getVal(0); 2050 GenPolynomial<C> b = me.getValue(); 2051 if (c == null) { 2052 c = pfac.valueOf(b, z); 2053 } else { 2054 for (long i = el2; i < el1; i++) { // i = 0, el1-el2. 2055 GenPolynomial<GenPolynomial<C>> d1 = c.multiply(x); 2056 GenPolynomial<GenPolynomial<C>> d2 = c.multiply(H); 2057 c = d1.sum(d2); 2058 } 2059 c = c.sum(b); 2060 } 2061 el1 = el2; 2062 } 2063 for (long i = 0; i < el2; i++) { 2064 GenPolynomial<GenPolynomial<C>> d1 = c.multiply(x); 2065 GenPolynomial<GenPolynomial<C>> d2 = c.multiply(H); 2066 c = d1.sum(d2); 2067 } 2068 return c; 2069 } 2070 2071 2072 /** 2073 * Polynomial translation, base univariate. 2074 * @param <C> coefficient type. 2075 * @param A is a non-zero polynomial in 1 variables, A(x_1). 2076 * @param h is a coefficient ring element. 2077 * @return B with B(x1) = A(x1+h1). 2078 * @see "maspoly.SACIPOL.mi#IPTRAN from SAC2/MAS" 2079 */ 2080 public static <C extends RingElem<C>> GenPolynomial<C> translationBase(GenPolynomial<C> A, C h) { 2081 if (A == null) { 2082 return null; 2083 } 2084 GenPolynomialRing<C> pfac = A.ring; 2085 if (pfac.nvar != 1) { 2086 throw new IllegalArgumentException("translationBase no univariate polynomial"); 2087 } 2088 if (A.isZERO()) { 2089 return A; 2090 } 2091 // assert descending exponents, i.e. compatible term order 2092 Map<ExpVector, C> val = A.val; 2093 GenPolynomial<C> c = null; 2094 ExpVector z = pfac.evzero; 2095 ExpVector x = pfac.evzero.subst(0, 1L); 2096 long el1 = -1; // undefined 2097 long el2 = -1; 2098 for (Map.Entry<ExpVector, C> me : val.entrySet()) { 2099 ExpVector e = me.getKey(); 2100 el2 = e.getVal(0); 2101 C b = me.getValue(); 2102 if (c == null) { 2103 c = pfac.valueOf(b, z); 2104 } else { 2105 for (long i = el2; i < el1; i++) { // i = 0, el1-el2. 2106 GenPolynomial<C> d1 = c.multiply(x); 2107 GenPolynomial<C> d2 = c.multiply(h); 2108 c = d1.sum(d2); 2109 } 2110 c = c.sum(b); 2111 } 2112 el1 = el2; 2113 } 2114 for (long i = 0; i < el2; i++) { 2115 GenPolynomial<C> d1 = c.multiply(x); 2116 GenPolynomial<C> d2 = c.multiply(h); 2117 c = d1.sum(d2); 2118 } 2119 return c; 2120 } 2121 2122 2123 /** 2124 * Polynomial translation, all variables. 2125 * @param <C> coefficient type. 2126 * @param A is a non-zero polynomial in r variables, A(x_1, ..., x(r-1), 2127 * x_r). 2128 * @param H is a list of coefficient ring elements H = (h1, ..., hr). 2129 * @return B with B(x1, ..., x(r-1), xr) = A(x1+h1, ..., x(r-1)+h(r-1), 2130 * xr+hr). 2131 * @see "maspoly.SACIPOL.mi#IPTRAN from SAC2/MAS" 2132 */ 2133 public static <C extends RingElem<C>> GenPolynomial<C> translation(GenPolynomial<C> A, List<C> H) { 2134 if (A == null) { 2135 return null; 2136 } 2137 if (A.isZERO()) { 2138 return A; 2139 } 2140 GenPolynomialRing<C> pfac = A.ring; 2141 if (pfac.nvar <= 1) { 2142 return translationBase(A, H.get(0)); 2143 } 2144 if (H == null || pfac.nvar != H.size()) { 2145 throw new IllegalArgumentException( 2146 "number of translation points do not match number of variables " + pfac.nvar 2147 + " != " + H.size()); 2148 } 2149 C h = H.get(0); 2150 List<C> L = H.subList(1, H.size()); 2151 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 2152 GenPolynomial<GenPolynomial<C>> Ar = recursive(rfac, A); 2153 GenPolynomial<GenPolynomial<C>> Br = translationMainRecursive(Ar, h); 2154 GenPolynomial<GenPolynomial<C>> Cr = rfac.getZERO().copy(); 2155 Map<ExpVector, GenPolynomial<C>> val = Br.val; 2156 Map<ExpVector, GenPolynomial<C>> cval = Cr.val; 2157 for (Map.Entry<ExpVector, GenPolynomial<C>> me : val.entrySet()) { 2158 ExpVector e = me.getKey(); 2159 GenPolynomial<C> b = me.getValue(); 2160 GenPolynomial<C> c = translation(b, L); 2161 cval.put(e, c); 2162 } 2163 GenPolynomial<C> B = distribute(pfac, Cr); 2164 return B; 2165 } 2166 2167 2168 /** 2169 * Polynomial translation, r-1 variables. 2170 * @param <C> coefficient type. 2171 * @param A is a non-zero polynomial in r variables, A(x_1, ..., x(r-1), 2172 * x_r). 2173 * @param H is a list of coefficient ring elements H = (h2, ..., hr). 2174 * @return B with B(x1, ..., x(r-1), xr) = A(x1, x2+h2, ..., x(r-1)+h(r-1), 2175 * xr+hr). 2176 * @see "maspoly.SACIPOL.mi#IPTRAN from SAC2/MAS" 2177 */ 2178 public static <C extends RingElem<C>> GenPolynomial<C> translation1(GenPolynomial<C> A, List<C> H) { 2179 if (A == null) { 2180 return null; 2181 } 2182 if (A.isZERO()) { 2183 return A; 2184 } 2185 GenPolynomialRing<C> pfac = A.ring; 2186 if (pfac.nvar <= 1) { 2187 return A; //translationBase(A, H.get(0)); 2188 } 2189 if (H == null || pfac.nvar - 1 != H.size()) { 2190 throw new IllegalArgumentException( 2191 "number of translation points do not match number of variables " + (pfac.nvar - 1) 2192 + " != " + H.size()); 2193 } 2194 C h = H.get(0); 2195 List<C> L = H.subList(1, H.size()); 2196 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 2197 GenPolynomial<GenPolynomial<C>> Ar = recursive(rfac, A); 2198 GenPolynomial<GenPolynomial<C>> Br = translationMainRecursive(Ar, h); 2199 GenPolynomial<GenPolynomial<C>> Cr = rfac.getZERO().copy(); 2200 Map<ExpVector, GenPolynomial<C>> val = Br.val; 2201 Map<ExpVector, GenPolynomial<C>> cval = Cr.val; 2202 for (Map.Entry<ExpVector, GenPolynomial<C>> me : val.entrySet()) { 2203 ExpVector e = me.getKey(); 2204 GenPolynomial<C> b = me.getValue(); 2205 GenPolynomial<C> c = translation1(b, L); 2206 cval.put(e, c); 2207 } 2208 GenPolynomial<C> B = distribute(pfac, Cr); 2209 return B; 2210 } 2211 2212 2213 /** 2214 * Evaluate at main variable. 2215 * @param <C> coefficient type. 2216 * @param cfac coefficient polynomial ring factory. 2217 * @param A recursive polynomial to be evaluated. 2218 * @param a value to evaluate at. 2219 * @return A( x_1, ..., x_{n-1}, a ). 2220 */ 2221 public static <C extends RingElem<C>> GenPolynomial<C> evaluateMainRecursive(GenPolynomialRing<C> cfac, 2222 GenPolynomial<GenPolynomial<C>> A, C a) { 2223 if (A == null || A.isZERO()) { 2224 return cfac.getZERO(); 2225 } 2226 if (A.ring.nvar != 1) { 2227 throw new IllegalArgumentException("evaluateMain no univariate polynomial"); 2228 } 2229 if (a == null || a.isZERO()) { 2230 return A.trailingBaseCoefficient(); 2231 } 2232 // assert descending exponents, i.e. compatible term order 2233 Map<ExpVector, GenPolynomial<C>> val = A.getMap(); 2234 GenPolynomial<C> B = null; 2235 long el1 = -1; // undefined 2236 long el2 = -1; 2237 for (Map.Entry<ExpVector, GenPolynomial<C>> me : val.entrySet()) { 2238 ExpVector e = me.getKey(); 2239 el2 = e.getVal(0); 2240 if (B == null /*el1 < 0*/) { // first turn 2241 B = me.getValue(); 2242 } else { 2243 for (long i = el2; i < el1; i++) { 2244 B = B.multiply(a); 2245 } 2246 B = B.sum(me.getValue()); 2247 } 2248 el1 = el2; 2249 } 2250 for (long i = 0; i < el2; i++) { 2251 B = B.multiply(a); 2252 } 2253 return B; 2254 } 2255 2256 2257 /** 2258 * Evaluate at main variable. 2259 * @param <C> coefficient type. 2260 * @param cfac coefficient polynomial ring factory. 2261 * @param A distributed polynomial to be evaluated. 2262 * @param a value to evaluate at. 2263 * @return A( x_1, ..., x_{n-1}, a ). 2264 */ 2265 public static <C extends RingElem<C>> GenPolynomial<C> evaluateMain(GenPolynomialRing<C> cfac, 2266 GenPolynomial<C> A, C a) { 2267 if (A == null || A.isZERO()) { 2268 return cfac.getZERO(); 2269 } 2270 GenPolynomialRing<GenPolynomial<C>> rfac = A.ring.recursive(1); 2271 if (rfac.nvar + cfac.nvar != A.ring.nvar) { 2272 throw new IllegalArgumentException("evaluateMain number of variables mismatch"); 2273 } 2274 GenPolynomial<GenPolynomial<C>> Ap = recursive(rfac, A); 2275 return PolyUtil.<C> evaluateMainRecursive(cfac, Ap, a); 2276 } 2277 2278 2279 /** 2280 * Evaluate at main variable. 2281 * @param <C> coefficient type. 2282 * @param cfac coefficient ring factory. 2283 * @param L list of univariate polynomials to be evaluated. 2284 * @param a value to evaluate at. 2285 * @return list( A( x_1, ..., x_{n-1}, a ) ) for A in L. 2286 */ 2287 public static <C extends RingElem<C>> List<GenPolynomial<C>> evaluateMain(GenPolynomialRing<C> cfac, 2288 List<GenPolynomial<C>> L, C a) { 2289 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(L, new EvalMainPol<C>(cfac, a)); 2290 } 2291 2292 2293 /** 2294 * Evaluate at main variable. 2295 * @param <C> coefficient type. 2296 * @param cfac coefficient ring factory. 2297 * @param A univariate polynomial to be evaluated. 2298 * @param a value to evaluate at. 2299 * @return A( a ). 2300 */ 2301 public static <C extends RingElem<C>> C evaluateMain(RingFactory<C> cfac, GenPolynomial<C> A, C a) { 2302 if (A == null || A.isZERO()) { 2303 return cfac.getZERO(); 2304 } 2305 if (A.ring.nvar != 1) { 2306 throw new IllegalArgumentException("evaluateMain no univariate polynomial"); 2307 } 2308 if (a == null || a.isZERO()) { 2309 return A.trailingBaseCoefficient(); 2310 } 2311 // assert decreasing exponents, i.e. compatible term order 2312 Map<ExpVector, C> val = A.getMap(); 2313 C B = null; 2314 long el1 = -1; // undefined 2315 long el2 = -1; 2316 for (Map.Entry<ExpVector, C> me : val.entrySet()) { 2317 ExpVector e = me.getKey(); 2318 el2 = e.getVal(0); 2319 if (B == null /*el1 < 0*/) { // first turn 2320 B = me.getValue(); 2321 } else { 2322 for (long i = el2; i < el1; i++) { 2323 B = B.multiply(a); 2324 } 2325 B = B.sum(me.getValue()); 2326 } 2327 el1 = el2; 2328 } 2329 for (long i = 0; i < el2; i++) { 2330 B = B.multiply(a); 2331 } 2332 return B; 2333 } 2334 2335 2336 /** 2337 * Evaluate at main variable. 2338 * @param <C> coefficient type. 2339 * @param cfac coefficient ring factory. 2340 * @param L list of univariate polynomial to be evaluated. 2341 * @param a value to evaluate at. 2342 * @return list( A( a ) ) for A in L. 2343 */ 2344 public static <C extends RingElem<C>> List<C> evaluateMain(RingFactory<C> cfac, List<GenPolynomial<C>> L, 2345 C a) { 2346 return ListUtil.<GenPolynomial<C>, C> map(L, new EvalMain<C>(cfac, a)); 2347 } 2348 2349 2350 /** 2351 * Evaluate at k-th variable. 2352 * @param <C> coefficient type. 2353 * @param cfac coefficient polynomial ring in k variables C[x_1, ..., x_k] 2354 * factory. 2355 * @param rfac coefficient polynomial ring C[x_1, ..., x_{k-1}] [x_k] 2356 * factory, a recursive polynomial ring in 1 variable with 2357 * coefficients in k-1 variables. 2358 * @param nfac polynomial ring in n-1 variables C[x_1, ..., x_{k-1}] 2359 * [x_{k+1}, ..., x_n] factory, a recursive polynomial ring in 2360 * n-k+1 variables with coefficients in k-1 variables. 2361 * @param dfac polynomial ring in n-1 variables. C[x_1, ..., x_{k-1}, 2362 * x_{k+1}, ..., x_n] factory. 2363 * @param A polynomial to be evaluated. 2364 * @param a value to evaluate at. 2365 * @return A( x_1, ..., x_{k-1}, a, x_{k+1}, ..., x_n). 2366 */ 2367 public static <C extends RingElem<C>> GenPolynomial<C> evaluate(GenPolynomialRing<C> cfac, 2368 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomialRing<GenPolynomial<C>> nfac, 2369 GenPolynomialRing<C> dfac, GenPolynomial<C> A, C a) { 2370 if (rfac.nvar != 1) { 2371 throw new IllegalArgumentException("evaluate coefficient ring not univariate"); 2372 } 2373 if (A == null || A.isZERO()) { 2374 return cfac.getZERO(); 2375 } 2376 Map<ExpVector, GenPolynomial<C>> Ap = A.contract(cfac); 2377 GenPolynomialRing<C> rcf = (GenPolynomialRing<C>) rfac.coFac; 2378 GenPolynomial<GenPolynomial<C>> Ev = nfac.getZERO().copy(); 2379 Map<ExpVector, GenPolynomial<C>> Evm = Ev.val; //getMap(); 2380 for (Map.Entry<ExpVector, GenPolynomial<C>> m : Ap.entrySet()) { 2381 ExpVector e = m.getKey(); 2382 GenPolynomial<C> b = m.getValue(); 2383 GenPolynomial<GenPolynomial<C>> c = recursive(rfac, b); 2384 GenPolynomial<C> d = evaluateMainRecursive(rcf, c, a); 2385 if (d != null && !d.isZERO()) { 2386 Evm.put(e, d); 2387 } 2388 } 2389 GenPolynomial<C> B = distribute(dfac, Ev); 2390 return B; 2391 } 2392 2393 2394 /** 2395 * Evaluate at first (lowest) variable. 2396 * @param <C> coefficient type. 2397 * @param cfac coefficient polynomial ring in first variable C[x_1] factory. 2398 * @param dfac polynomial ring in n-1 variables. C[x_2, ..., x_n] factory. 2399 * @param A polynomial to be evaluated. 2400 * @param a value to evaluate at. 2401 * @return A( a, x_2, ..., x_n). 2402 */ 2403 public static <C extends RingElem<C>> GenPolynomial<C> evaluateFirst(GenPolynomialRing<C> cfac, 2404 GenPolynomialRing<C> dfac, GenPolynomial<C> A, C a) { 2405 if (A == null || A.isZERO()) { 2406 return dfac.getZERO(); 2407 } 2408 Map<ExpVector, GenPolynomial<C>> Ap = A.contract(cfac); 2409 //RingFactory<C> rcf = cfac.coFac; // == dfac.coFac 2410 2411 GenPolynomial<C> B = dfac.getZERO().copy(); 2412 Map<ExpVector, C> Bm = B.val; //getMap(); 2413 2414 for (Map.Entry<ExpVector, GenPolynomial<C>> m : Ap.entrySet()) { 2415 ExpVector e = m.getKey(); 2416 GenPolynomial<C> b = m.getValue(); 2417 C d = evaluateMain(cfac.coFac, b, a); 2418 if (d != null && !d.isZERO()) { 2419 Bm.put(e, d); 2420 } 2421 } 2422 return B; 2423 } 2424 2425 2426 /** 2427 * Evaluate at first (lowest) variable. Could also be called 2428 * <code>evaluateFirst()</code>, but type erasure of parameter 2429 * <code>A</code> does not allow the same name. 2430 * @param <C> coefficient type. 2431 * @param cfac coefficient polynomial ring in first variable C[x_1] factory. 2432 * @param dfac polynomial ring in n-1 variables. C[x_2, ..., x_n] factory. 2433 * @param A recursive polynomial to be evaluated. 2434 * @param a value to evaluate at. 2435 * @return A( a, x_2, ..., x_n). 2436 */ 2437 public static <C extends RingElem<C>> GenPolynomial<C> evaluateFirstRec(GenPolynomialRing<C> cfac, 2438 GenPolynomialRing<C> dfac, GenPolynomial<GenPolynomial<C>> A, C a) { 2439 if (A == null || A.isZERO()) { 2440 return dfac.getZERO(); 2441 } 2442 Map<ExpVector, GenPolynomial<C>> Ap = A.getMap(); 2443 GenPolynomial<C> B = dfac.getZERO().copy(); 2444 Map<ExpVector, C> Bm = B.val; //getMap(); 2445 for (Map.Entry<ExpVector, GenPolynomial<C>> m : Ap.entrySet()) { 2446 ExpVector e = m.getKey(); 2447 GenPolynomial<C> b = m.getValue(); 2448 C d = evaluateMain(cfac.coFac, b, a); 2449 if (d != null && !d.isZERO()) { 2450 Bm.put(e, d); 2451 } 2452 } 2453 return B; 2454 } 2455 2456 2457 /** 2458 * Evaluate all variables. 2459 * @param <C> coefficient type. 2460 * @param cfac coefficient ring factory. 2461 * @param L list of polynomials to be evaluated. 2462 * @param a = (a_1, a_2, ..., a_n) a tuple of values to evaluate at. 2463 * @return L = ( A_1(a_1, a_2, ..., a_n), ... A_k(a_1, a_2, ..., a_n)). 2464 */ 2465 public static <C extends RingElem<C>> List<C> evaluateAll(RingFactory<C> cfac, List<GenPolynomial<C>> L, 2466 List<C> a) { 2467 return ListUtil.<GenPolynomial<C>, C> map(L, new EvalAllPol<C>(cfac, a)); 2468 } 2469 2470 2471 /** 2472 * Evaluate all variables. 2473 * @param <C> coefficient type. 2474 * @param cfac coefficient ring factory. 2475 * @param A polynomial to be evaluated. 2476 * @param a = (a_1, a_2, ..., a_n) a tuple of values to evaluate at. 2477 * @return A(a_1, a_2, ..., a_n). 2478 */ 2479 public static <C extends RingElem<C>> C evaluateAll(RingFactory<C> cfac, GenPolynomial<C> A, List<C> a) { 2480 if (A == null || A.isZERO()) { 2481 return cfac.getZERO(); 2482 } 2483 GenPolynomialRing<C> dfac = A.ring; 2484 if (a == null || a.size() != dfac.nvar) { 2485 throw new IllegalArgumentException("evaluate tuple size not equal to number of variables"); 2486 } 2487 if (dfac.nvar == 0) { 2488 return A.trailingBaseCoefficient(); 2489 } 2490 if (dfac.nvar == 1) { 2491 return evaluateMain(cfac, A, a.get(0)); 2492 } 2493 C b = cfac.getZERO(); 2494 GenPolynomial<C> Ap = A; 2495 for (int k = 0; k < dfac.nvar - 1; k++) { 2496 C ap = a.get(k); 2497 GenPolynomialRing<C> c1fac = new GenPolynomialRing<C>(cfac, 1); // no vars 2498 GenPolynomialRing<C> cnfac = new GenPolynomialRing<C>(cfac, dfac.nvar - 1 - k); // no vars 2499 GenPolynomial<C> Bp = evaluateFirst(c1fac, cnfac, Ap, ap); 2500 if (Bp.isZERO()) { 2501 return b; 2502 } 2503 Ap = Bp; 2504 //System.out.println("Ap = " + Ap); 2505 } 2506 C ap = a.get(dfac.nvar - 1); 2507 b = evaluateMain(cfac, Ap, ap); 2508 return b; 2509 } 2510 2511 2512 /** 2513 * Substitute main variable. 2514 * @param A univariate polynomial. 2515 * @param s polynomial for substitution. 2516 * @return polynomial A(x <- s). 2517 */ 2518 public static <C extends RingElem<C>> GenPolynomial<C> substituteMain(GenPolynomial<C> A, 2519 GenPolynomial<C> s) { 2520 return substituteUnivariate(A, s); 2521 } 2522 2523 2524 /** 2525 * Substitute univariate polynomial. 2526 * @param f univariate polynomial. 2527 * @param t polynomial for substitution. 2528 * @return polynomial f(x <- t). 2529 */ 2530 public static <C extends RingElem<C>> GenPolynomial<C> substituteUnivariate(GenPolynomial<C> f, 2531 GenPolynomial<C> t) { 2532 if (f == null || t == null) { 2533 return null; 2534 } 2535 GenPolynomialRing<C> fac = f.ring; 2536 if (fac.nvar > 1) { 2537 throw new IllegalArgumentException("only for univariate polynomial f"); 2538 } 2539 if (f.isZERO() || f.isConstant()) { 2540 return f; 2541 } 2542 if (t.ring.nvar > 1) { 2543 fac = t.ring; 2544 } 2545 // assert descending exponents, i.e. compatible term order 2546 Map<ExpVector, C> val = f.getMap(); 2547 GenPolynomial<C> s = null; 2548 long el1 = -1; // undefined 2549 long el2 = -1; 2550 for (Map.Entry<ExpVector, C> me : val.entrySet()) { 2551 ExpVector e = me.getKey(); 2552 el2 = e.getVal(0); 2553 if (s == null /*el1 < 0*/) { // first turn 2554 s = fac.getZERO().sum(me.getValue()); 2555 } else { 2556 for (long i = el2; i < el1; i++) { 2557 s = s.multiply(t); 2558 } 2559 s = s.sum(me.getValue()); 2560 } 2561 el1 = el2; 2562 } 2563 for (long i = 0; i < el2; i++) { 2564 s = s.multiply(t); 2565 } 2566 //System.out.println("s = " + s); 2567 return s; 2568 } 2569 2570 2571 /** 2572 * Substitute univariate polynomial with multivariate coefficients. 2573 * @param f univariate polynomial with multivariate coefficients. 2574 * @param t polynomial for substitution. 2575 * @return polynomial f(x <- t). 2576 */ 2577 public static <C extends RingElem<C>> GenPolynomial<C> substituteUnivariateMult(GenPolynomial<C> f, 2578 GenPolynomial<C> t) { 2579 if (f == null || t == null) { 2580 return null; 2581 } 2582 GenPolynomialRing<C> fac = f.ring; 2583 if (fac.nvar == 1) { 2584 return substituteUnivariate(f, t); 2585 } 2586 GenPolynomialRing<GenPolynomial<C>> rfac = fac.recursive(1); 2587 GenPolynomial<GenPolynomial<C>> fr = PolyUtil.<C> recursive(rfac, f); 2588 GenPolynomial<GenPolynomial<C>> tr = PolyUtil.<C> recursive(rfac, t); 2589 //System.out.println("fr = " + fr); 2590 //System.out.println("tr = " + tr); 2591 GenPolynomial<GenPolynomial<C>> sr = PolyUtil.<GenPolynomial<C>> substituteUnivariate(fr, tr); 2592 //System.out.println("sr = " + sr); 2593 GenPolynomial<C> s = PolyUtil.<C> distribute(fac, sr); 2594 return s; 2595 } 2596 2597 2598 /** 2599 * Taylor series for polynomial. 2600 * @param f univariate polynomial. 2601 * @param a expansion point. 2602 * @return Taylor series (a polynomial) of f at a. 2603 */ 2604 public static <C extends RingElem<C>> GenPolynomial<C> seriesOfTaylor(GenPolynomial<C> f, C a) { 2605 if (f == null) { 2606 return null; 2607 } 2608 GenPolynomialRing<C> fac = f.ring; 2609 if (fac.nvar > 1) { 2610 throw new IllegalArgumentException("only for univariate polynomials"); 2611 } 2612 if (f.isZERO() || f.isConstant()) { 2613 return f; 2614 } 2615 GenPolynomial<C> s = fac.getZERO(); 2616 C fa = PolyUtil.<C> evaluateMain(fac.coFac, f, a); 2617 s = s.sum(fa); 2618 long n = 1; 2619 long i = 0; 2620 GenPolynomial<C> g = PolyUtil.<C> baseDerivative(f); 2621 //GenPolynomial<C> p = fac.getONE(); 2622 while (!g.isZERO()) { 2623 i++; 2624 n *= i; 2625 fa = PolyUtil.<C> evaluateMain(fac.coFac, g, a); 2626 GenPolynomial<C> q = fac.univariate(0, i); //p; 2627 q = q.multiply(fa); 2628 q = q.divide(fac.fromInteger(n)); 2629 s = s.sum(q); 2630 g = PolyUtil.<C> baseDerivative(g); 2631 } 2632 //System.out.println("s = " + s); 2633 return s; 2634 } 2635 2636 2637 /** 2638 * ModInteger interpolate on first variable. 2639 * @param <C> coefficient type. 2640 * @param fac GenPolynomial<C> result factory. 2641 * @param A GenPolynomial. 2642 * @param M GenPolynomial interpolation modul of A. 2643 * @param mi inverse of M(am) in ring fac.coFac. 2644 * @param B evaluation of other GenPolynomial. 2645 * @param am evaluation point (interpolation modul) of B, i.e. P(am) = B. 2646 * @return S, with S mod M == A and S(am) == B. 2647 */ 2648 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> interpolate( 2649 GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<GenPolynomial<C>> A, 2650 GenPolynomial<C> M, C mi, GenPolynomial<C> B, C am) { 2651 GenPolynomial<GenPolynomial<C>> S = fac.getZERO().copy(); 2652 GenPolynomial<GenPolynomial<C>> Ap = A.copy(); 2653 SortedMap<ExpVector, GenPolynomial<C>> av = Ap.val; //getMap(); 2654 SortedMap<ExpVector, C> bv = B.getMap(); 2655 SortedMap<ExpVector, GenPolynomial<C>> sv = S.val; //getMap(); 2656 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) fac.coFac; 2657 RingFactory<C> bfac = cfac.coFac; 2658 GenPolynomial<C> c = null; 2659 for (Map.Entry<ExpVector, C> me : bv.entrySet()) { 2660 ExpVector e = me.getKey(); 2661 C y = me.getValue(); //bv.get(e); // assert y != null 2662 GenPolynomial<C> x = av.get(e); 2663 if (x != null) { 2664 av.remove(e); 2665 c = PolyUtil.<C> interpolate(cfac, x, M, mi, y, am); 2666 if (!c.isZERO()) { // 0 cannot happen 2667 sv.put(e, c); 2668 } 2669 } else { 2670 c = PolyUtil.<C> interpolate(cfac, cfac.getZERO(), M, mi, y, am); 2671 if (!c.isZERO()) { // 0 cannot happen 2672 sv.put(e, c); // c != null 2673 } 2674 } 2675 } 2676 // assert bv is empty = done 2677 for (Map.Entry<ExpVector, GenPolynomial<C>> me : av.entrySet()) { // rest of av 2678 ExpVector e = me.getKey(); 2679 GenPolynomial<C> x = me.getValue(); //av.get(e); // assert x != null 2680 c = PolyUtil.<C> interpolate(cfac, x, M, mi, bfac.getZERO(), am); 2681 if (!c.isZERO()) { // 0 cannot happen 2682 sv.put(e, c); // c != null 2683 } 2684 } 2685 return S; 2686 } 2687 2688 2689 /** 2690 * Univariate polynomial interpolation. 2691 * @param <C> coefficient type. 2692 * @param fac GenPolynomial<C> result factory. 2693 * @param A GenPolynomial. 2694 * @param M GenPolynomial interpolation modul of A. 2695 * @param mi inverse of M(am) in ring fac.coFac. 2696 * @param a evaluation of other GenPolynomial. 2697 * @param am evaluation point (interpolation modul) of a, i.e. P(am) = a. 2698 * @return S, with S mod M == A and S(am) == a. 2699 */ 2700 public static <C extends RingElem<C>> GenPolynomial<C> interpolate(GenPolynomialRing<C> fac, 2701 GenPolynomial<C> A, GenPolynomial<C> M, C mi, C a, C am) { 2702 GenPolynomial<C> s; 2703 C b = PolyUtil.<C> evaluateMain(fac.coFac, A, am); 2704 // A mod a.modul 2705 C d = a.subtract(b); // a-A mod a.modul 2706 if (d.isZERO()) { 2707 return A; 2708 } 2709 b = d.multiply(mi); // b = (a-A)*mi mod a.modul 2710 // (M*b)+A mod M = A mod M = 2711 // (M*mi*(a-A)+A) mod a.modul = a mod a.modul 2712 s = M.multiply(b); 2713 s = s.sum(A); 2714 return s; 2715 } 2716 2717 2718 /** 2719 * Recursive GenPolynomial switch variable blocks. 2720 * @param <C> coefficient type. 2721 * @param P recursive GenPolynomial in R[X,Y]. 2722 * @return this in R[Y,X]. 2723 */ 2724 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> switchVariables( 2725 GenPolynomial<GenPolynomial<C>> P) { 2726 if (P == null) { 2727 throw new IllegalArgumentException("P == null"); 2728 } 2729 GenPolynomialRing<GenPolynomial<C>> rfac1 = P.ring; 2730 GenPolynomialRing<C> cfac1 = (GenPolynomialRing<C>) rfac1.coFac; 2731 GenPolynomialRing<C> cfac2 = new GenPolynomialRing<C>(cfac1.coFac, rfac1); 2732 GenPolynomial<C> zero = cfac2.getZERO(); 2733 GenPolynomialRing<GenPolynomial<C>> rfac2 = new GenPolynomialRing<GenPolynomial<C>>(cfac2, cfac1); 2734 GenPolynomial<GenPolynomial<C>> B = rfac2.getZERO().copy(); 2735 if (P.isZERO()) { 2736 return B; 2737 } 2738 for (Monomial<GenPolynomial<C>> mr : P) { 2739 GenPolynomial<C> cr = mr.c; 2740 for (Monomial<C> mc : cr) { 2741 GenPolynomial<C> c = zero.sum(mc.c, mr.e); 2742 B = B.sum(c, mc.e); 2743 } 2744 } 2745 return B; 2746 } 2747 2748 2749 /** 2750 * Maximal degree of leading terms of a polynomial list. 2751 * @return maximum degree of the leading terms of a polynomial list. 2752 */ 2753 public static <C extends RingElem<C>> long totalDegreeLeadingTerm(List<GenPolynomial<C>> P) { 2754 long degree = 0; 2755 for (GenPolynomial<C> g : P) { 2756 long total = g.leadingExpVector().totalDeg(); 2757 if (degree < total) { 2758 degree = total; 2759 } 2760 } 2761 return degree; 2762 } 2763 2764 2765 /** 2766 * Total degree of polynomial list. 2767 * @return total degree of the polynomial list. 2768 */ 2769 public static <C extends RingElem<C>> long totalDegree(List<GenPolynomial<C>> P) { 2770 long degree = 0; 2771 for (GenPolynomial<C> g : P) { 2772 long total = g.totalDegree(); 2773 if (degree < total) { 2774 degree = total; 2775 } 2776 } 2777 return degree; 2778 } 2779 2780 2781 /** 2782 * Maximal degree of polynomial list. 2783 * @return maximal degree of the polynomial list. 2784 */ 2785 public static <C extends RingElem<C>> long maxDegree(List<GenPolynomial<C>> P) { 2786 long degree = 0; 2787 for (GenPolynomial<C> g : P) { 2788 long total = g.degree(); 2789 if (degree < total) { 2790 degree = total; 2791 } 2792 } 2793 return degree; 2794 } 2795 2796 2797 /** 2798 * Maximal degree in the coefficient polynomials. 2799 * @param <C> coefficient type. 2800 * @return maximal degree in the coefficients. 2801 */ 2802 public static <C extends RingElem<C>> long coeffMaxDegree(GenPolynomial<GenPolynomial<C>> A) { 2803 if (A.isZERO()) { 2804 return 0; // 0 or -1 ?; 2805 } 2806 long deg = 0; 2807 for (GenPolynomial<C> a : A.getMap().values()) { 2808 long d = a.degree(); 2809 if (d > deg) { 2810 deg = d; 2811 } 2812 } 2813 return deg; 2814 } 2815 2816 2817 /** 2818 * Map a unary function to the coefficients. 2819 * @param ring result polynomial ring factory. 2820 * @param p polynomial. 2821 * @param f evaluation functor. 2822 * @return new polynomial with coefficients f(p(e)). 2823 */ 2824 public static <C extends RingElem<C>, D extends RingElem<D>> GenPolynomial<D> map( 2825 GenPolynomialRing<D> ring, GenPolynomial<C> p, UnaryFunctor<C, D> f) { 2826 GenPolynomial<D> n = ring.getZERO().copy(); 2827 SortedMap<ExpVector, D> nv = n.val; 2828 for (Monomial<C> m : p) { 2829 D c = f.eval(m.c); 2830 if (c != null && !c.isZERO()) { 2831 nv.put(m.e, c); 2832 } 2833 } 2834 return n; 2835 } 2836 2837 2838 /** 2839 * Product representation. 2840 * @param <C> coefficient type. 2841 * @param pfac polynomial ring factory. 2842 * @param L list of polynomials to be represented. 2843 * @return Product representation of L in the polynomial ring pfac. 2844 */ 2845 public static <C extends GcdRingElem<C>> List<GenPolynomial<Product<C>>> toProductGen( 2846 GenPolynomialRing<Product<C>> pfac, List<GenPolynomial<C>> L) { 2847 2848 List<GenPolynomial<Product<C>>> list = new ArrayList<GenPolynomial<Product<C>>>(); 2849 if (L == null || L.size() == 0) { 2850 return list; 2851 } 2852 for (GenPolynomial<C> a : L) { 2853 GenPolynomial<Product<C>> b = toProductGen(pfac, a); 2854 list.add(b); 2855 } 2856 return list; 2857 } 2858 2859 2860 /** 2861 * Product representation. 2862 * @param <C> coefficient type. 2863 * @param pfac polynomial ring factory. 2864 * @param A polynomial to be represented. 2865 * @return Product representation of A in the polynomial ring pfac. 2866 */ 2867 public static <C extends GcdRingElem<C>> GenPolynomial<Product<C>> toProductGen( 2868 GenPolynomialRing<Product<C>> pfac, GenPolynomial<C> A) { 2869 2870 GenPolynomial<Product<C>> P = pfac.getZERO().copy(); 2871 if (A == null || A.isZERO()) { 2872 return P; 2873 } 2874 RingFactory<Product<C>> rpfac = pfac.coFac; 2875 ProductRing<C> rfac = (ProductRing<C>) rpfac; 2876 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 2877 ExpVector e = y.getKey(); 2878 C a = y.getValue(); 2879 Product<C> p = toProductGen(rfac, a); 2880 if (!p.isZERO()) { 2881 P.doPutToMap(e, p); 2882 } 2883 } 2884 return P; 2885 } 2886 2887 2888 /** 2889 * Product representation. 2890 * @param <C> coefficient type. 2891 * @param pfac product ring factory. 2892 * @param c coefficient to be represented. 2893 * @return Product representation of c in the ring pfac. 2894 */ 2895 public static <C extends GcdRingElem<C>> Product<C> toProductGen(ProductRing<C> pfac, C c) { 2896 2897 SortedMap<Integer, C> elem = new TreeMap<Integer, C>(); 2898 for (int i = 0; i < pfac.length(); i++) { 2899 RingFactory<C> rfac = pfac.getFactory(i); 2900 C u = rfac.copy(c); 2901 if (u != null && !u.isZERO()) { 2902 elem.put(i, u); 2903 } 2904 } 2905 return new Product<C>(pfac, elem); 2906 } 2907 2908 2909 /** 2910 * Product representation. 2911 * @param <C> coefficient type. 2912 * @param pfac product polynomial ring factory. 2913 * @param c coefficient to be used. 2914 * @param e exponent vector. 2915 * @return Product representation of c X^e in the ring pfac. 2916 */ 2917 public static <C extends RingElem<C>> Product<GenPolynomial<C>> toProduct( 2918 ProductRing<GenPolynomial<C>> pfac, C c, ExpVector e) { 2919 SortedMap<Integer, GenPolynomial<C>> elem = new TreeMap<Integer, GenPolynomial<C>>(); 2920 for (int i = 0; i < e.length(); i++) { 2921 RingFactory<GenPolynomial<C>> rfac = pfac.getFactory(i); 2922 GenPolynomialRing<C> fac = (GenPolynomialRing<C>) rfac; 2923 //GenPolynomialRing<C> cfac = fac.ring; 2924 long a = e.getVal(i); 2925 GenPolynomial<C> u; 2926 if (a == 0) { 2927 u = fac.getONE(); 2928 } else { 2929 u = fac.univariate(0, a); 2930 } 2931 u = u.multiply(c); 2932 elem.put(i, u); 2933 } 2934 return new Product<GenPolynomial<C>>(pfac, elem); 2935 } 2936 2937 2938 /** 2939 * Product representation. 2940 * @param <C> coefficient type. 2941 * @param pfac product polynomial ring factory. 2942 * @param A polynomial. 2943 * @return Product representation of the terms of A in the ring pfac. 2944 */ 2945 public static <C extends RingElem<C>> Product<GenPolynomial<C>> toProduct( 2946 ProductRing<GenPolynomial<C>> pfac, GenPolynomial<C> A) { 2947 Product<GenPolynomial<C>> P = pfac.getZERO(); 2948 if (A == null || A.isZERO()) { 2949 return P; 2950 } 2951 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 2952 ExpVector e = y.getKey(); 2953 C a = y.getValue(); 2954 Product<GenPolynomial<C>> p = toProduct(pfac, a, e); 2955 P = P.sum(p); 2956 } 2957 return P; 2958 } 2959 2960 2961 /** 2962 * Product representation. 2963 * @param pfac product ring factory. 2964 * @param c coefficient to be represented. 2965 * @return Product representation of c in the ring pfac. 2966 */ 2967 public static Product<ModInteger> toProduct(ProductRing<ModInteger> pfac, BigInteger c) { 2968 2969 SortedMap<Integer, ModInteger> elem = new TreeMap<Integer, ModInteger>(); 2970 for (int i = 0; i < pfac.length(); i++) { 2971 RingFactory<ModInteger> rfac = pfac.getFactory(i); 2972 ModIntegerRing fac = (ModIntegerRing) rfac; 2973 ModInteger u = fac.fromInteger(c.getVal()); 2974 if (!u.isZERO()) { 2975 elem.put(i, u); 2976 } 2977 } 2978 return new Product<ModInteger>(pfac, elem); 2979 } 2980 2981 2982 /** 2983 * Product representation. 2984 * @param pfac polynomial ring factory. 2985 * @param A polynomial to be represented. 2986 * @return Product representation of A in the polynomial ring pfac. 2987 */ 2988 public static GenPolynomial<Product<ModInteger>> toProduct(GenPolynomialRing<Product<ModInteger>> pfac, 2989 GenPolynomial<BigInteger> A) { 2990 2991 GenPolynomial<Product<ModInteger>> P = pfac.getZERO().copy(); 2992 if (A == null || A.isZERO()) { 2993 return P; 2994 } 2995 RingFactory<Product<ModInteger>> rpfac = pfac.coFac; 2996 ProductRing<ModInteger> fac = (ProductRing<ModInteger>) rpfac; 2997 for (Map.Entry<ExpVector, BigInteger> y : A.getMap().entrySet()) { 2998 ExpVector e = y.getKey(); 2999 BigInteger a = y.getValue(); 3000 Product<ModInteger> p = toProduct(fac, a); 3001 if (!p.isZERO()) { 3002 P.doPutToMap(e, p); 3003 } 3004 } 3005 return P; 3006 } 3007 3008 3009 /** 3010 * Product representation. 3011 * @param pfac polynomial ring factory. 3012 * @param L list of polynomials to be represented. 3013 * @return Product representation of L in the polynomial ring pfac. 3014 */ 3015 public static List<GenPolynomial<Product<ModInteger>>> toProduct( 3016 GenPolynomialRing<Product<ModInteger>> pfac, List<GenPolynomial<BigInteger>> L) { 3017 3018 List<GenPolynomial<Product<ModInteger>>> list = new ArrayList<GenPolynomial<Product<ModInteger>>>(); 3019 if (L == null || L.size() == 0) { 3020 return list; 3021 } 3022 for (GenPolynomial<BigInteger> a : L) { 3023 GenPolynomial<Product<ModInteger>> b = toProduct(pfac, a); 3024 list.add(b); 3025 } 3026 return list; 3027 } 3028 3029 3030 /** 3031 * Intersection. Intersection of a list of polynomials with a polynomial 3032 * ring. The polynomial ring must be a contraction of the polynomial ring of 3033 * the list of polynomials and the TermOrder must be an elimination order. 3034 * @param R polynomial ring 3035 * @param F list of polynomials 3036 * @return R \cap F 3037 */ 3038 public static <C extends RingElem<C>> List<GenPolynomial<C>> intersect(GenPolynomialRing<C> R, 3039 List<GenPolynomial<C>> F) { 3040 if (F == null || F.isEmpty()) { 3041 return F; 3042 } 3043 GenPolynomialRing<C> pfac = F.get(0).ring; 3044 int d = pfac.nvar - R.nvar; 3045 if (d <= 0) { 3046 return F; 3047 } 3048 List<GenPolynomial<C>> H = new ArrayList<GenPolynomial<C>>(F.size()); 3049 for (GenPolynomial<C> p : F) { 3050 Map<ExpVector, GenPolynomial<C>> m = null; 3051 m = p.contract(R); 3052 logger.debug("intersect contract m = {}", m); 3053 if (m.size() == 1) { // contains one power of variables 3054 for (Map.Entry<ExpVector, GenPolynomial<C>> me : m.entrySet()) { 3055 ExpVector e = me.getKey(); 3056 if (e.isZERO()) { 3057 H.add(me.getValue()); 3058 } 3059 } 3060 } 3061 } 3062 GenPolynomialRing<C> tfac = pfac.contract(d); 3063 if (tfac.equals(R)) { // check 3064 return H; 3065 } 3066 logger.warn("tfac != R: tfac = {}, R = {}, pdac = {}", tfac.toScript(), R.toScript(), 3067 pfac.toScript()); 3068 // throw new RuntimeException("contract(pfac) != R"); 3069 return H; 3070 } 3071 3072 3073 /** 3074 * Intersection. Intersection of a list of solvable polynomials with a 3075 * solvable polynomial ring. The solvable polynomial ring must be a 3076 * contraction of the solvable polynomial ring of the list of polynomials 3077 * and the TermOrder must be an elimination order. 3078 * @param R solvable polynomial ring 3079 * @param F list of solvable polynomials 3080 * @return R \cap F 3081 */ 3082 @SuppressWarnings("cast") 3083 public static <C extends RingElem<C>> List<GenSolvablePolynomial<C>> intersect( 3084 GenSolvablePolynomialRing<C> R, List<GenSolvablePolynomial<C>> F) { 3085 List<GenPolynomial<C>> Fp = PolynomialList.<C> castToList(F); 3086 GenPolynomialRing<C> Rp = (GenPolynomialRing<C>) R; 3087 List<GenPolynomial<C>> H = intersect(Rp, Fp); 3088 return PolynomialList.<C> castToSolvableList(H); 3089 } 3090 3091 3092 /** 3093 * Intersection. Intersection of a list of word polynomials with a word 3094 * polynomial ring. The polynomial ring must be a contraction of the 3095 * polynomial ring of the list of polynomials, 3096 * @param R word polynomial ring 3097 * @param F list of word polynomials 3098 * @return R \cap F 3099 */ 3100 public static <C extends RingElem<C>> List<GenWordPolynomial<C>> intersect(GenWordPolynomialRing<C> R, 3101 List<GenWordPolynomial<C>> F) { 3102 if (F == null || F.isEmpty()) { 3103 return F; 3104 } 3105 GenWordPolynomialRing<C> pfac = F.get(0).ring; 3106 assert pfac.alphabet.isSubFactory(R.alphabet) : "pfac=" + pfac.alphabet + ", R=" + R.alphabet; 3107 List<GenWordPolynomial<C>> H = new ArrayList<GenWordPolynomial<C>>(F.size()); 3108 for (GenWordPolynomial<C> p : F) { 3109 if (p == null || p.isZERO()) { 3110 continue; 3111 } 3112 GenWordPolynomial<C> m = p.contract(R); 3113 logger.debug("intersect contract m = {}", m); 3114 if (!m.isZERO()) { 3115 H.add(m); 3116 } 3117 } 3118 // throw new RuntimeException("contract(pfac) != R"); 3119 return H; 3120 } 3121 3122 3123 /** 3124 * Remove all upper variables which do not occur in polynomial. 3125 * @param p polynomial. 3126 * @return polynomial with removed variables 3127 */ 3128 public static <C extends RingElem<C>> GenPolynomial<C> removeUnusedUpperVariables(GenPolynomial<C> p) { 3129 GenPolynomialRing<C> fac = p.ring; 3130 if (fac.nvar <= 1) { // univariate 3131 return p; 3132 } 3133 int[] dep = p.degreeVector().dependencyOnVariables(); 3134 if (fac.nvar == dep.length) { // all variables appear 3135 return p; 3136 } 3137 if (dep.length == 0) { // no variables 3138 GenPolynomialRing<C> fac0 = new GenPolynomialRing<C>(fac.coFac, 0); 3139 GenPolynomial<C> p0 = new GenPolynomial<C>(fac0, p.leadingBaseCoefficient()); 3140 return p0; 3141 } 3142 int l = dep[0]; // higher variable 3143 int r = dep[dep.length - 1]; // lower variable 3144 if (l == 0 /*|| l == fac.nvar-1*/) { // upper variable appears 3145 return p; 3146 } 3147 int n = l; 3148 GenPolynomialRing<C> facr = fac.contract(n); 3149 Map<ExpVector, GenPolynomial<C>> mpr = p.contract(facr); 3150 if (mpr.size() != 1) { 3151 logger.warn("upper ex, l = {}, r = {}, p = {}, fac = {}", l, r, p, fac.toScript()); 3152 throw new RuntimeException("this should not happen " + mpr); 3153 } 3154 GenPolynomial<C> pr = mpr.values().iterator().next(); 3155 n = fac.nvar - 1 - r; 3156 if (n == 0) { 3157 return pr; 3158 } // else case not implemented 3159 return pr; 3160 } 3161 3162 3163 /** 3164 * Remove all lower variables which do not occur in polynomial. 3165 * @param p polynomial. 3166 * @return polynomial with removed variables 3167 */ 3168 public static <C extends RingElem<C>> GenPolynomial<C> removeUnusedLowerVariables(GenPolynomial<C> p) { 3169 GenPolynomialRing<C> fac = p.ring; 3170 if (fac.nvar <= 1) { // univariate 3171 return p; 3172 } 3173 int[] dep = p.degreeVector().dependencyOnVariables(); 3174 if (fac.nvar == dep.length) { // all variables appear 3175 return p; 3176 } 3177 if (dep.length == 0) { // no variables 3178 GenPolynomialRing<C> fac0 = new GenPolynomialRing<C>(fac.coFac, 0); 3179 GenPolynomial<C> p0 = new GenPolynomial<C>(fac0, p.leadingBaseCoefficient()); 3180 return p0; 3181 } 3182 int l = dep[0]; // higher variable 3183 int r = dep[dep.length - 1]; // lower variable 3184 if (r == fac.nvar - 1) { // lower variable appears 3185 return p; 3186 } 3187 int n = r + 1; 3188 GenPolynomialRing<GenPolynomial<C>> rfac = fac.recursive(n); 3189 GenPolynomial<GenPolynomial<C>> mpr = recursive(rfac, p); 3190 if (mpr.length() != p.length()) { 3191 logger.warn("lower ex, l = {}, r = {}, p = {}, fac = {}", l, r, p, fac.toScript()); 3192 throw new RuntimeException("this should not happen " + mpr); 3193 } 3194 RingFactory<C> cf = fac.coFac; 3195 GenPolynomialRing<C> facl = new GenPolynomialRing<C>(cf, rfac); 3196 GenPolynomial<C> pr = facl.getZERO().copy(); 3197 for (Monomial<GenPolynomial<C>> m : mpr) { 3198 ExpVector e = m.e; 3199 GenPolynomial<C> a = m.c; 3200 if (!a.isConstant()) { 3201 throw new RuntimeException("this can not happen " + a); 3202 } 3203 C c = a.leadingBaseCoefficient(); 3204 pr.doPutToMap(e, c); 3205 } 3206 return pr; 3207 } 3208 3209 3210 /** 3211 * Remove upper block of middle variables which do not occur in polynomial. 3212 * @param p polynomial. 3213 * @return polynomial with removed variables 3214 */ 3215 public static <C extends RingElem<C>> GenPolynomial<C> removeUnusedMiddleVariables(GenPolynomial<C> p) { 3216 GenPolynomialRing<C> fac = p.ring; 3217 if (fac.nvar <= 2) { // univariate or bi-variate 3218 return p; 3219 } 3220 int[] dep = p.degreeVector().dependencyOnVariables(); 3221 if (fac.nvar == dep.length) { // all variables appear 3222 return p; 3223 } 3224 if (dep.length == 0) { // no variables 3225 GenPolynomialRing<C> fac0 = new GenPolynomialRing<C>(fac.coFac, 0); 3226 GenPolynomial<C> p0 = new GenPolynomial<C>(fac0, p.leadingBaseCoefficient()); 3227 return p0; 3228 } 3229 ExpVector e1 = p.leadingExpVector(); 3230 if (dep.length == 1) { // one variable 3231 TermOrder to = new TermOrder(fac.tord.getEvord()); 3232 int i = dep[0]; 3233 String v1 = e1.indexVarName(i, fac.getVars()); 3234 String[] vars = new String[] { v1 }; 3235 GenPolynomialRing<C> fac1 = new GenPolynomialRing<C>(fac.coFac, to, vars); 3236 GenPolynomial<C> p1 = fac1.getZERO().copy(); 3237 for (Monomial<C> m : p) { 3238 ExpVector e = m.e; 3239 ExpVector f = ExpVector.create(1, 0, e.getVal(i)); 3240 p1.doPutToMap(f, m.c); 3241 } 3242 return p1; 3243 } 3244 GenPolynomialRing<GenPolynomial<C>> rfac = fac.recursive(1); 3245 GenPolynomial<GenPolynomial<C>> mpr = recursive(rfac, p); 3246 3247 int l = dep[0]; // higher variable 3248 int r = fac.nvar - dep[1]; // next variable 3249 //System.out.println("l = " + l); 3250 //System.out.println("r = " + r); 3251 3252 TermOrder to = new TermOrder(fac.tord.getEvord()); 3253 String[] vs = fac.getVars(); 3254 String[] vars = new String[r + 1]; 3255 for (int i = 0; i < r; i++) { 3256 vars[i] = vs[i]; 3257 } 3258 vars[r] = e1.indexVarName(l, vs); 3259 //System.out.println("fac = " + fac); 3260 GenPolynomialRing<C> dfac = new GenPolynomialRing<C>(fac.coFac, to, vars); 3261 //System.out.println("dfac = " + dfac); 3262 GenPolynomialRing<GenPolynomial<C>> fac2 = dfac.recursive(1); 3263 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) fac2.coFac; 3264 GenPolynomial<GenPolynomial<C>> p2r = fac2.getZERO().copy(); 3265 for (Monomial<GenPolynomial<C>> m : mpr) { 3266 ExpVector e = m.e; 3267 GenPolynomial<C> a = m.c; 3268 Map<ExpVector, GenPolynomial<C>> cc = a.contract(cfac); 3269 for (Map.Entry<ExpVector, GenPolynomial<C>> me : cc.entrySet()) { 3270 ExpVector f = me.getKey(); 3271 if (f.isZERO()) { 3272 GenPolynomial<C> c = me.getValue(); //cc.get(f); 3273 p2r.doPutToMap(e, c); 3274 } else { 3275 throw new RuntimeException("this should not happen " + cc); 3276 } 3277 } 3278 } 3279 GenPolynomial<C> p2 = distribute(dfac, p2r); 3280 return p2; 3281 } 3282 3283 3284 /** 3285 * Select polynomial with univariate leading term in variable i. 3286 * @param i variable index. 3287 * @return polynomial with head term in variable i 3288 */ 3289 public static <C extends RingElem<C>> GenPolynomial<C> selectWithVariable(List<GenPolynomial<C>> P, 3290 int i) { 3291 for (GenPolynomial<C> p : P) { 3292 int[] dep = p.leadingExpVector().dependencyOnVariables(); 3293 if (dep.length == 1 && dep[0] == i) { 3294 return p; 3295 } 3296 } 3297 return null; // not found 3298 } 3299 3300} 3301 3302 3303/** 3304 * Conversion of distributive to recursive representation. 3305 */ 3306class DistToRec<C extends RingElem<C>> 3307 implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<GenPolynomial<C>>> { 3308 3309 3310 GenPolynomialRing<GenPolynomial<C>> fac; 3311 3312 3313 public DistToRec(GenPolynomialRing<GenPolynomial<C>> fac) { 3314 this.fac = fac; 3315 } 3316 3317 3318 public GenPolynomial<GenPolynomial<C>> eval(GenPolynomial<C> c) { 3319 if (c == null) { 3320 return fac.getZERO(); 3321 } 3322 return PolyUtil.<C> recursive(fac, c); 3323 } 3324} 3325 3326 3327/** 3328 * Conversion of recursive to distributive representation. 3329 */ 3330class RecToDist<C extends RingElem<C>> 3331 implements UnaryFunctor<GenPolynomial<GenPolynomial<C>>, GenPolynomial<C>> { 3332 3333 3334 GenPolynomialRing<C> fac; 3335 3336 3337 public RecToDist(GenPolynomialRing<C> fac) { 3338 this.fac = fac; 3339 } 3340 3341 3342 public GenPolynomial<C> eval(GenPolynomial<GenPolynomial<C>> c) { 3343 if (c == null) { 3344 return fac.getZERO(); 3345 } 3346 return PolyUtil.<C> distribute(fac, c); 3347 } 3348} 3349 3350 3351/** 3352 * BigRational numerator functor. 3353 */ 3354class RatNumer implements UnaryFunctor<BigRational, BigInteger> { 3355 3356 3357 public BigInteger eval(BigRational c) { 3358 if (c == null) { 3359 return new BigInteger(); 3360 } 3361 return new BigInteger(c.numerator()); 3362 } 3363} 3364 3365 3366/** 3367 * Conversion of symmetric ModInteger to BigInteger functor. 3368 */ 3369class ModSymToInt<C extends RingElem<C> & Modular> implements UnaryFunctor<C, BigInteger> { 3370 3371 3372 public BigInteger eval(C c) { 3373 if (c == null) { 3374 return new BigInteger(); 3375 } 3376 return c.getSymmetricInteger(); 3377 } 3378} 3379 3380 3381/** 3382 * Conversion of ModInteger to BigInteger functor. 3383 */ 3384class ModToInt<C extends RingElem<C> & Modular> implements UnaryFunctor<C, BigInteger> { 3385 3386 3387 public BigInteger eval(C c) { 3388 if (c == null) { 3389 return new BigInteger(); 3390 } 3391 return c.getInteger(); 3392 } 3393} 3394 3395 3396/** 3397 * Conversion of BigRational to BigInteger with division by lcm functor. result 3398 * = num*(lcm/denom). 3399 */ 3400class RatToInt implements UnaryFunctor<BigRational, BigInteger> { 3401 3402 3403 java.math.BigInteger lcm; 3404 3405 3406 public RatToInt(java.math.BigInteger lcm) { 3407 this.lcm = lcm; //.getVal(); 3408 } 3409 3410 3411 public BigInteger eval(BigRational c) { 3412 if (c == null) { 3413 return new BigInteger(); 3414 } 3415 // p = num*(lcm/denom) 3416 java.math.BigInteger b = lcm.divide(c.denominator()); 3417 return new BigInteger(c.numerator().multiply(b)); 3418 } 3419} 3420 3421 3422/** 3423 * Conversion of BigRational to BigInteger. result = (num/gcd)*(lcm/denom). 3424 */ 3425class RatToIntFactor implements UnaryFunctor<BigRational, BigInteger> { 3426 3427 3428 final java.math.BigInteger lcm; 3429 3430 3431 final java.math.BigInteger gcd; 3432 3433 3434 public RatToIntFactor(java.math.BigInteger gcd, java.math.BigInteger lcm) { 3435 this.gcd = gcd; 3436 this.lcm = lcm; // .getVal(); 3437 } 3438 3439 3440 public BigInteger eval(BigRational c) { 3441 if (c == null) { 3442 return new BigInteger(); 3443 } 3444 if (gcd.equals(java.math.BigInteger.ONE)) { 3445 // p = num*(lcm/denom) 3446 java.math.BigInteger b = lcm.divide(c.denominator()); 3447 return new BigInteger(c.numerator().multiply(b)); 3448 } 3449 // p = (num/gcd)*(lcm/denom) 3450 java.math.BigInteger a = c.numerator().divide(gcd); 3451 java.math.BigInteger b = lcm.divide(c.denominator()); 3452 return new BigInteger(a.multiply(b)); 3453 } 3454} 3455 3456 3457/** 3458 * Conversion of Rational to BigDecimal. result = decimal(r). 3459 */ 3460class RatToDec<C extends Element<C> & Rational> implements UnaryFunctor<C, BigDecimal> { 3461 3462 3463 public BigDecimal eval(C c) { 3464 if (c == null) { 3465 return new BigDecimal(); 3466 } 3467 return new BigDecimal(c.getRational()); 3468 } 3469} 3470 3471 3472/** 3473 * Conversion of Complex Rational to Complex BigDecimal. result = decimal(r). 3474 */ 3475class CompRatToDec<C extends RingElem<C> & Rational> 3476 implements UnaryFunctor<Complex<C>, Complex<BigDecimal>> { 3477 3478 3479 ComplexRing<BigDecimal> ring; 3480 3481 3482 public CompRatToDec(RingFactory<Complex<BigDecimal>> ring) { 3483 this.ring = (ComplexRing<BigDecimal>) ring; 3484 } 3485 3486 3487 public Complex<BigDecimal> eval(Complex<C> c) { 3488 if (c == null) { 3489 return ring.getZERO(); 3490 } 3491 BigDecimal r = new BigDecimal(c.getRe().getRational()); 3492 BigDecimal i = new BigDecimal(c.getIm().getRational()); 3493 return new Complex<BigDecimal>(ring, r, i); 3494 } 3495} 3496 3497 3498/** 3499 * Conversion from BigInteger functor. 3500 */ 3501class FromInteger<D extends RingElem<D>> implements UnaryFunctor<BigInteger, D> { 3502 3503 3504 RingFactory<D> ring; 3505 3506 3507 public FromInteger(RingFactory<D> ring) { 3508 this.ring = ring; 3509 } 3510 3511 3512 public D eval(BigInteger c) { 3513 if (c == null) { 3514 return ring.getZERO(); 3515 } 3516 return ring.fromInteger(c.getVal()); 3517 } 3518} 3519 3520 3521/** 3522 * Conversion from GenPolynomial<BigInteger> functor. 3523 */ 3524class FromIntegerPoly<D extends RingElem<D>> 3525 implements UnaryFunctor<GenPolynomial<BigInteger>, GenPolynomial<D>> { 3526 3527 3528 GenPolynomialRing<D> ring; 3529 3530 3531 FromInteger<D> fi; 3532 3533 3534 public FromIntegerPoly(GenPolynomialRing<D> ring) { 3535 if (ring == null) { 3536 throw new IllegalArgumentException("ring must not be null"); 3537 } 3538 this.ring = ring; 3539 fi = new FromInteger<D>(ring.coFac); 3540 } 3541 3542 3543 public GenPolynomial<D> eval(GenPolynomial<BigInteger> c) { 3544 if (c == null) { 3545 return ring.getZERO(); 3546 } 3547 return PolyUtil.<BigInteger, D> map(ring, c, fi); 3548 } 3549} 3550 3551 3552/** 3553 * Conversion from GenPolynomial<BigRational> to GenPolynomial <BigInteger> 3554 * functor. 3555 */ 3556class RatToIntPoly implements UnaryFunctor<GenPolynomial<BigRational>, GenPolynomial<BigInteger>> { 3557 3558 3559 GenPolynomialRing<BigInteger> ring; 3560 3561 3562 public RatToIntPoly(GenPolynomialRing<BigInteger> ring) { 3563 if (ring == null) { 3564 throw new IllegalArgumentException("ring must not be null"); 3565 } 3566 this.ring = ring; 3567 } 3568 3569 3570 public GenPolynomial<BigInteger> eval(GenPolynomial<BigRational> c) { 3571 if (c == null) { 3572 return ring.getZERO(); 3573 } 3574 return PolyUtil.integerFromRationalCoefficients(ring, c); 3575 } 3576} 3577 3578 3579/** 3580 * Real part functor. 3581 */ 3582class RealPart implements UnaryFunctor<BigComplex, BigRational> { 3583 3584 3585 public BigRational eval(BigComplex c) { 3586 if (c == null) { 3587 return new BigRational(); 3588 } 3589 return c.getRe(); 3590 } 3591} 3592 3593 3594/** 3595 * Imaginary part functor. 3596 */ 3597class ImagPart implements UnaryFunctor<BigComplex, BigRational> { 3598 3599 3600 public BigRational eval(BigComplex c) { 3601 if (c == null) { 3602 return new BigRational(); 3603 } 3604 return c.getIm(); 3605 } 3606} 3607 3608 3609/** 3610 * Real part functor. 3611 */ 3612class RealPartComplex<C extends RingElem<C>> implements UnaryFunctor<Complex<C>, C> { 3613 3614 3615 public C eval(Complex<C> c) { 3616 if (c == null) { 3617 return null; 3618 } 3619 return c.getRe(); 3620 } 3621} 3622 3623 3624/** 3625 * Imaginary part functor. 3626 */ 3627class ImagPartComplex<C extends RingElem<C>> implements UnaryFunctor<Complex<C>, C> { 3628 3629 3630 public C eval(Complex<C> c) { 3631 if (c == null) { 3632 return null; 3633 } 3634 return c.getIm(); 3635 } 3636} 3637 3638 3639/** 3640 * Rational to complex functor. 3641 */ 3642class ToComplex<C extends RingElem<C>> implements UnaryFunctor<C, Complex<C>> { 3643 3644 3645 final protected ComplexRing<C> cfac; 3646 3647 3648 @SuppressWarnings("unchecked") 3649 public ToComplex(RingFactory<Complex<C>> fac) { 3650 if (fac == null) { 3651 throw new IllegalArgumentException("fac must not be null"); 3652 } 3653 cfac = (ComplexRing<C>) fac; 3654 } 3655 3656 3657 public Complex<C> eval(C c) { 3658 if (c == null) { 3659 return cfac.getZERO(); 3660 } 3661 return new Complex<C>(cfac, c); 3662 } 3663} 3664 3665 3666/** 3667 * Rational to complex functor. 3668 */ 3669class RatToCompl implements UnaryFunctor<BigRational, BigComplex> { 3670 3671 3672 public BigComplex eval(BigRational c) { 3673 if (c == null) { 3674 return new BigComplex(); 3675 } 3676 return new BigComplex(c); 3677 } 3678} 3679 3680 3681/** 3682 * Any ring element to generic complex functor. 3683 */ 3684class AnyToComplex<C extends GcdRingElem<C>> implements UnaryFunctor<C, Complex<C>> { 3685 3686 3687 final protected ComplexRing<C> cfac; 3688 3689 3690 public AnyToComplex(ComplexRing<C> fac) { 3691 if (fac == null) { 3692 throw new IllegalArgumentException("fac must not be null"); 3693 } 3694 cfac = fac; 3695 } 3696 3697 3698 public AnyToComplex(RingFactory<C> fac) { 3699 this(new ComplexRing<C>(fac)); 3700 } 3701 3702 3703 public Complex<C> eval(C a) { 3704 if (a == null || a.isZERO()) { // should not happen 3705 return cfac.getZERO(); 3706 } else if (a.isONE()) { 3707 return cfac.getONE(); 3708 } else { 3709 return new Complex<C>(cfac, a); 3710 } 3711 } 3712} 3713 3714 3715/** 3716 * Algebraic to generic complex functor. 3717 */ 3718class AlgebToCompl<C extends GcdRingElem<C>> implements UnaryFunctor<AlgebraicNumber<C>, Complex<C>> { 3719 3720 3721 final protected ComplexRing<C> cfac; 3722 3723 3724 public AlgebToCompl(ComplexRing<C> fac) { 3725 if (fac == null) { 3726 throw new IllegalArgumentException("fac must not be null"); 3727 } 3728 cfac = fac; 3729 } 3730 3731 3732 public Complex<C> eval(AlgebraicNumber<C> a) { 3733 if (a == null || a.isZERO()) { // should not happen 3734 return cfac.getZERO(); 3735 } else if (a.isONE()) { 3736 return cfac.getONE(); 3737 } else { 3738 GenPolynomial<C> p = a.getVal(); 3739 C real = cfac.ring.getZERO(); 3740 C imag = cfac.ring.getZERO(); 3741 for (Monomial<C> m : p) { 3742 if (m.exponent().getVal(0) == 1L) { 3743 imag = m.coefficient(); 3744 } else if (m.exponent().getVal(0) == 0L) { 3745 real = m.coefficient(); 3746 } else { 3747 throw new IllegalArgumentException("unexpected monomial " + m); 3748 } 3749 } 3750 //Complex<C> c = new Complex<C>(cfac,real,imag); 3751 return new Complex<C>(cfac, real, imag); 3752 } 3753 } 3754} 3755 3756 3757/** 3758 * Ceneric complex to algebraic number functor. 3759 */ 3760class ComplToAlgeb<C extends GcdRingElem<C>> implements UnaryFunctor<Complex<C>, AlgebraicNumber<C>> { 3761 3762 3763 final protected AlgebraicNumberRing<C> afac; 3764 3765 3766 final protected AlgebraicNumber<C> I; 3767 3768 3769 public ComplToAlgeb(AlgebraicNumberRing<C> fac) { 3770 if (fac == null) { 3771 throw new IllegalArgumentException("fac must not be null"); 3772 } 3773 afac = fac; 3774 I = afac.getGenerator(); 3775 } 3776 3777 3778 public AlgebraicNumber<C> eval(Complex<C> c) { 3779 if (c == null || c.isZERO()) { // should not happen 3780 return afac.getZERO(); 3781 } else if (c.isONE()) { 3782 return afac.getONE(); 3783 } else if (c.isIMAG()) { 3784 return I; 3785 } else { 3786 return I.multiply(c.getIm()).sum(c.getRe()); 3787 } 3788 } 3789} 3790 3791 3792/** 3793 * Algebraic to polynomial functor. 3794 */ 3795class AlgToPoly<C extends GcdRingElem<C>> implements UnaryFunctor<AlgebraicNumber<C>, GenPolynomial<C>> { 3796 3797 3798 public GenPolynomial<C> eval(AlgebraicNumber<C> c) { 3799 if (c == null) { 3800 return null; 3801 } 3802 return c.val; 3803 } 3804} 3805 3806 3807/** 3808 * Polynomial to algebriac functor. 3809 */ 3810class PolyToAlg<C extends GcdRingElem<C>> implements UnaryFunctor<GenPolynomial<C>, AlgebraicNumber<C>> { 3811 3812 3813 final protected AlgebraicNumberRing<C> afac; 3814 3815 3816 public PolyToAlg(AlgebraicNumberRing<C> fac) { 3817 if (fac == null) { 3818 throw new IllegalArgumentException("fac must not be null"); 3819 } 3820 afac = fac; 3821 } 3822 3823 3824 public AlgebraicNumber<C> eval(GenPolynomial<C> c) { 3825 if (c == null) { 3826 return afac.getZERO(); 3827 } 3828 return new AlgebraicNumber<C>(afac, c); 3829 } 3830} 3831 3832 3833/** 3834 * Coefficient to algebriac functor. 3835 */ 3836class CoeffToAlg<C extends GcdRingElem<C>> implements UnaryFunctor<C, AlgebraicNumber<C>> { 3837 3838 3839 final protected AlgebraicNumberRing<C> afac; 3840 3841 3842 final protected GenPolynomial<C> zero; 3843 3844 3845 public CoeffToAlg(AlgebraicNumberRing<C> fac) { 3846 if (fac == null) { 3847 throw new IllegalArgumentException("fac must not be null"); 3848 } 3849 afac = fac; 3850 GenPolynomialRing<C> pfac = afac.ring; 3851 zero = pfac.getZERO(); 3852 } 3853 3854 3855 public AlgebraicNumber<C> eval(C c) { 3856 if (c == null) { 3857 return afac.getZERO(); 3858 } 3859 return new AlgebraicNumber<C>(afac, zero.sum(c)); 3860 } 3861} 3862 3863 3864/** 3865 * Coefficient to recursive algebriac functor. 3866 */ 3867class CoeffToRecAlg<C extends GcdRingElem<C>> implements UnaryFunctor<C, AlgebraicNumber<C>> { 3868 3869 3870 final protected List<AlgebraicNumberRing<C>> lfac; 3871 3872 3873 final int depth; 3874 3875 3876 @SuppressWarnings("unchecked") 3877 public CoeffToRecAlg(int depth, AlgebraicNumberRing<C> fac) { 3878 if (fac == null) { 3879 throw new IllegalArgumentException("fac must not be null"); 3880 } 3881 AlgebraicNumberRing<C> afac = fac; 3882 this.depth = depth; 3883 lfac = new ArrayList<AlgebraicNumberRing<C>>(this.depth); 3884 lfac.add(fac); 3885 for (int i = 1; i < this.depth; i++) { 3886 RingFactory<C> rf = afac.ring.coFac; 3887 if (!(rf instanceof AlgebraicNumberRing)) { 3888 throw new IllegalArgumentException("fac depth to low"); 3889 } 3890 afac = (AlgebraicNumberRing<C>) (Object) rf; 3891 lfac.add(afac); 3892 } 3893 } 3894 3895 3896 @SuppressWarnings("unchecked") 3897 public AlgebraicNumber<C> eval(C c) { 3898 if (c == null) { 3899 return lfac.get(0).getZERO(); 3900 } 3901 C ac = c; 3902 AlgebraicNumberRing<C> af = lfac.get(lfac.size() - 1); 3903 GenPolynomial<C> zero = af.ring.getZERO(); 3904 AlgebraicNumber<C> an = new AlgebraicNumber<C>(af, zero.sum(ac)); 3905 for (int i = lfac.size() - 2; i >= 0; i--) { 3906 af = lfac.get(i); 3907 zero = af.ring.getZERO(); 3908 ac = (C) (Object) an; 3909 an = new AlgebraicNumber<C>(af, zero.sum(ac)); 3910 } 3911 return an; 3912 } 3913} 3914 3915 3916/** 3917 * Evaluate main variable functor. 3918 */ 3919class EvalMain<C extends RingElem<C>> implements UnaryFunctor<GenPolynomial<C>, C> { 3920 3921 3922 final RingFactory<C> cfac; 3923 3924 3925 final C a; 3926 3927 3928 public EvalMain(RingFactory<C> cfac, C a) { 3929 this.cfac = cfac; 3930 this.a = a; 3931 } 3932 3933 3934 public C eval(GenPolynomial<C> c) { 3935 if (c == null) { 3936 return cfac.getZERO(); 3937 } 3938 return PolyUtil.<C> evaluateMain(cfac, c, a); 3939 } 3940} 3941 3942 3943/** 3944 * Evaluate main variable functor. 3945 */ 3946class EvalMainPol<C extends RingElem<C>> implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 3947 3948 3949 final GenPolynomialRing<C> cfac; 3950 3951 3952 final C a; 3953 3954 3955 public EvalMainPol(GenPolynomialRing<C> cfac, C a) { 3956 this.cfac = cfac; 3957 this.a = a; 3958 } 3959 3960 3961 public GenPolynomial<C> eval(GenPolynomial<C> c) { 3962 if (c == null) { 3963 return cfac.getZERO(); 3964 } 3965 return PolyUtil.<C> evaluateMain(cfac, c, a); 3966 } 3967} 3968 3969 3970/** 3971 * Evaluate all variable functor. 3972 */ 3973class EvalAllPol<C extends RingElem<C>> implements UnaryFunctor<GenPolynomial<C>, C> { 3974 3975 3976 final RingFactory<C> cfac; 3977 3978 3979 final List<C> a; 3980 3981 3982 public EvalAllPol(RingFactory<C> cfac, List<C> a) { 3983 this.cfac = cfac; 3984 this.a = a; 3985 } 3986 3987 3988 public C eval(GenPolynomial<C> c) { 3989 if (c == null) { 3990 return cfac.getZERO(); 3991 } 3992 return PolyUtil.<C> evaluateAll(cfac, c, a); 3993 } 3994}