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