001/* 002 * $Id$ 003 */ 004 005package edu.jas.poly; 006 007 008import java.io.IOException; 009import java.io.Reader; 010import java.io.StringReader; 011import java.math.BigInteger; 012import java.util.ArrayList; 013import java.util.Arrays; 014import java.util.Iterator; 015import java.util.List; 016import java.util.Random; 017import java.util.SortedMap; 018import java.util.concurrent.atomic.AtomicLong; 019 020import org.apache.logging.log4j.LogManager; 021import org.apache.logging.log4j.Logger; 022 023import edu.jas.arith.ModIntegerRing; 024import edu.jas.kern.PreemptStatus; 025import edu.jas.kern.PrettyPrint; 026import edu.jas.kern.Scripting; 027import edu.jas.structure.RingElem; 028import edu.jas.structure.RingFactory; 029import edu.jas.util.CartesianProduct; 030import edu.jas.util.CartesianProductInfinite; 031import edu.jas.util.LongIterable; 032import edu.jas.vector.GenVector; 033import edu.jas.vector.GenMatrix; 034import edu.jas.vector.GenMatrixRing; 035 036 037/** 038 * GenPolynomialRing generic polynomial factory. It implements RingFactory for 039 * n-variate ordered polynomials over coefficients C. The variables commute with 040 * each other and with the coefficients. For non-commutative coefficients some 041 * care is taken to respect the multiplication order. 042 * 043 * Almost immutable object, except variable names. 044 * @param <C> coefficient type 045 * @author Heinz Kredel 046 */ 047 048public class GenPolynomialRing<C extends RingElem<C>> 049 implements RingFactory<GenPolynomial<C>>, Iterable<GenPolynomial<C>> { 050 051 052 /** 053 * The factory for the coefficients. 054 */ 055 public final RingFactory<C> coFac; 056 057 058 /** 059 * The number of variables. 060 */ 061 public final int nvar; 062 063 064 /** 065 * The term order. 066 */ 067 public final TermOrder tord; 068 069 070 /** 071 * True for partially reversed variables. 072 */ 073 protected boolean partial; 074 075 076 /** 077 * The names of the variables. This value can be modified. 078 */ 079 protected String[] vars; 080 081 082 /** 083 * Counter to distinguish new variables. 084 */ 085 private static AtomicLong varCounter = new AtomicLong(0L); 086 087 088 /** 089 * The constant polynomial 0 for this ring. 090 */ 091 public /*final*/ GenPolynomial<C> ZERO; // volatile not meaningful by DL 092 093 094 /** 095 * The constant polynomial 1 for this ring. 096 */ 097 public /*final*/ GenPolynomial<C> ONE; // volatile not meaningful by DL 098 099 100 /** 101 * The constant exponent vector 0 for this ring. 102 */ 103 public final ExpVector evzero; // volatile not meaningful by DL 104 105 106 /** 107 * A default random sequence generator. 108 */ 109 protected final static Random random = new Random(); 110 111 112 /** 113 * Indicator if this ring is a field. 114 */ 115 protected int isField = -1; // initially unknown 116 117 118 /** 119 * Log4j logger object. 120 */ 121 private static final Logger logger = LogManager.getLogger(GenPolynomialRing.class); 122 123 124 /** 125 * Count for number of polynomial creations. 126 */ 127 static int creations = 0; 128 129 130 /** 131 * Flag to enable if preemptive interrupt is checked. 132 */ 133 volatile boolean checkPreempt = PreemptStatus.isAllowed(); 134 135 136 /** 137 * The constructor creates a polynomial factory object with the default term 138 * order. 139 * @param cf factory for coefficients of type C. 140 * @param n number of variables. 141 */ 142 public GenPolynomialRing(RingFactory<C> cf, int n) { 143 this(cf, n, new TermOrder(), null); 144 } 145 146 147 /** 148 * The constructor creates a polynomial factory object. 149 * @param cf factory for coefficients of type C. 150 * @param n number of variables. 151 * @param t a term order. 152 */ 153 public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t) { 154 this(cf, n, t, null); 155 } 156 157 158 /** 159 * The constructor creates a polynomial factory object. 160 * @param cf factory for coefficients of type C. 161 * @param v names for the variables. 162 */ 163 public GenPolynomialRing(RingFactory<C> cf, String[] v) { 164 this(cf, v.length, v); 165 } 166 167 168 /** 169 * The constructor creates a polynomial factory object. 170 * @param cf factory for coefficients of type C. 171 * @param n number of variables. 172 * @param v names for the variables. 173 */ 174 public GenPolynomialRing(RingFactory<C> cf, int n, String[] v) { 175 this(cf, n, new TermOrder(), v); 176 } 177 178 179 /** 180 * The constructor creates a polynomial factory object. 181 * @param cf factory for coefficients of type C. 182 * @param t a term order. 183 * @param v names for the variables. 184 */ 185 public GenPolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) { 186 this(cf, v.length, t, v); 187 } 188 189 190 /** 191 * The constructor creates a polynomial factory object. 192 * @param cf factory for coefficients of type C. 193 * @param v names for the variables. 194 * @param t a term order. 195 */ 196 public GenPolynomialRing(RingFactory<C> cf, String[] v, TermOrder t) { 197 this(cf, v.length, t, v); 198 } 199 200 201 /** 202 * The constructor creates a polynomial factory object. 203 * @param cf factory for coefficients of type C. 204 * @param n number of variables. 205 * @param t a term order. 206 * @param v names for the variables. 207 */ 208 public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) { 209 coFac = cf; 210 nvar = n; 211 tord = t; 212 partial = false; 213 if (v == null) { 214 vars = null; 215 } else { 216 vars = Arrays.copyOf(v, v.length); // > Java-5 217 } 218 C coeff = coFac.getONE(); 219 synchronized (this) { 220 evzero = ExpVector.create(nvar); 221 ZERO = new GenPolynomial<C>(this); 222 ONE = new GenPolynomial<C>(this, coeff, evzero); 223 } 224 //logger.debug("ZERO {} {}", ZERO.toString(), ZERO.val); 225 //System.out.println("thread@ZERO: " + Thread.currentThread()); 226 if (vars == null) { 227 if (PrettyPrint.isTrue()) { 228 vars = newVars("x", nvar); 229 } 230 } else { 231 if (vars.length != nvar) { 232 throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar); 233 } 234 // addVars(vars); 235 } 236 } 237 238 239 /** 240 * The constructor creates a polynomial factory object with the the same 241 * term order, number of variables and variable names as the given 242 * polynomial factory, only the coefficient factories differ. 243 * @param cf factory for coefficients of type C. 244 * @param o other polynomial ring. 245 */ 246 public GenPolynomialRing(RingFactory<C> cf, GenPolynomialRing o) { 247 this(cf, o.nvar, o.tord, o.vars); 248 } 249 250 251 /** 252 * The constructor creates a polynomial factory object with the the same 253 * coefficient factory, number of variables and variable names as the given 254 * polynomial factory, only the term order differs. 255 * @param to term order. 256 * @param o other polynomial ring. 257 */ 258 public GenPolynomialRing(GenPolynomialRing<C> o, TermOrder to) { 259 this(o.coFac, o.nvar, to, o.vars); 260 } 261 262 263 /** 264 * Copy this factory. 265 * @return a clone of this. 266 */ 267 public GenPolynomialRing<C> copy() { 268 return new GenPolynomialRing<C>(coFac, this); 269 } 270 271 272 /** 273 * Get the String representation. 274 * @see java.lang.Object#toString() 275 */ 276 @SuppressWarnings("cast") 277 @Override 278 public String toString() { 279 String res = null; 280 if (PrettyPrint.isTrue()) { // wrong: && coFac != null 281 String scf = coFac.getClass().getSimpleName(); 282 if (coFac instanceof AlgebraicNumberRing) { 283 AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; 284 res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]"; 285 } 286 if (coFac instanceof GenPolynomialRing) { 287 GenPolynomialRing rf = (GenPolynomialRing) coFac; 288 //String[] v = rf.vars; 289 //RingFactory cf = rf.coFac; 290 //String cs; 291 //if (cf instanceof ModIntegerRing) { 292 // cs = cf.toString(); 293 //} else { 294 // cs = " " + cf.getClass().getSimpleName(); 295 //} 296 //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } "; 297 res = "IntFunc" + "( " + rf.toString() + " )"; 298 } 299 if (((Object) coFac) instanceof ModIntegerRing) { 300 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 301 res = "Mod " + mn.getModul() + " "; 302 } 303 if (res == null) { 304 res = coFac.toString(); 305 if (res.matches("[0-9].*")) { 306 res = scf; 307 } 308 } 309 res += "( " + varsToString() + " ) " + tord.toString() + " "; 310 } else { 311 res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " "; 312 if (coFac instanceof AlgebraicNumberRing) { 313 AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; 314 res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]"; 315 } 316 if (coFac instanceof GenPolynomialRing) { 317 GenPolynomialRing rf = (GenPolynomialRing) coFac; 318 //String[] v = rf.vars; 319 //RingFactory cf = rf.coFac; 320 //String cs; 321 //if (cf instanceof ModIntegerRing) { 322 // cs = cf.toString(); 323 //} else { 324 // cs = " " + cf.getClass().getSimpleName(); 325 //} 326 //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } "; 327 res = "IntFunc" + "( " + rf.toString() + " )"; 328 } 329 if (((Object) coFac) instanceof ModIntegerRing) { 330 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 331 res = "Mod " + mn.getModul() + " "; 332 } 333 //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]"; 334 res += "( " + varsToString() + " ) " + tord.toString() + " ]"; 335 } 336 return res; 337 } 338 339 340 /** 341 * Get a scripting compatible string representation. 342 * @return script compatible representation for this Element. 343 * @see edu.jas.structure.Element#toScript() 344 */ 345 @Override 346 public String toScript() { 347 StringBuffer s = new StringBuffer(); 348 switch (Scripting.getLang()) { 349 case Ruby: 350 s.append("PolyRing.new("); 351 break; 352 case Python: 353 default: 354 s.append("PolyRing("); 355 } 356 if (coFac instanceof RingElem) { 357 s.append(((RingElem<C>) coFac).toScriptFactory()); 358 } else { 359 s.append(coFac.toScript().trim()); 360 } 361 s.append(",\"" + varsToString() + "\""); 362 String to = tord.toScript(); 363 s.append("," + to); 364 s.append(")"); 365 return s.toString(); 366 } 367 368 369 /** 370 * Get a scripting compatible string representation of an ExpVector of this 371 * ring. 372 * @param e exponent vector 373 * @return script compatible representation for the ExpVector. 374 */ 375 public String toScript(ExpVector e) { 376 if (e == null) { 377 return "null"; 378 } 379 if (vars != null) { 380 return e.toScript(vars); 381 } 382 return e.toScript(); 383 } 384 385 386 /** 387 * Comparison with any other object. 388 * @see java.lang.Object#equals(java.lang.Object) 389 */ 390 @Override 391 @SuppressWarnings("unchecked") 392 public boolean equals(Object other) { 393 if (other == null) { 394 return false; 395 } 396 if (!(other instanceof GenPolynomialRing)) { 397 return false; 398 } 399 GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other; 400 if (nvar != oring.nvar) { 401 return false; 402 } 403 if (!coFac.equals(oring.coFac)) { 404 return false; 405 } 406 if (!tord.equals(oring.tord)) { 407 return false; 408 } 409 // same variables required ? 410 if (!Arrays.deepEquals(vars, oring.vars)) { 411 return false; 412 } 413 return true; 414 } 415 416 417 /** 418 * Hash code for this polynomial ring. 419 * @see java.lang.Object#hashCode() 420 */ 421 @Override 422 public int hashCode() { 423 int h; 424 h = (nvar << 27); 425 h += (coFac.hashCode() << 11); 426 h += (tord.hashCode() << 9); 427 h += Arrays.hashCode(vars); 428 //System.out.println("GenPolynomialRing.hashCode: " + h); 429 return h; 430 } 431 432 433 /** 434 * Get the number of polynomial creations. 435 * @return creations. 436 */ 437 public int getCreations() { 438 return creations; 439 } 440 441 442 /** 443 * Get the variable names. 444 * @return vars. 445 */ 446 public String[] getVars() { 447 return Arrays.copyOf(vars, vars.length); // > Java-5 448 } 449 450 451 /** 452 * Set the variable names. 453 * @return old vars. 454 */ 455 public String[] setVars(String[] v) { 456 if (v.length != nvar) { 457 throw new IllegalArgumentException( 458 "v not matching number of variables: " + Arrays.toString(v) + ", nvar " + nvar); 459 } 460 String[] t = vars; 461 vars = Arrays.copyOf(v, v.length); // > Java-5 462 return t; 463 } 464 465 466 /** 467 * Get a String representation of the variable names. 468 * @return names separated by commas. 469 */ 470 public String varsToString() { 471 if (vars == null) { 472 return "#" + nvar; 473 } 474 //return Arrays.toString(vars); 475 return ExpVector.varsToString(vars); 476 } 477 478 479 /** 480 * Get the zero element from the coefficients. 481 * @return 0 as C. 482 */ 483 public C getZEROCoefficient() { 484 return coFac.getZERO(); 485 } 486 487 488 /** 489 * Get the one element from the coefficients. 490 * @return 1 as C. 491 */ 492 public C getONECoefficient() { 493 return coFac.getONE(); 494 } 495 496 497 /** 498 * Get the zero element. 499 * @return 0 as GenPolynomial<C>. 500 */ 501 public synchronized GenPolynomial<C> getZERO() { 502 if (ZERO == null || !ZERO.isZERO()) { // happened since May 5 2022 503 // Name : java-11-openjdk-headless, java-17-openjdk-headless 504 // Version : 11.0.15.0, 17.0.4 505 // Release : 150000.3.80.1, 150400.3.3.1 506 GenPolynomial<C> x = ZERO; 507 ZERO = new GenPolynomial<C>(this); 508 logger.info("warn: ZERO@get |{}| wrong fix to {}", x, ZERO); 509 } 510 return ZERO; 511 } 512 513 514 /** 515 * Get the one element. 516 * @return 1 as GenPolynomial<C>. 517 */ 518 public synchronized GenPolynomial<C> getONE() { 519 if (ONE == null || !ONE.isONE()) { 520 ONE = new GenPolynomial<C>(this, coFac.getONE(), evzero); 521 logger.info("warn: ONE@get {}", ONE); 522 } 523 return ONE; 524 } 525 526 527 /** 528 * Query if this ring is commutative. 529 * @return true if this ring is commutative, else false. 530 */ 531 public boolean isCommutative() { 532 return coFac.isCommutative(); 533 } 534 535 536 /** 537 * Query if this ring is associative. 538 * @return true if this ring is associative, else false. 539 */ 540 public boolean isAssociative() { 541 return coFac.isAssociative(); 542 } 543 544 545 /** 546 * Query if this ring is a field. 547 * @return false. 548 */ 549 public boolean isField() { 550 if (isField > 0) { 551 return true; 552 } 553 if (isField == 0) { 554 return false; 555 } 556 if (coFac.isField() && nvar == 0) { 557 isField = 1; 558 return true; 559 } 560 isField = 0; 561 return false; 562 } 563 564 565 /** 566 * Characteristic of this ring. 567 * @return characteristic of this ring. 568 */ 569 public java.math.BigInteger characteristic() { 570 return coFac.characteristic(); 571 } 572 573 574 /** 575 * Get a (constant) GenPolynomial<C> element from a coefficient value. 576 * @param a coefficient. 577 * @return a GenPolynomial<C>. 578 */ 579 public GenPolynomial<C> valueOf(C a) { 580 return new GenPolynomial<C>(this, a); 581 } 582 583 584 /** 585 * Get a GenPolynomial<C> element from an exponent vector. 586 * @param e exponent vector. 587 * @return a GenPolynomial<C>. 588 */ 589 public GenPolynomial<C> valueOf(ExpVector e) { 590 if (e == null) { 591 return getZERO(); 592 } 593 return new GenPolynomial<C>(this, coFac.getONE(), e); 594 } 595 596 597 /** 598 * Get a GenPolynomial<C> element from a list of exponent vectors. 599 * @param E list of exponent vector. 600 * @return a GenPolynomial<C>. 601 */ 602 public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) { 603 if (E == null) { 604 return null; 605 } 606 List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size()); 607 for (ExpVector e : E) { 608 GenPolynomial<C> p = valueOf(e); 609 P.add(p); 610 } 611 return P; 612 } 613 614 615 /** 616 * Get a GenPolynomial<C> element from a coefficient and an exponent 617 * vector. 618 * @param a coefficient. 619 * @param e exponent vector. 620 * @return a GenPolynomial<C>. 621 */ 622 public GenPolynomial<C> valueOf(C a, ExpVector e) { 623 return new GenPolynomial<C>(this, a, e); 624 } 625 626 627 /** 628 * Get a GenPolynomial<C> element from a monomial. 629 * @param m monomial. 630 * @return a GenPolynomial<C>. 631 */ 632 public GenPolynomial<C> valueOf(Monomial<C> m) { 633 return new GenPolynomial<C>(this, m.c, m.e); 634 } 635 636 637 /** 638 * Get a (constant) GenPolynomial<C> element from a long value. 639 * @param a long. 640 * @return a GenPolynomial<C>. 641 */ 642 public GenPolynomial<C> fromInteger(long a) { 643 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 644 } 645 646 647 /** 648 * Get a (constant) GenPolynomial<C> element from a BigInteger value. 649 * @param a BigInteger. 650 * @return a GenPolynomial<C>. 651 */ 652 public GenPolynomial<C> fromInteger(BigInteger a) { 653 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 654 } 655 656 657 /** 658 * Get a GenPolynomial<C> from a GenVector<C>. 659 * @param a GenVector<C>. 660 * @return a GenPolynomial<C>. 661 */ 662 public GenPolynomial<C> fromVector(GenVector<C> a) { 663 if (a == null || a.isZERO()) { 664 return ZERO; 665 } 666 if (nvar != 1) { 667 throw new IllegalArgumentException("no univariate polynomial ring"); 668 } 669 GenPolynomial<C> ret = copy(ZERO); 670 SortedMap<ExpVector, C> tm = ret.val; 671 long i = -1; 672 for (C m : a.val) { 673 i++; 674 if (m.isZERO()) { 675 continue; 676 } 677 ExpVector e = ExpVector.create(1, 0, i); 678 tm.put(e, m); 679 } 680 return ret; 681 } 682 683 684 /** 685 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 686 * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. 687 * @param n number of terms. 688 * @return a random polynomial. 689 */ 690 public GenPolynomial<C> random(int n) { 691 return random(n, random); 692 } 693 694 695 /** 696 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 697 * n, q = (nvar == 1) ? 0.5 : 0.3. 698 * @param n number of terms. 699 * @param rnd is a source for random bits. 700 * @return a random polynomial. 701 */ 702 public GenPolynomial<C> random(int n, Random rnd) { 703 if (nvar == 1) { 704 return random(3, n, n, 0.5f, rnd); 705 } 706 return random(3, n, n, 0.3f, rnd); 707 } 708 709 710 /** 711 * Generate a random polynomial. 712 * @param k bitsize of random coefficients. 713 * @param l number of terms. 714 * @param d maximal degree in each variable. 715 * @param q density of nozero exponents. 716 * @return a random polynomial. 717 */ 718 public GenPolynomial<C> random(int k, int l, int d, float q) { 719 return random(k, l, d, q, random); 720 } 721 722 723 /** 724 * Generate a random polynomial. 725 * @param k bitsize of random coefficients. 726 * @param l number of terms. 727 * @param d maximal degree in each variable. 728 * @param q density of nozero exponents. 729 * @param rnd is a source for random bits. 730 * @return a random polynomial. 731 */ 732 public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) { 733 GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 734 ExpVector e; 735 C a; 736 // add l random coeffs and exponents 737 for (int i = 0; i < l; i++) { 738 e = ExpVector.random(nvar, d, q, rnd); 739 a = coFac.random(k, rnd); 740 r = r.sum(a, e); // somewhat inefficient but clean 741 //System.out.println("e = " + e + " a = " + a); 742 } 743 // System.out.println("r = " + r); 744 return r; 745 } 746 747 748 /** 749 * Copy polynomial c. 750 * @param c 751 * @return a copy of c. 752 */ 753 public GenPolynomial<C> copy(GenPolynomial<C> c) { 754 //System.out.println("GP copy = " + this); 755 return new GenPolynomial<C>(this, c.val); 756 } 757 758 759 /** 760 * Copy polynomial list. 761 * @param L polynomial list 762 * @return a copy of L in this ring. 763 */ 764 public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) { 765 if (L == null) { 766 return L; 767 } 768 List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size()); 769 for (GenPolynomial<C> a : L) { 770 R.add(copy(a)); 771 } 772 return R; 773 } 774 775 776 /** 777 * Parse a polynomial with the use of GenPolynomialTokenizer. 778 * @param s String. 779 * @return GenPolynomial from s. 780 */ 781 public GenPolynomial<C> parse(String s) { 782 String val = s; 783 if (!s.contains("|")) { 784 val = val.replace("{", "").replace("}", ""); 785 } 786 return parse(new StringReader(val)); 787 } 788 789 790 /** 791 * Parse a polynomial with the use of GenPolynomialTokenizer. 792 * @param r Reader. 793 * @return next GenPolynomial from r. 794 */ 795 @SuppressWarnings({ "unchecked", "cast" }) 796 public GenPolynomial<C> parse(Reader r) { 797 GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); 798 GenPolynomial<C> p = null; 799 try { 800 p = (GenPolynomial<C>) pt.nextPolynomial(); 801 } catch (IOException e) { 802 logger.error("{} parse {}", e, this); 803 p = ZERO; 804 } 805 return p; 806 } 807 808 809 /** 810 * Generate univariate polynomial in a given variable with given exponent. 811 * @param x the name of a variable. 812 * @return x as univariate polynomial. 813 */ 814 public GenPolynomial<C> univariate(String x) { 815 return univariate(x, 1L); 816 } 817 818 819 /** 820 * Generate univariate polynomial in a given variable with given exponent. 821 * @param x the name of the variable. 822 * @param e the exponent of the variable. 823 * @return x^e as univariate polynomial. 824 */ 825 public GenPolynomial<C> univariate(String x, long e) { 826 if (vars == null) { // should not happen 827 throw new IllegalArgumentException("no variables defined for polynomial ring"); 828 } 829 if (x == null || x.isEmpty()) { 830 throw new IllegalArgumentException("no variable name given"); 831 } 832 int i; 833 for (i = 0; i < vars.length; i++) { 834 if (x.equals(vars[i])) { // use HashMap or TreeMap 835 break; 836 } 837 } 838 if (i >= vars.length) { 839 throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring"); 840 } 841 return univariate(0, nvar - i - 1, e); 842 } 843 844 845 /** 846 * Generate univariate polynomial in a given variable. 847 * @param i the index of the variable. 848 * @return X_i as univariate polynomial. 849 */ 850 public GenPolynomial<C> univariate(int i) { 851 return univariate(0, i, 1L); 852 } 853 854 855 /** 856 * Generate univariate polynomial in a given variable with given exponent. 857 * @param i the index of the variable. 858 * @param e the exponent of the variable. 859 * @return X_i^e as univariate polynomial. 860 */ 861 public GenPolynomial<C> univariate(int i, long e) { 862 return univariate(0, i, e); 863 } 864 865 866 /** 867 * Generate univariate polynomial in a given variable with given exponent. 868 * @param modv number of module variables. 869 * @param i the index of the variable. 870 * @param e the exponent of the variable. 871 * @return X_i^e as univariate polynomial. 872 */ 873 public GenPolynomial<C> univariate(int modv, int i, long e) { 874 GenPolynomial<C> p = getZERO(); 875 int r = nvar - modv; 876 if (0 <= i && i < r) { 877 C one = coFac.getONE(); 878 ExpVector f = ExpVector.create(r, i, e); 879 if (modv > 0) { 880 f = f.extend(modv, 0, 0l); 881 } 882 p = p.sum(one, f); 883 } 884 return p; 885 } 886 887 888 /** 889 * Get the generating elements excluding the generators for the coefficient 890 * ring. 891 * @return a list of generating elements for this ring. 892 */ 893 public List<GenPolynomial<C>> getGenerators() { 894 List<? extends GenPolynomial<C>> univs = univariateList(); 895 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1); 896 gens.add(getONE()); 897 gens.addAll(univs); 898 return gens; 899 } 900 901 902 /** 903 * Get a list of the generating elements. 904 * @return list of generators for the algebraic structure. 905 * @see edu.jas.structure.ElemFactory#generators() 906 */ 907 public List<GenPolynomial<C>> generators() { 908 List<? extends C> cogens = coFac.generators(); 909 List<? extends GenPolynomial<C>> univs = univariateList(); 910 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 911 for (C c : cogens) { 912 gens.add(getONE().multiply(c)); 913 } 914 gens.addAll(univs); 915 return gens; 916 } 917 918 919 /** 920 * Get a list of the generating elements excluding the module variables. 921 * @param modv number of module variables 922 * @return list of generators for the polynomial ring. 923 */ 924 public List<GenPolynomial<C>> generators(int modv) { 925 List<? extends C> cogens = coFac.generators(); 926 List<? extends GenPolynomial<C>> univs = univariateList(modv); 927 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 928 for (C c : cogens) { 929 gens.add(getONE().multiply(c)); 930 } 931 gens.addAll(univs); 932 return gens; 933 } 934 935 936 /** 937 * Is this structure finite or infinite. 938 * @return true if this structure is finite, else false. 939 * @see edu.jas.structure.ElemFactory#isFinite() 940 */ 941 public boolean isFinite() { 942 return (nvar == 0) && coFac.isFinite(); 943 } 944 945 946 /** 947 * Generate list of univariate polynomials in all variables. 948 * @return List(X_1,...,X_n) a list of univariate polynomials. 949 */ 950 public List<? extends GenPolynomial<C>> univariateList() { 951 return univariateList(0, 1L); 952 } 953 954 955 /** 956 * Generate list of univariate polynomials in all variables. 957 * @param modv number of module variables. 958 * @return List(X_1,...,X_n) a list of univariate polynomials. 959 */ 960 public List<? extends GenPolynomial<C>> univariateList(int modv) { 961 return univariateList(modv, 1L); 962 } 963 964 965 /** 966 * Generate list of univariate polynomials in all variables with given 967 * exponent. 968 * @param modv number of module variables. 969 * @param e the exponent of the variables. 970 * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. 971 */ 972 public List<? extends GenPolynomial<C>> univariateList(int modv, long e) { 973 List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar); 974 int nm = nvar - modv; 975 for (int i = 0; i < nm; i++) { 976 GenPolynomial<C> p = univariate(modv, nm - 1 - i, e); 977 pols.add(p); 978 } 979 return pols; 980 } 981 982 983 /** 984 * Extend variables. Used e.g. in module embedding. Extend number of 985 * variables by i. 986 * @param i number of variables to extend. 987 * @return extended polynomial ring factory. 988 */ 989 public GenPolynomialRing<C> extend(int i) { 990 return extend(i, false); 991 } 992 993 994 /** 995 * Extend variables. Used e.g. in module embedding. Extend number of 996 * variables by i. 997 * @param i number of variables to extend. 998 * @param top true for TOP term order, false for POT term order. 999 * @return extended polynomial ring factory. 1000 */ 1001 public GenPolynomialRing<C> extend(int i, boolean top) { 1002 // add module variable names 1003 String[] v = newVars("e", i); 1004 return extend(v, top); 1005 } 1006 1007 1008 /** 1009 * Extend variables. Used e.g. in module embedding. Extend number of 1010 * variables by length(vn). 1011 * @param vn names for extended variables. 1012 * @return extended polynomial ring factory. 1013 */ 1014 public GenPolynomialRing<C> extend(String[] vn) { 1015 return extend(vn, false); 1016 } 1017 1018 1019 /** 1020 * Extend variables. Used e.g. in module embedding. Extend number of 1021 * variables by length(vn). 1022 * @param vn names for extended variables. 1023 * @param top true for TOP term order, false for POT term order. 1024 * @return extended polynomial ring factory. 1025 */ 1026 public GenPolynomialRing<C> extend(String[] vn, boolean top) { 1027 if (vn == null || vars == null) { 1028 throw new IllegalArgumentException("vn and vars may not be null"); 1029 } 1030 int i = vn.length; 1031 String[] v = new String[vars.length + i]; 1032 for (int k = 0; k < vars.length; k++) { 1033 v[k] = vars[k]; 1034 } 1035 for (int k = 0; k < vn.length; k++) { 1036 v[vars.length + k] = vn[k]; 1037 } 1038 TermOrder to = tord.extend(nvar, i, top); 1039 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1040 return pfac; 1041 } 1042 1043 1044 /** 1045 * Extend lower variables. Extend number of variables by i. 1046 * @param i number of variables to extend. 1047 * @return extended polynomial ring factory. 1048 */ 1049 public GenPolynomialRing<C> extendLower(int i) { 1050 String[] v = newVars("e", i); 1051 return extendLower(v); 1052 } 1053 1054 1055 /** 1056 * Extend lower variables. Extend number of variables by length(vn). 1057 * @param vn names for extended lower variables. 1058 * @return extended polynomial ring factory. 1059 */ 1060 public GenPolynomialRing<C> extendLower(String[] vn) { 1061 return extendLower(vn, false); 1062 } 1063 1064 1065 /** 1066 * Extend lower variables. Extend number of variables by length(vn). 1067 * @param vn names for extended lower variables. 1068 * @param top true for TOP term order, false for POT term order. 1069 * @return extended polynomial ring factory. 1070 */ 1071 public GenPolynomialRing<C> extendLower(String[] vn, boolean top) { 1072 if (vn == null || vars == null) { 1073 throw new IllegalArgumentException("vn and vars may not be null"); 1074 } 1075 int i = vn.length; 1076 String[] v = new String[vars.length + i]; 1077 for (int k = 0; k < vn.length; k++) { 1078 v[k] = vn[k]; 1079 } 1080 for (int k = 0; k < vars.length; k++) { 1081 v[vn.length + k] = vars[k]; 1082 } 1083 TermOrder to = tord.extendLower(nvar, i, top); 1084 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1085 return pfac; 1086 } 1087 1088 1089 /** 1090 * Contract variables. Used e.g. in module embedding. Contract number of 1091 * variables by i. 1092 * @param i number of variables to remove. 1093 * @return contracted polynomial ring factory. 1094 */ 1095 public GenPolynomialRing<C> contract(int i) { 1096 String[] v = null; 1097 if (vars != null) { 1098 v = new String[vars.length - i]; 1099 for (int j = 0; j < vars.length - i; j++) { 1100 v[j] = vars[j]; 1101 } 1102 } 1103 TermOrder to = tord.contract(i, nvar - i); 1104 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v); 1105 return pfac; 1106 } 1107 1108 1109 /** 1110 * Recursive representation as polynomial with i main variables. 1111 * @param i number of main variables. 1112 * @return recursive polynomial ring factory. 1113 */ 1114 public GenPolynomialRing<GenPolynomial<C>> recursive(int i) { 1115 if (i <= 0 || i >= nvar) { 1116 throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar); 1117 } 1118 GenPolynomialRing<C> cfac = contract(i); 1119 String[] v = null; 1120 if (vars != null) { 1121 v = new String[i]; 1122 int k = 0; 1123 for (int j = nvar - i; j < nvar; j++) { 1124 v[k++] = vars[j]; 1125 } 1126 } 1127 TermOrder to = tord.contract(0, i); // ?? 1128 GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v); 1129 return pfac; 1130 } 1131 1132 1133 /** 1134 * Distributive representation as polynomial with all main variables. 1135 * @return distributive polynomial ring factory. 1136 */ 1137 @SuppressWarnings("unchecked") 1138 public GenPolynomialRing<C> distribute() { 1139 if (!(coFac instanceof GenPolynomialRing)) { 1140 return this; 1141 } 1142 RingFactory cf = coFac; 1143 RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf; 1144 GenPolynomialRing cr = (GenPolynomialRing) cfp; 1145 GenPolynomialRing<C> pfac; 1146 if (cr.vars != null) { 1147 pfac = extend(cr.vars); 1148 } else { 1149 pfac = extend(cr.nvar); 1150 } 1151 return pfac; 1152 } 1153 1154 1155 /** 1156 * Reverse variables. Used e.g. in opposite rings. 1157 * @return polynomial ring factory with reversed variables. 1158 */ 1159 public GenPolynomialRing<C> reverse() { 1160 return reverse(false); 1161 } 1162 1163 1164 /** 1165 * Reverse variables. Used e.g. in opposite rings. 1166 * @param partial true for partially reversed term orders. 1167 * @return polynomial ring factory with reversed variables. 1168 */ 1169 public GenPolynomialRing<C> reverse(boolean partial) { 1170 String[] v = null; 1171 if (vars != null) { // vars are not inversed 1172 v = new String[vars.length]; 1173 int k = tord.getSplit(); 1174 if (partial && k < vars.length) { 1175 // copy upper 1176 for (int j = 0; j < k; j++) { 1177 //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper 1178 v[vars.length - k + j] = vars[vars.length - k + j]; 1179 } 1180 // reverse lower 1181 for (int j = 0; j < vars.length - k; j++) { 1182 //v[j] = vars[j]; // copy upper 1183 v[j] = vars[vars.length - k - j - 1]; 1184 } 1185 } else { 1186 for (int j = 0; j < vars.length; j++) { 1187 v[j] = vars[vars.length - 1 - j]; 1188 } 1189 } 1190 //System.out.println("vars = " + Arrays.toString(vars)); 1191 //System.out.println("v = " + Arrays.toString(v)); 1192 } 1193 TermOrder to = tord.reverse(partial); 1194 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v); 1195 pfac.partial = partial; 1196 return pfac; 1197 } 1198 1199 1200 /** 1201 * Get PolynomialComparator. 1202 * @return polynomial comparator. 1203 */ 1204 public PolynomialComparator<C> getComparator() { 1205 return new PolynomialComparator<C>(tord, false); 1206 } 1207 1208 1209 /** 1210 * Get PolynomialComparator. 1211 * @param rev for reverse comparator. 1212 * @return polynomial comparator. 1213 */ 1214 public PolynomialComparator<C> getComparator(boolean rev) { 1215 return new PolynomialComparator<C>(tord, rev); 1216 } 1217 1218 1219 /** 1220 * New variable names. Generate new names for variables, 1221 * @param prefix name prefix. 1222 * @param n number of variables. 1223 * @return new variable names. 1224 */ 1225 public static String[] newVars(String prefix, int n) { 1226 String[] vars = new String[n]; 1227 for (int i = 0; i < n; i++) { 1228 long m = varCounter.getAndIncrement(); 1229 vars[i] = prefix + m; 1230 } 1231 return vars; 1232 } 1233 1234 1235 /** 1236 * New variable names. Generate new names for variables, 1237 * @param prefix name prefix. 1238 * @return new variable names. 1239 */ 1240 public String[] newVars(String prefix) { 1241 return newVars(prefix, nvar); 1242 } 1243 1244 1245 /** 1246 * New variable names. Generate new names for variables, 1247 * @param n number of variables. 1248 * @return new variable names. 1249 */ 1250 public static String[] newVars(int n) { 1251 return newVars("x", n); 1252 } 1253 1254 1255 /** 1256 * New variable names. Generate new names for variables, 1257 * @return new variable names. 1258 */ 1259 public String[] newVars() { 1260 return newVars(nvar); 1261 } 1262 1263 1264 /* 1265 * Add variable names. 1266 * @param vars variable names to be recorded. 1267 public static void addVars(String[] vars) { 1268 if (vars == null) { 1269 return; 1270 } 1271 // synchronized (knownVars) { 1272 // for (int i = 0; i < vars.length; i++) { 1273 // knownVars.add(vars[i]); // eventually names 'overwritten' 1274 // } 1275 // } 1276 } 1277 */ 1278 1279 1280 /** 1281 * Permute variable names. 1282 * @param vars variable names. 1283 * @param P permutation. 1284 * @return P(vars). 1285 */ 1286 public static String[] permuteVars(List<Integer> P, String[] vars) { 1287 if (vars == null || vars.length <= 1) { 1288 return vars; 1289 } 1290 String[] b = new String[vars.length]; 1291 int j = 0; 1292 for (Integer i : P) { 1293 b[j++] = vars[i]; 1294 } 1295 return b; 1296 } 1297 1298 1299 /** 1300 * Permutation of polynomial ring variables. 1301 * @param P permutation. 1302 * @return P(this). 1303 */ 1304 public GenPolynomialRing<C> permutation(List<Integer> P) { 1305 if (nvar <= 1) { 1306 return this; 1307 } 1308 TermOrder tp = tord.permutation(P); 1309 if (vars == null) { 1310 return new GenPolynomialRing<C>(coFac, nvar, tp); 1311 } 1312 String[] v1 = new String[vars.length]; 1313 for (int i = 0; i < v1.length; i++) { 1314 v1[i] = vars[v1.length - 1 - i]; 1315 } 1316 String[] vp = permuteVars(P, v1); 1317 String[] v2 = new String[vp.length]; 1318 for (int i = 0; i < vp.length; i++) { 1319 v2[i] = vp[vp.length - 1 - i]; 1320 } 1321 return new GenPolynomialRing<C>(coFac, nvar, tp, v2); 1322 } 1323 1324 1325 /** 1326 * Characteristic polynomial of matrix. 1327 * <b>Note:</b> using Faddeev–LeVerrier algorithm 1328 * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm 1329 * @param A a square matrix. 1330 * @return characteristic polynomial of A. 1331 */ 1332 public GenPolynomial<C> charPolynomial(GenMatrix<C> A) { 1333 if (A == null || A.isZERO()) { 1334 return ZERO; 1335 } 1336 if (nvar != 1) { 1337 throw new IllegalArgumentException("no univariate polynomial ring"); 1338 } 1339 GenMatrixRing<C> mfac = A.ring; 1340 int n = mfac.rows; 1341 java.math.BigInteger c0 = coFac.characteristic(); 1342 if (c0.signum() > 0 && c0.compareTo(java.math.BigInteger.valueOf(n)) <= 0) { 1343 throw new UnsupportedOperationException("characteristic <= n: " + c0 + " <= " + n); 1344 } 1345 GenPolynomial<C> ret = copy(ZERO); 1346 //SortedMap<ExpVector, C> tm = ret.val; 1347 GenMatrix<C> M = mfac.getZERO(); //new GenMatrix<C>(A.ring); 1348 GenMatrix<C> I = mfac.getONE(); 1349 ExpVector e = ExpVector.create(1, 0, n); 1350 C one = coFac.getONE(); 1351 ret = ret.sum(one, e); 1352 C c = coFac.getONE(); 1353 GenMatrix<C> Ms = null; 1354 GenMatrix<C> Mp = null, Mc; 1355 // M_0 = 0, c_n = 1 1356 // k = 1..n: M_k = A*M_{k-1} + c_{n-k+1}*I, c_{n-k} = -1/k*trace(A*M_k) 1357 for (int k = 1; k <= n; k++) { 1358 if (Ms == null) { 1359 Mp = A.multiply(M); // reuse A*Mp? todo 1360 } else { 1361 Mp = Ms; 1362 } 1363 Mc = I.multiply(c); 1364 Mp = Mp.sum(Mc); 1365 Ms = A.multiply(Mp); 1366 C cp = Ms.trace(); 1367 C ki = coFac.fromInteger(k).inverse(); // characteristic != k 1368 cp = cp.multiply(ki).negate(); 1369 M = Mp; 1370 c = cp; 1371 e = ExpVector.create(1, 0, n-k); 1372 ret = ret.sum(c, e); 1373 //System.out.println("k = " + k + ", c = " + c + ", M = " + M); 1374 } 1375 // only for demonstrating how to get the determinant, trace and inverse: 1376 // C det = coFac.getZERO(); //ret.trailingBaseCoefficient(); 1377 // //System.out.println("n = " + n + ", deg = " + ret.degree()); 1378 // if (n % 2 != 0) { 1379 // det = det.negate(); 1380 // } 1381 // if (! det.isZERO()) { 1382 // C d = det.inverse(); 1383 // if ((n-1) % 2 != 0) { 1384 // d = d.negate(); 1385 // } 1386 // Mc = Mp.multiply(d); 1387 // } else { 1388 // Mc = null; 1389 // } 1390 // //System.out.println("det = " + det + ", trace = " + c + ", A^{-1} = " + Mc); 1391 return ret; 1392 } 1393 1394 1395 /** 1396 * Determinant of matrix from characteristic polynomial. 1397 * <b>Note:</b> using Faddeev–LeVerrier algorithm 1398 * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm 1399 * @param P characteristic polynomial of a matrix. 1400 * @return determinant from characteristic polynomial. 1401 */ 1402 public C determinantFromCharPol(GenPolynomial<C> P) { 1403 C det = coFac.getZERO(); 1404 if (P == null || P.isZERO()) { 1405 return det; 1406 } 1407 det = P.trailingBaseCoefficient(); 1408 if (P.degree() % 2 != 0) { 1409 det = det.negate(); 1410 } 1411 return det; 1412 } 1413 1414 1415 /** 1416 * Determinant of matrix via characteristic polynomial. 1417 * <b>Note:</b> using Faddeev–LeVerrier algorithm 1418 * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm 1419 * @param A square matrix. 1420 * @return determinant of A from characteristic polynomial of A. 1421 */ 1422 public C determinant(GenMatrix<C> A) { 1423 GenPolynomial<C> P = charPolynomial(A); 1424 return determinantFromCharPol(P); 1425 } 1426 1427 1428 /** 1429 * Trace of matrix from characteristic polynomial. 1430 * @param P characteristic polynomial of a matrix. 1431 * @return trace from characteristic polynomial. 1432 */ 1433 public C traceFromCharPol(GenPolynomial<C> P) { 1434 if (P == null || P.isZERO()) { 1435 return coFac.getZERO(); 1436 } 1437 long n = P.degree(); 1438 ExpVector e = ExpVector.create(1, 0, n-1); 1439 C t = P.coefficient(e).negate(); 1440 return t; 1441 } 1442 1443 1444 /** 1445 * Get a GenPolynomial iterator. 1446 * @return an iterator over all polynomials. 1447 */ 1448 public Iterator<GenPolynomial<C>> iterator() { 1449 if (coFac.isFinite()) { 1450 return new GenPolynomialIterator<C>(this); 1451 } 1452 logger.warn("ring of coefficients {} is infinite, constructing iterator only over monomials", coFac); 1453 return new GenPolynomialMonomialIterator<C>(this); 1454 //throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1455 } 1456 1457} 1458 1459 1460/** 1461 * Polynomial iterator. 1462 * @author Heinz Kredel 1463 */ 1464class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1465 1466 1467 /** 1468 * data structure. 1469 */ 1470 final GenPolynomialRing<C> ring; 1471 1472 1473 final Iterator<List<Long>> eviter; 1474 1475 1476 final List<ExpVector> powers; 1477 1478 1479 final List<Iterable<C>> coeffiter; 1480 1481 1482 Iterator<List<C>> itercoeff; 1483 1484 1485 GenPolynomial<C> current; 1486 1487 1488 /** 1489 * Polynomial iterator constructor. 1490 */ 1491 @SuppressWarnings("unchecked") 1492 public GenPolynomialIterator(GenPolynomialRing<C> fac) { 1493 ring = fac; 1494 LongIterable li = new LongIterable(); 1495 li.setNonNegativeIterator(); 1496 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1497 for (int i = 0; i < ring.nvar; i++) { 1498 tlist.add(li); 1499 } 1500 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1501 eviter = ei.iterator(); 1502 RingFactory<C> cf = ring.coFac; 1503 coeffiter = new ArrayList<Iterable<C>>(); 1504 if (cf instanceof Iterable && cf.isFinite()) { 1505 Iterable<C> cfi = (Iterable<C>) cf; 1506 coeffiter.add(cfi); 1507 } else { 1508 throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1509 } 1510 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1511 itercoeff = tuples.iterator(); 1512 powers = new ArrayList<ExpVector>(); 1513 ExpVector e = ExpVector.create(eviter.next()); 1514 powers.add(e); 1515 //System.out.println("new e = " + e); 1516 //System.out.println("powers = " + powers); 1517 List<C> c = itercoeff.next(); 1518 //System.out.println("coeffs = " + c); 1519 current = new GenPolynomial<C>(ring, c.get(0), e); 1520 } 1521 1522 1523 /** 1524 * Test for availability of a next element. 1525 * @return true if the iteration has more elements, else false. 1526 */ 1527 public boolean hasNext() { 1528 return true; 1529 } 1530 1531 1532 /** 1533 * Get next polynomial. 1534 * @return next polynomial. 1535 */ 1536 public synchronized GenPolynomial<C> next() { 1537 GenPolynomial<C> res = current; 1538 if (!itercoeff.hasNext()) { 1539 ExpVector e = ExpVector.create(eviter.next()); 1540 powers.add(0, e); // add new ev at beginning 1541 //System.out.println("new e = " + e); 1542 //System.out.println("powers = " + powers); 1543 if (coeffiter.size() == 1) { // shorten first iterator by one element 1544 coeffiter.add(coeffiter.get(0)); 1545 Iterable<C> it = coeffiter.get(0); 1546 List<C> elms = new ArrayList<C>(); 1547 for (C elm : it) { 1548 elms.add(elm); 1549 } 1550 elms.remove(0); 1551 coeffiter.set(0, elms); 1552 } else { 1553 coeffiter.add(coeffiter.get(1)); 1554 } 1555 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1556 itercoeff = tuples.iterator(); 1557 } 1558 List<C> coeffs = itercoeff.next(); 1559 // while ( coeffs.get(0).isZERO() ) { 1560 // System.out.println(" skip zero "); 1561 // coeffs = itercoeff.next(); // skip tuples with zero in first component 1562 // } 1563 //System.out.println("coeffs = " + coeffs); 1564 GenPolynomial<C> pol = ring.getZERO().copy(); 1565 int i = 0; 1566 for (ExpVector f : powers) { 1567 C c = coeffs.get(i++); 1568 if (c.isZERO()) { 1569 continue; 1570 } 1571 if (pol.val.get(f) != null) { 1572 System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f)); 1573 throw new RuntimeException("error in iterator"); 1574 } 1575 pol.doPutToMap(f, c); 1576 } 1577 current = pol; 1578 return res; 1579 } 1580 1581 1582 /** 1583 * Remove an element if allowed. 1584 */ 1585 public void remove() { 1586 throw new UnsupportedOperationException("cannot remove elements"); 1587 } 1588} 1589 1590 1591/** 1592 * Polynomial monomial iterator. 1593 * @author Heinz Kredel 1594 */ 1595class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1596 1597 1598 /** 1599 * data structure. 1600 */ 1601 final GenPolynomialRing<C> ring; 1602 1603 1604 final Iterator<List> iter; 1605 1606 1607 GenPolynomial<C> current; 1608 1609 1610 /** 1611 * Polynomial iterator constructor. 1612 */ 1613 @SuppressWarnings("unchecked") 1614 public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) { 1615 ring = fac; 1616 LongIterable li = new LongIterable(); 1617 li.setNonNegativeIterator(); 1618 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1619 for (int i = 0; i < ring.nvar; i++) { 1620 tlist.add(li); 1621 } 1622 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1623 //Iterator<List<Long>> eviter = ei.iterator(); 1624 1625 RingFactory<C> cf = ring.coFac; 1626 Iterable<C> coeffiter; 1627 if (cf instanceof Iterable && !cf.isFinite()) { 1628 Iterable<C> cfi = (Iterable<C>) cf; 1629 coeffiter = cfi; 1630 } else { 1631 throw new IllegalArgumentException("only for infinite iterable coefficients implemented"); 1632 } 1633 1634 // Cantor iterator for exponents and coefficients 1635 List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter 1636 eci.add(ei); 1637 eci.add(coeffiter); 1638 CartesianProductInfinite ecp = new CartesianProductInfinite(eci); 1639 iter = ecp.iterator(); 1640 1641 List ec = iter.next(); 1642 List<Long> ecl = (List<Long>) ec.get(0); 1643 C c = (C) ec.get(1); // zero 1644 ExpVector e = ExpVector.create(ecl); 1645 //System.out.println("exp = " + e); 1646 //System.out.println("coeffs = " + c); 1647 current = new GenPolynomial<C>(ring, c, e); 1648 } 1649 1650 1651 /** 1652 * Test for availability of a next element. 1653 * @return true if the iteration has more elements, else false. 1654 */ 1655 public boolean hasNext() { 1656 return true; 1657 } 1658 1659 1660 /** 1661 * Get next polynomial. 1662 * @return next polynomial. 1663 */ 1664 @SuppressWarnings("unchecked") 1665 public synchronized GenPolynomial<C> next() { 1666 GenPolynomial<C> res = current; 1667 1668 List ec = iter.next(); 1669 C c = (C) ec.get(1); 1670 while (c.isZERO()) { // zero already done in first next 1671 ec = iter.next(); 1672 c = (C) ec.get(1); 1673 } 1674 List<Long> ecl = (List<Long>) ec.get(0); 1675 ExpVector e = ExpVector.create(ecl); 1676 //System.out.println("exp = " + e); 1677 //System.out.println("coeffs = " + c); 1678 current = new GenPolynomial<C>(ring, c, e); 1679 1680 return res; 1681 } 1682 1683 1684 /** 1685 * Remove an element if allowed. 1686 */ 1687 public void remove() { 1688 throw new UnsupportedOperationException("cannot remove elements"); 1689 } 1690}