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