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