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