001/* 002 * $Id: GenPolynomial.java 5918 2018-08-29 20:32:55Z kredel $ 003 */ 004 005package edu.jas.poly; 006 007 008import java.io.IOException; 009import java.lang.reflect.InvocationTargetException; 010import java.lang.reflect.Method; 011import java.util.ArrayList; 012import java.util.Collections; 013import java.util.Iterator; 014import java.util.List; 015import java.util.Map; 016import java.util.SortedMap; 017import java.util.TreeMap; 018 019import org.apache.logging.log4j.Logger; 020import org.apache.logging.log4j.LogManager; 021 022import edu.jas.kern.PreemptingException; 023import edu.jas.kern.PrettyPrint; 024import edu.jas.structure.NotInvertibleException; 025import edu.jas.structure.RingElem; 026import edu.jas.structure.UnaryFunctor; 027 028 029/** 030 * GenPolynomial generic polynomials implementing RingElem. n-variate 031 * ordered polynomials over coefficients C. The variables commute with each other 032 * and with the coefficients. For non-commutative coefficients some 033 * care is taken to respect the multiplication order. 034 * 035 * Objects of this class are intended to be immutable. The 036 * implementation is based on TreeMap respectively SortedMap from 037 * exponents to coefficients. Only the coefficients are modeled with 038 * generic types, the exponents are fixed to ExpVector with long 039 * entries (this will eventually be changed in the future). C can also 040 * be a non integral domain, e.g. a ModInteger, i.e. it may contain 041 * zero divisors, since multiply() does check for zeros. <b>Note:</b> 042 * multiply() now checks for wrong method dispatch for 043 * GenSolvablePolynomial. 044 * @param <C> coefficient type 045 * @author Heinz Kredel 046 */ 047public class GenPolynomial<C extends RingElem<C>> 048 implements RingElem<GenPolynomial<C>>, /* not yet Polynomial<C> */ 049 Iterable<Monomial<C>> { 050 051 052 /** 053 * The factory for the polynomial ring. 054 */ 055 public final GenPolynomialRing<C> ring; 056 057 058 /** 059 * The data structure for polynomials. 060 */ 061 protected final SortedMap<ExpVector, C> val; // do not change to TreeMap 062 063 064 /** 065 * Stored hash code. 066 */ 067 transient protected int hash = -1; 068 069 070 /** 071 * Stored bitLength. 072 */ 073 transient protected long blen = -1; 074 075 076 private static final Logger logger = LogManager.getLogger(GenPolynomial.class); 077 078 079 private static final boolean debug = logger.isDebugEnabled(); 080 081 082 // protected GenPolynomial() { ring = null; val = null; } // don't use 083 084 085 /** 086 * Private constructor for GenPolynomial. 087 * @param r polynomial ring factory. 088 * @param t TreeMap with correct ordering. 089 */ 090 private GenPolynomial(GenPolynomialRing<C> r, TreeMap<ExpVector, C> t) { 091 ring = r; 092 val = t; 093 if (ring.checkPreempt) { 094 if (Thread.currentThread().isInterrupted()) { 095 logger.debug("throw PreemptingException"); 096 throw new PreemptingException(); 097 } 098 } 099 } 100 101 102 /** 103 * Constructor for zero GenPolynomial. 104 * @param r polynomial ring factory. 105 */ 106 public GenPolynomial(GenPolynomialRing<C> r) { 107 this(r, new TreeMap<ExpVector, C>(r.tord.getDescendComparator())); 108 } 109 110 111 /** 112 * Constructor for GenPolynomial c * x<sup>e</sup>. 113 * @param r polynomial ring factory. 114 * @param c coefficient. 115 * @param e exponent. 116 */ 117 public GenPolynomial(GenPolynomialRing<C> r, C c, ExpVector e) { 118 this(r); 119 if (!c.isZERO()) { 120 val.put(e, c); 121 } 122 } 123 124 125 /** 126 * Constructor for GenPolynomial c * x<sup>0</sup>. 127 * @param r polynomial ring factory. 128 * @param c coefficient. 129 */ 130 public GenPolynomial(GenPolynomialRing<C> r, C c) { 131 this(r, c, r.evzero); 132 } 133 134 135 /** 136 * Constructor for GenPolynomial x<sup>e</sup>. 137 * @param r polynomial ring factory. 138 * @param e exponent. 139 */ 140 public GenPolynomial(GenPolynomialRing<C> r, ExpVector e) { 141 this(r, r.coFac.getONE(), e); 142 } 143 144 145 /** 146 * Constructor for GenPolynomial. 147 * @param r polynomial ring factory. 148 * @param v the SortedMap of some other polynomial. 149 */ 150 protected GenPolynomial(GenPolynomialRing<C> r, SortedMap<ExpVector, C> v) { 151 this(r); 152 if (v.size() > 0) { 153 GenPolynomialRing.creations++; 154 val.putAll(v); // assume no zero coefficients and val is empty 155 } 156 } 157 158 159 /** 160 * Get the corresponding element factory. 161 * @return factory for this Element. 162 * @see edu.jas.structure.Element#factory() 163 */ 164 public GenPolynomialRing<C> factory() { 165 return ring; 166 } 167 168 169 /** 170 * Copy this GenPolynomial. 171 * @return copy of this. 172 */ 173 public GenPolynomial<C> copy() { 174 return new GenPolynomial<C>(ring, this.val); 175 } 176 177 178 /** 179 * Length of GenPolynomial. 180 * @return number of coefficients of this GenPolynomial. 181 */ 182 public int length() { 183 return val.size(); 184 } 185 186 187 /** 188 * ExpVector to coefficient map of GenPolynomial. 189 * @return val as unmodifiable SortedMap. 190 */ 191 public SortedMap<ExpVector, C> getMap() { 192 // return val; 193 return Collections.<ExpVector, C> unmodifiableSortedMap(val); 194 } 195 196 197 /** 198 * Put an ExpVector to coefficient entry into the internal map of this 199 * GenPolynomial. <b>Note:</b> Do not use this method unless you are 200 * constructing a new polynomial. this is modified and breaks the 201 * immutability promise of this class. 202 * @param c coefficient. 203 * @param e exponent. 204 */ 205 public void doPutToMap(ExpVector e, C c) { 206 if (debug) { 207 C a = val.get(e); 208 if (a != null) { 209 logger.error("map entry exists " + e + " to " + a + " new " + c); 210 } 211 hash = -1; 212 blen = -1; 213 } 214 if (!c.isZERO()) { 215 val.put(e, c); 216 } 217 } 218 219 220 /** 221 * Remove an ExpVector to coefficient entry from the internal map of this 222 * GenPolynomial. <b>Note:</b> Do not use this method unless you are 223 * constructing a new polynomial. this is modified and breaks the 224 * immutability promise of this class. 225 * @param e exponent. 226 * @param c expected coefficient, null for ignore. 227 */ 228 public void doRemoveFromMap(ExpVector e, C c) { 229 C b = val.remove(e); 230 if (true) { //||debug 231 hash = -1; 232 blen = -1; 233 if (c == null) { // ignore b 234 return; 235 } 236 if (!c.equals(b)) { 237 logger.error("map entry wrong " + e + " to " + c + " old " + b); 238 throw new RuntimeException("c != b"); 239 } 240 } 241 } 242 243 244 /** 245 * Put an a sorted map of exponents to coefficients into the internal map of 246 * this GenPolynomial. <b>Note:</b> Do not use this method unless you are 247 * constructing a new polynomial. this is modified and breaks the 248 * immutability promise of this class. 249 * @param vals sorted map of exponents and coefficients. 250 */ 251 public void doPutToMap(SortedMap<ExpVector, C> vals) { 252 for (Map.Entry<ExpVector, C> me : vals.entrySet()) { 253 ExpVector e = me.getKey(); 254 if (debug) { 255 C a = val.get(e); 256 if (a != null) { 257 logger.error("map entry exists " + e + " to " + a + " new " + me.getValue()); 258 } 259 hash = -1; 260 blen = -1; 261 } 262 C c = me.getValue(); 263 if (!c.isZERO()) { 264 val.put(e, c); 265 } 266 } 267 } 268 269 270 /** 271 * String representation of GenPolynomial. 272 * @see java.lang.Object#toString() 273 */ 274 @Override 275 public String toString() { 276 if (ring.vars != null) { 277 return toString(ring.vars); 278 } 279 StringBuffer s = new StringBuffer(); 280 s.append(this.getClass().getSimpleName() + ":"); 281 s.append(ring.coFac.getClass().getSimpleName()); 282 if (ring.coFac.characteristic().signum() != 0) { 283 s.append("(" + ring.coFac.characteristic() + ")"); 284 } 285 s.append("[ "); 286 boolean first = true; 287 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 288 if (first) { 289 first = false; 290 } else { 291 s.append(", "); 292 } 293 s.append(m.getValue().toString()); 294 s.append(" "); 295 s.append(m.getKey().toString()); 296 } 297 s.append(" ] "); // no not use: ring.toString() ); 298 return s.toString(); 299 } 300 301 302 /** 303 * String representation of GenPolynomial. 304 * @param v names for variables. 305 * @see java.lang.Object#toString() 306 */ 307 public String toString(String[] v) { 308 StringBuffer s = new StringBuffer(); 309 if (PrettyPrint.isTrue()) { 310 if (val.isEmpty()) { 311 s.append("0"); 312 } else { 313 // s.append( "( " ); 314 boolean first = true; 315 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 316 C c = m.getValue(); 317 if (first) { 318 first = false; 319 } else { 320 if (c.signum() < 0) { 321 s.append(" - "); 322 c = c.negate(); 323 } else { 324 s.append(" + "); 325 } 326 } 327 ExpVector e = m.getKey(); 328 if (!c.isONE() || e.isZERO()) { 329 String cs = c.toString(); 330 //if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { 331 if (cs.indexOf("-") >= 0 || cs.indexOf("+") >= 0) { 332 s.append("( "); 333 s.append(cs); 334 s.append(" )"); 335 } else { 336 s.append(cs); 337 } 338 s.append(" "); 339 } 340 if (e != null && v != null) { 341 s.append(e.toString(v)); 342 } else { 343 s.append(e); 344 } 345 } 346 //s.append(" )"); 347 } 348 } else { 349 s.append(this.getClass().getSimpleName() + "[ "); 350 if (val.isEmpty()) { 351 s.append("0"); 352 } else { 353 boolean first = true; 354 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 355 C c = m.getValue(); 356 if (first) { 357 first = false; 358 } else { 359 if (c.signum() < 0) { 360 s.append(" - "); 361 c = c.negate(); 362 } else { 363 s.append(" + "); 364 } 365 } 366 ExpVector e = m.getKey(); 367 if (!c.isONE() || e.isZERO()) { 368 s.append(c.toString()); 369 s.append(" "); 370 } 371 s.append(e.toString(v)); 372 } 373 } 374 s.append(" ] "); // no not use: ring.toString() ); 375 } 376 return s.toString(); 377 } 378 379 380 /** 381 * Get a scripting compatible string representation. 382 * @return script compatible representation for this Element. 383 * @see edu.jas.structure.Element#toScript() 384 */ 385 @Override 386 public String toScript() { 387 // Python case 388 if (isZERO()) { 389 return "0"; 390 } 391 StringBuffer s = new StringBuffer(); 392 if (val.size() > 1) { 393 s.append("( "); 394 } 395 String[] v = ring.vars; 396 if (v == null) { 397 v = GenPolynomialRing.newVars("x", ring.nvar); 398 } 399 boolean first = true; 400 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 401 C c = m.getValue(); 402 if (first) { 403 first = false; 404 } else { 405 if (c.signum() < 0) { 406 s.append(" - "); 407 c = c.negate(); 408 } else { 409 s.append(" + "); 410 } 411 } 412 ExpVector e = m.getKey(); 413 String cs = c.toScript(); 414 boolean parenthesis = (cs.indexOf("-") >= 0 || cs.indexOf("+") >= 0); 415 if (!c.isONE() || e.isZERO()) { 416 if (parenthesis) { 417 s.append("( "); 418 } 419 s.append(cs); 420 if (parenthesis) { 421 s.append(" )"); 422 } 423 if (!e.isZERO()) { 424 s.append(" * "); 425 } 426 } 427 s.append(e.toScript(v)); 428 } 429 if (val.size() > 1) { 430 s.append(" )"); 431 } 432 return s.toString(); 433 } 434 435 436 /** 437 * Get a scripting compatible string representation of the factory. 438 * @return script compatible representation for this ElemFactory. 439 * @see edu.jas.structure.Element#toScriptFactory() 440 */ 441 @Override 442 public String toScriptFactory() { 443 // Python case 444 return factory().toScript(); 445 } 446 447 448 /** 449 * Is GenPolynomial<C> zero. 450 * @return If this is 0 then true is returned, else false. 451 * @see edu.jas.structure.RingElem#isZERO() 452 */ 453 public boolean isZERO() { 454 return val.isEmpty(); 455 } 456 457 458 /** 459 * Is GenPolynomial<C> one. 460 * @return If this is 1 then true is returned, else false. 461 * @see edu.jas.structure.RingElem#isONE() 462 */ 463 public boolean isONE() { 464 if (val.size() != 1) { 465 return false; 466 } 467 C c = val.get(ring.evzero); 468 if (c == null) { 469 return false; 470 } 471 return c.isONE(); 472 } 473 474 475 /** 476 * Is GenPolynomial<C> a unit. 477 * @return If this is a unit then true is returned, else false. 478 * @see edu.jas.structure.RingElem#isUnit() 479 */ 480 public boolean isUnit() { 481 if (val.size() != 1) { 482 return false; 483 } 484 C c = val.get(ring.evzero); 485 if (c == null) { 486 return false; 487 } 488 return c.isUnit(); 489 } 490 491 492 /** 493 * Is GenPolynomial<C> a constant. 494 * @return If this is a constant polynomial then true is returned, else 495 * false. 496 */ 497 public boolean isConstant() { 498 if (val.size() != 1) { 499 return false; 500 } 501 C c = val.get(ring.evzero); 502 if (c == null) { 503 return false; 504 } 505 return true; 506 } 507 508 509 /** 510 * Is GenPolynomial<C> homogeneous. 511 * @return true, if this is homogeneous, else false. 512 */ 513 public boolean isHomogeneous() { 514 if (val.size() <= 1) { 515 return true; 516 } 517 long deg = -1; 518 for (ExpVector e : val.keySet()) { 519 if (deg < 0) { 520 deg = e.totalDeg(); 521 } else if (deg != e.totalDeg()) { 522 return false; 523 } 524 } 525 return true; 526 } 527 528 529 /** 530 * Comparison with any other object. 531 * @see java.lang.Object#equals(java.lang.Object) 532 */ 533 @Override 534 @SuppressWarnings("unchecked") 535 public boolean equals(Object B) { 536 if (B == null) { 537 return false; 538 } 539 if (!(B instanceof GenPolynomial)) { 540 return false; 541 } 542 GenPolynomial<C> a = (GenPolynomial<C>) B; 543 return this.compareTo(a) == 0; 544 } 545 546 547 /** 548 * Hash code for this polynomial. 549 * @see java.lang.Object#hashCode() 550 */ 551 @Override 552 public int hashCode() { 553 int h = hash; 554 if (h < 0) { 555 h = (ring.hashCode() << 27); 556 h += val.hashCode(); 557 hash = h; 558 } 559 return h; 560 } 561 562 563 /** 564 * GenPolynomial comparison. 565 * @param b GenPolynomial. 566 * @return sign(this-b). 567 */ 568 public int compareTo(GenPolynomial<C> b) { 569 if (b == null) { 570 return 1; 571 } 572 SortedMap<ExpVector, C> av = this.val; 573 SortedMap<ExpVector, C> bv = b.val; 574 Iterator<Map.Entry<ExpVector, C>> ai = av.entrySet().iterator(); 575 Iterator<Map.Entry<ExpVector, C>> bi = bv.entrySet().iterator(); 576 int s = 0; 577 int c = 0; 578 while (ai.hasNext() && bi.hasNext()) { 579 Map.Entry<ExpVector, C> aie = ai.next(); 580 Map.Entry<ExpVector, C> bie = bi.next(); 581 ExpVector ae = aie.getKey(); 582 ExpVector be = bie.getKey(); 583 s = ae.compareTo(be); 584 if (s != 0) { 585 //System.out.println("s = " + s + ", " + ring.toScript(ae) + ", " + ring.toScript(be)); 586 return s; 587 } 588 if (c == 0) { 589 C ac = aie.getValue(); //av.get(ae); 590 C bc = bie.getValue(); //bv.get(be); 591 c = ac.compareTo(bc); 592 } 593 } 594 if (ai.hasNext()) { 595 //System.out.println("ai = " + ai); 596 return 1; 597 } 598 if (bi.hasNext()) { 599 //System.out.println("bi = " + bi); 600 return -1; 601 } 602 //if (c != 0) { 603 //System.out.println("c = " + c); 604 //} 605 // now all keys are equal 606 return c; 607 } 608 609 610 /** 611 * GenPolynomial signum. 612 * @return sign(ldcf(this)). 613 */ 614 public int signum() { 615 if (this.isZERO()) { 616 return 0; 617 } 618 ExpVector t = val.firstKey(); 619 C c = val.get(t); 620 return c.signum(); 621 } 622 623 624 /** 625 * Number of variables. 626 * @return ring.nvar. 627 */ 628 public int numberOfVariables() { 629 return ring.nvar; 630 } 631 632 633 /** 634 * Leading monomial. 635 * @return first map entry. 636 */ 637 public Map.Entry<ExpVector, C> leadingMonomial() { 638 if (val.isEmpty()) { 639 return null; 640 } 641 Iterator<Map.Entry<ExpVector, C>> ai = val.entrySet().iterator(); 642 return ai.next(); 643 } 644 645 646 /** 647 * Leading exponent vector. 648 * @return first exponent. 649 */ 650 public ExpVector leadingExpVector() { 651 if (val.isEmpty()) { 652 return null; // ring.evzero? needs many changes 653 } 654 return val.firstKey(); 655 } 656 657 658 /** 659 * Trailing exponent vector. 660 * @return last exponent. 661 */ 662 public ExpVector trailingExpVector() { 663 if (val.isEmpty()) { 664 return null; //ring.evzero; // or null ?; 665 } 666 return val.lastKey(); 667 } 668 669 670 /** 671 * Leading base coefficient. 672 * @return first coefficient. 673 */ 674 public C leadingBaseCoefficient() { 675 if (val.isEmpty()) { 676 return ring.coFac.getZERO(); 677 } 678 return val.get(val.firstKey()); 679 } 680 681 682 /** 683 * Trailing base coefficient. 684 * @return coefficient of constant term. 685 */ 686 public C trailingBaseCoefficient() { 687 C c = val.get(ring.evzero); 688 if (c == null) { 689 return ring.coFac.getZERO(); 690 } 691 return c; 692 } 693 694 695 /** 696 * Coefficient. 697 * @param e exponent. 698 * @return coefficient for given exponent. 699 */ 700 public C coefficient(ExpVector e) { 701 C c = val.get(e); 702 if (c == null) { 703 c = ring.coFac.getZERO(); 704 } 705 return c; 706 } 707 708 709 /** 710 * Reductum. 711 * @return this - leading monomial. 712 */ 713 public GenPolynomial<C> reductum() { 714 if (val.size() <= 1) { 715 return ring.getZERO(); 716 } 717 Iterator<ExpVector> ai = val.keySet().iterator(); 718 ExpVector lt = ai.next(); 719 lt = ai.next(); // size > 1 720 SortedMap<ExpVector, C> red = val.tailMap(lt); 721 GenPolynomial<C> r = ring.getZERO().copy(); 722 r.doPutToMap(red); // new GenPolynomial<C>(ring, red); 723 return r; 724 } 725 726 727 /** 728 * Degree in variable i. 729 * @return maximal degree in the variable i. 730 */ 731 public long degree(int i) { 732 if (val.isEmpty()) { 733 return -1L; // 0 or -1 ?; 734 } 735 int j; 736 if (i >= 0) { 737 j = ring.nvar - 1 - i; 738 } else { // python like -1 means main variable 739 j = ring.nvar + i; 740 } 741 long deg = 0; 742 if (j < 0) { 743 return deg; 744 } 745 for (ExpVector e : val.keySet()) { 746 long d = e.getVal(j); 747 if (d > deg) { 748 deg = d; 749 } 750 } 751 return deg; 752 } 753 754 755 /** 756 * Maximal degree. 757 * @return maximal degree in any variables. 758 */ 759 public long degree() { 760 if (val.isEmpty()) { 761 return -1L; // 0 or -1 ?; 762 } 763 long deg = 0; 764 for (ExpVector e : val.keySet()) { 765 long d = e.maxDeg(); 766 if (d > deg) { 767 deg = d; 768 } 769 } 770 return deg; 771 } 772 773 774 /** 775 * Minimal degree. 776 * <b>Author:</b> Youssef Elbarbary 777 * @return minimal degree in any variables. 778 */ 779 public long degreeMin() { 780 if (val.isEmpty()) { 781 return -1L; // 0 or -1 ?; 782 } 783 long deg = Long.MAX_VALUE; 784 for (ExpVector e : val.keySet()) { 785 long d = e.minDeg(); 786 if (d < deg) { 787 deg = d; 788 } 789 } 790 return deg; 791 } 792 793 794 /** 795 * Total degree. 796 * @return total degree in any variables. 797 */ 798 public long totalDegree() { 799 if (val.isEmpty()) { 800 return -1L; // 0 or -1 ?; 801 } 802 long deg = 0; 803 for (ExpVector e : val.keySet()) { 804 long d = e.totalDeg(); 805 if (d > deg) { 806 deg = d; 807 } 808 } 809 return deg; 810 } 811 812 813 /** 814 * Weight degree. 815 * @return weight degree in all variables. 816 */ 817 public long weightDegree() { 818 long[][] w = ring.tord.getWeight(); 819 if (w == null || w.length == 0) { 820 return totalDegree(); // assume weight 1 821 } 822 if (val.isEmpty()) { 823 return -1L; // 0 or -1 ?; 824 } 825 long deg = 0; 826 for (ExpVector e : val.keySet()) { 827 long d = e.weightDeg(w); 828 if (d > deg) { 829 deg = d; 830 } 831 } 832 return deg; 833 } 834 835 836 /** 837 * Leading weight polynomial. 838 * @return polynomial with terms of maximal weight degree. 839 */ 840 public GenPolynomial<C> leadingWeightPolynomial() { 841 if (val.isEmpty()) { 842 return ring.getZERO(); 843 } 844 long[][] w = ring.tord.getWeight(); 845 long maxw = weightDegree(); 846 GenPolynomial<C> wp = ring.getZERO().copy(); //new GenPolynomial<C>(ring); 847 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 848 ExpVector e = m.getKey(); 849 long d = e.weightDeg(w); 850 if (d >= maxw) { 851 wp.val.put(e, m.getValue()); 852 } 853 } 854 return wp; 855 } 856 857 858 /** 859 * Leading facet normal polynomial. 860 * @param u leading exponent vector. 861 * @param uv exponent vector of facet normal. 862 * @return polynomial with terms of facet normal. 863 */ 864 public GenPolynomial<C> leadingFacetPolynomial(ExpVector u, ExpVector uv) { 865 if (val.isEmpty()) { 866 return ring.getZERO(); 867 } 868 long[] normal = uv.getVal(); 869 GenPolynomial<C> fp = ring.getZERO().copy(); 870 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 871 ExpVector e = m.getKey(); 872 if (u.equals(e)) { 873 fp.val.put(e, m.getValue()); 874 } else { 875 ExpVector v = u.subtract(e); 876 if (v.compareTo(uv) == 0) { // || v.negate().compareTo(uv) == 0 877 fp.val.put(e, m.getValue()); 878 } else { // check for v parallel to uv 879 long ab = v.weightDeg(normal); //scalarProduct(v, uv); 880 long a = v.weightDeg(v.getVal()); //scalarProduct(v, v); 881 long b = uv.weightDeg(normal); //scalarProduct(uv, uv); 882 if (ab * ab == a * b) { // cos == 1 883 fp.val.put(e, m.getValue()); 884 logger.info("ab = " + ab + ", a = " + a + ", b = " + b + ", u = " + u + ", e = " + e 885 + ", v = " + v); 886 } 887 } 888 } 889 } 890 return fp; 891 } 892 893 894 /** 895 * Is GenPolynomial<C> homogeneous with respect to a weight. 896 * @return true, if this is weight homogeneous, else false. 897 */ 898 public boolean isWeightHomogeneous() { 899 if (val.size() <= 1) { 900 return true; 901 } 902 long[][] w = ring.tord.getWeight(); 903 if (w == null || w.length == 0) { 904 return isHomogeneous(); // assume weights = 1 905 } 906 long deg = -1; 907 for (ExpVector e : val.keySet()) { 908 if (deg < 0) { 909 deg = e.weightDeg(w); 910 } else if (deg != e.weightDeg(w)) { 911 return false; 912 } 913 } 914 return true; 915 } 916 917 918 /** 919 * Maximal degree vector. 920 * @return maximal degree vector of all variables. 921 */ 922 public ExpVector degreeVector() { 923 if (val.isEmpty()) { 924 return null; //deg; 925 } 926 ExpVector deg = ring.evzero; 927 for (ExpVector e : val.keySet()) { 928 deg = deg.lcm(e); 929 } 930 return deg; 931 } 932 933 934 /** 935 * Delta of exponent vectors. 936 * @return list of u-v, where u = lt() and v != u in this. 937 */ 938 public List<ExpVector> deltaExpVectors() { 939 List<ExpVector> de = new ArrayList<ExpVector>(val.size()); 940 if (val.isEmpty()) { 941 return de; 942 } 943 ExpVector u = null; 944 for (ExpVector e : val.keySet()) { 945 if (u == null) { 946 u = e; 947 } else { 948 ExpVector v = u.subtract(e); 949 de.add(v); 950 } 951 } 952 return de; 953 } 954 955 956 /** 957 * Delta of exponent vectors. 958 * @param u marked ExpVector in this.expVectors 959 * @return list of u-v, where v != u in this.expVectors. 960 */ 961 public List<ExpVector> deltaExpVectors(ExpVector u) { 962 List<ExpVector> de = new ArrayList<ExpVector>(val.size()); 963 if (val.isEmpty()) { 964 return de; 965 } 966 for (ExpVector e : val.keySet()) { 967 ExpVector v = u.subtract(e); 968 if (v.isZERO()) { 969 continue; 970 } 971 de.add(v); 972 } 973 return de; 974 } 975 976 977 /** 978 * GenPolynomial maximum norm. 979 * @return ||this||. 980 */ 981 public C maxNorm() { 982 C n = ring.getZEROCoefficient(); 983 for (C c : val.values()) { 984 C x = c.abs(); 985 if (n.compareTo(x) < 0) { 986 n = x; 987 } 988 } 989 return n; 990 } 991 992 993 /** 994 * GenPolynomial sum norm. 995 * @return sum of all absolute values of coefficients. 996 */ 997 public C sumNorm() { 998 C n = ring.getZEROCoefficient(); 999 for (C c : val.values()) { 1000 C x = c.abs(); 1001 n = n.sum(x); 1002 } 1003 return n; 1004 } 1005 1006 1007 /** 1008 * GenPolynomial summation. 1009 * @param S GenPolynomial. 1010 * @return this+S. 1011 */ 1012 //public <T extends GenPolynomial<C>> T sum(T /*GenPolynomial<C>*/ S) { 1013 public GenPolynomial<C> sum(GenPolynomial<C> S) { 1014 if (S == null) { 1015 return this; 1016 } 1017 if (S.isZERO()) { 1018 return this; 1019 } 1020 if (this.isZERO()) { 1021 return S; 1022 } 1023 assert (ring.nvar == S.ring.nvar); 1024 GenPolynomial<C> n = this.copy(); //new GenPolynomial<C>(ring, val); 1025 SortedMap<ExpVector, C> nv = n.val; 1026 SortedMap<ExpVector, C> sv = S.val; 1027 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1028 ExpVector e = me.getKey(); 1029 C y = me.getValue(); //sv.get(e); // assert y != null 1030 C x = nv.get(e); 1031 if (x != null) { 1032 x = x.sum(y); 1033 if (!x.isZERO()) { 1034 nv.put(e, x); 1035 } else { 1036 nv.remove(e); 1037 } 1038 } else { 1039 nv.put(e, y); 1040 } 1041 } 1042 return n; 1043 } 1044 1045 1046 /** 1047 * GenPolynomial addition. This method is not very efficient, since this is 1048 * copied. 1049 * @param a coefficient. 1050 * @param e exponent. 1051 * @return this + a x<sup>e</sup>. 1052 */ 1053 public GenPolynomial<C> sum(C a, ExpVector e) { 1054 if (a == null) { 1055 return this; 1056 } 1057 if (a.isZERO()) { 1058 return this; 1059 } 1060 GenPolynomial<C> n = this.copy(); //new GenPolynomial<C>(ring, val); 1061 SortedMap<ExpVector, C> nv = n.val; 1062 //if ( nv.size() == 0 ) { nv.put(e,a); return n; } 1063 C x = nv.get(e); 1064 if (x != null) { 1065 x = x.sum(a); 1066 if (!x.isZERO()) { 1067 nv.put(e, x); 1068 } else { 1069 nv.remove(e); 1070 } 1071 } else { 1072 nv.put(e, a); 1073 } 1074 return n; 1075 } 1076 1077 1078 /** 1079 * GenPolynomial addition. This method is not very efficient, since this is 1080 * copied. 1081 * @param m monomial. 1082 * @return this + m. 1083 */ 1084 public GenPolynomial<C> sum(Monomial<C> m) { 1085 return sum(m.coefficient(), m.exponent()); 1086 } 1087 1088 1089 /** 1090 * GenPolynomial addition. This method is not very efficient, since this is 1091 * copied. 1092 * @param a coefficient. 1093 * @return this + a x<sup>0</sup>. 1094 */ 1095 public GenPolynomial<C> sum(C a) { 1096 return sum(a, ring.evzero); 1097 } 1098 1099 1100 /** 1101 * GenPolynomial destructive summation. 1102 * @param S GenPolynomial. 1103 */ 1104 public void doAddTo(GenPolynomial<C> S) { 1105 if (S == null || S.isZERO()) { 1106 return; 1107 } 1108 if (this.isZERO()) { 1109 this.val.putAll(S.val); 1110 return; 1111 } 1112 assert (ring.nvar == S.ring.nvar); 1113 SortedMap<ExpVector, C> nv = this.val; 1114 SortedMap<ExpVector, C> sv = S.val; 1115 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1116 ExpVector e = me.getKey(); 1117 C y = me.getValue(); //sv.get(e); // assert y != null 1118 C x = nv.get(e); 1119 if (x != null) { 1120 x = x.sum(y); 1121 if (!x.isZERO()) { 1122 nv.put(e, x); 1123 } else { 1124 nv.remove(e); 1125 } 1126 } else { 1127 nv.put(e, y); 1128 } 1129 } 1130 return; 1131 } 1132 1133 1134 /** 1135 * GenPolynomial destructive summation. 1136 * @param a coefficient. 1137 * @param e exponent. 1138 */ 1139 public void doAddTo(C a, ExpVector e) { 1140 if (a == null || a.isZERO()) { 1141 return; 1142 } 1143 SortedMap<ExpVector, C> nv = this.val; 1144 C x = nv.get(e); 1145 if (x != null) { 1146 x = x.sum(a); 1147 if (!x.isZERO()) { 1148 nv.put(e, x); 1149 } else { 1150 nv.remove(e); 1151 } 1152 } else { 1153 nv.put(e, a); 1154 } 1155 return; 1156 } 1157 1158 1159 /** 1160 * GenPolynomial destructive summation. 1161 * @param a coefficient. 1162 */ 1163 public void doAddTo(C a) { 1164 doAddTo(a, ring.evzero); 1165 } 1166 1167 1168 /** 1169 * GenPolynomial subtraction. 1170 * @param S GenPolynomial. 1171 * @return this-S. 1172 */ 1173 public GenPolynomial<C> subtract(GenPolynomial<C> S) { 1174 if (S == null) { 1175 return this; 1176 } 1177 if (S.isZERO()) { 1178 return this; 1179 } 1180 if (this.isZERO()) { 1181 return S.negate(); 1182 } 1183 assert (ring.nvar == S.ring.nvar); 1184 GenPolynomial<C> n = this.copy(); //new GenPolynomial<C>(ring, val); 1185 SortedMap<ExpVector, C> nv = n.val; 1186 SortedMap<ExpVector, C> sv = S.val; 1187 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1188 ExpVector e = me.getKey(); 1189 C y = me.getValue(); //sv.get(e); // assert y != null 1190 C x = nv.get(e); 1191 if (x != null) { 1192 x = x.subtract(y); 1193 if (!x.isZERO()) { 1194 nv.put(e, x); 1195 } else { 1196 nv.remove(e); 1197 } 1198 } else { 1199 nv.put(e, y.negate()); 1200 } 1201 } 1202 return n; 1203 } 1204 1205 1206 /** 1207 * GenPolynomial subtraction. This method is not very efficient, since this 1208 * is copied. 1209 * @param a coefficient. 1210 * @param e exponent. 1211 * @return this - a x<sup>e</sup>. 1212 */ 1213 public GenPolynomial<C> subtract(C a, ExpVector e) { 1214 if (a == null || a.isZERO()) { 1215 return this; 1216 } 1217 GenPolynomial<C> n = this.copy(); 1218 SortedMap<ExpVector, C> nv = n.val; 1219 C x = nv.get(e); 1220 if (x != null) { 1221 x = x.subtract(a); 1222 if (!x.isZERO()) { 1223 nv.put(e, x); 1224 } else { 1225 nv.remove(e); 1226 } 1227 } else { 1228 nv.put(e, a.negate()); 1229 } 1230 return n; 1231 } 1232 1233 1234 /** 1235 * GenPolynomial subtraction. This method is not very efficient, since this 1236 * is copied. 1237 * @param m monomial. 1238 * @return this - m. 1239 */ 1240 public GenPolynomial<C> subtract(Monomial<C> m) { 1241 return subtract(m.coefficient(), m.exponent()); 1242 } 1243 1244 1245 /** 1246 * GenPolynomial subtract. This method is not very efficient, since this is 1247 * copied. 1248 * @param a coefficient. 1249 * @return this + a x<sup>0</sup>. 1250 */ 1251 public GenPolynomial<C> subtract(C a) { 1252 return subtract(a, ring.evzero); 1253 } 1254 1255 1256 /** 1257 * GenPolynomial subtract a multiple. 1258 * @param a coefficient. 1259 * @param S GenPolynomial. 1260 * @return this - a S. 1261 */ 1262 public GenPolynomial<C> subtractMultiple(C a, GenPolynomial<C> S) { 1263 if (a == null || a.isZERO()) { 1264 return this; 1265 } 1266 if (S == null || S.isZERO()) { 1267 return this; 1268 } 1269 if (this.isZERO()) { 1270 return S.multiply(a.negate()); 1271 } 1272 assert (ring.nvar == S.ring.nvar); 1273 GenPolynomial<C> n = this.copy(); 1274 SortedMap<ExpVector, C> nv = n.val; 1275 SortedMap<ExpVector, C> sv = S.val; 1276 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1277 ExpVector f = me.getKey(); 1278 C y = me.getValue(); // assert y != null 1279 y = a.multiply(y); 1280 C x = nv.get(f); 1281 if (x != null) { 1282 x = x.subtract(y); 1283 if (!x.isZERO()) { 1284 nv.put(f, x); 1285 } else { 1286 nv.remove(f); 1287 } 1288 } else if (!y.isZERO()) { 1289 nv.put(f, y.negate()); 1290 } 1291 } 1292 return n; 1293 } 1294 1295 1296 /** 1297 * GenPolynomial subtract a multiple. 1298 * @param a coefficient. 1299 * @param e exponent. 1300 * @param S GenPolynomial. 1301 * @return this - a x<sup>e</sup> S. 1302 */ 1303 public GenPolynomial<C> subtractMultiple(C a, ExpVector e, GenPolynomial<C> S) { 1304 if (a == null || a.isZERO()) { 1305 return this; 1306 } 1307 if (S == null || S.isZERO()) { 1308 return this; 1309 } 1310 if (this.isZERO()) { 1311 return S.multiply(a.negate(), e); 1312 } 1313 assert (ring.nvar == S.ring.nvar); 1314 GenPolynomial<C> n = this.copy(); 1315 SortedMap<ExpVector, C> nv = n.val; 1316 SortedMap<ExpVector, C> sv = S.val; 1317 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1318 ExpVector f = me.getKey(); 1319 f = e.sum(f); 1320 C y = me.getValue(); // assert y != null 1321 y = a.multiply(y); 1322 C x = nv.get(f); 1323 if (x != null) { 1324 x = x.subtract(y); 1325 if (!x.isZERO()) { 1326 nv.put(f, x); 1327 } else { 1328 nv.remove(f); 1329 } 1330 } else if (!y.isZERO()) { 1331 nv.put(f, y.negate()); 1332 } 1333 } 1334 return n; 1335 } 1336 1337 1338 /** 1339 * GenPolynomial scale and subtract a multiple. 1340 * @param b scale factor. 1341 * @param a coefficient. 1342 * @param S GenPolynomial. 1343 * @return this * b - a S. 1344 */ 1345 public GenPolynomial<C> scaleSubtractMultiple(C b, C a, GenPolynomial<C> S) { 1346 if (a == null || S == null) { 1347 return this.multiply(b); 1348 } 1349 if (a.isZERO() || S.isZERO()) { 1350 return this.multiply(b); 1351 } 1352 if (this.isZERO() || b == null || b.isZERO()) { 1353 return S.multiply(a.negate()); //left? 1354 } 1355 if (b.isONE()) { 1356 return subtractMultiple(a, S); 1357 } 1358 assert (ring.nvar == S.ring.nvar); 1359 GenPolynomial<C> n = this.multiply(b); 1360 SortedMap<ExpVector, C> nv = n.val; 1361 SortedMap<ExpVector, C> sv = S.val; 1362 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1363 ExpVector f = me.getKey(); 1364 //f = e.sum(f); 1365 C y = me.getValue(); // assert y != null 1366 y = a.multiply(y); // now y can be zero 1367 C x = nv.get(f); 1368 if (x != null) { 1369 x = x.subtract(y); 1370 if (!x.isZERO()) { 1371 nv.put(f, x); 1372 } else { 1373 nv.remove(f); 1374 } 1375 } else if (!y.isZERO()) { 1376 nv.put(f, y.negate()); 1377 } 1378 } 1379 return n; 1380 } 1381 1382 1383 /** 1384 * GenPolynomial scale and subtract a multiple. 1385 * @param b scale factor. 1386 * @param a coefficient. 1387 * @param e exponent. 1388 * @param S GenPolynomial. 1389 * @return this * b - a x<sup>e</sup> S. 1390 */ 1391 public GenPolynomial<C> scaleSubtractMultiple(C b, C a, ExpVector e, GenPolynomial<C> S) { 1392 if (a == null || S == null) { 1393 return this.multiply(b); 1394 } 1395 if (a.isZERO() || S.isZERO()) { 1396 return this.multiply(b); 1397 } 1398 if (this.isZERO() || b == null || b.isZERO()) { 1399 return S.multiply(a.negate(), e); 1400 } 1401 if (b.isONE()) { 1402 return subtractMultiple(a, e, S); 1403 } 1404 assert (ring.nvar == S.ring.nvar); 1405 GenPolynomial<C> n = this.multiply(b); 1406 SortedMap<ExpVector, C> nv = n.val; 1407 SortedMap<ExpVector, C> sv = S.val; 1408 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1409 ExpVector f = me.getKey(); 1410 f = e.sum(f); 1411 C y = me.getValue(); // assert y != null 1412 y = a.multiply(y); // now y can be zero 1413 C x = nv.get(f); 1414 if (x != null) { 1415 x = x.subtract(y); 1416 if (!x.isZERO()) { 1417 nv.put(f, x); 1418 } else { 1419 nv.remove(f); 1420 } 1421 } else if (!y.isZERO()) { 1422 nv.put(f, y.negate()); 1423 } 1424 } 1425 return n; 1426 } 1427 1428 1429 /** 1430 * GenPolynomial scale and subtract a multiple. 1431 * @param b scale factor. 1432 * @param g scale exponent. 1433 * @param a coefficient. 1434 * @param e exponent. 1435 * @param S GenPolynomial. 1436 * @return this * a x<sup>g</sup> - a x<sup>e</sup> S. 1437 */ 1438 public GenPolynomial<C> scaleSubtractMultiple(C b, ExpVector g, C a, ExpVector e, GenPolynomial<C> S) { 1439 if (a == null || S == null) { 1440 return this.multiply(b, g); 1441 } 1442 if (a.isZERO() || S.isZERO()) { 1443 return this.multiply(b, g); 1444 } 1445 if (this.isZERO() || b == null || b.isZERO()) { 1446 return S.multiply(a.negate(), e); 1447 } 1448 if (b.isONE() && g.isZERO()) { 1449 return subtractMultiple(a, e, S); 1450 } 1451 assert (ring.nvar == S.ring.nvar); 1452 GenPolynomial<C> n = this.multiply(b, g); 1453 SortedMap<ExpVector, C> nv = n.val; 1454 SortedMap<ExpVector, C> sv = S.val; 1455 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 1456 ExpVector f = me.getKey(); 1457 f = e.sum(f); 1458 C y = me.getValue(); // assert y != null 1459 y = a.multiply(y); // y can be zero now 1460 C x = nv.get(f); 1461 if (x != null) { 1462 x = x.subtract(y); 1463 if (!x.isZERO()) { 1464 nv.put(f, x); 1465 } else { 1466 nv.remove(f); 1467 } 1468 } else if (!y.isZERO()) { 1469 nv.put(f, y.negate()); 1470 } 1471 } 1472 return n; 1473 } 1474 1475 1476 /** 1477 * GenPolynomial negation. 1478 * @return -this. 1479 */ 1480 public GenPolynomial<C> negate() { 1481 GenPolynomial<C> n = ring.getZERO().copy(); 1482 //new GenPolynomial<C>(ring, ring.getZERO().val); 1483 SortedMap<ExpVector, C> v = n.val; 1484 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1485 C x = m.getValue(); // != null, 0 1486 v.put(m.getKey(), x.negate()); 1487 // or m.setValue( x.negate() ) if this cloned 1488 } 1489 return n; 1490 } 1491 1492 1493 /** 1494 * GenPolynomial absolute value, i.e. leadingCoefficient > 0. 1495 * @return abs(this). 1496 */ 1497 public GenPolynomial<C> abs() { 1498 if (leadingBaseCoefficient().signum() < 0) { 1499 return this.negate(); 1500 } 1501 return this; 1502 } 1503 1504 1505 /** 1506 * GenPolynomial multiplication. 1507 * @param S GenPolynomial. 1508 * @return this*S. 1509 */ 1510 public GenPolynomial<C> multiply(GenPolynomial<C> S) { 1511 if (S == null) { 1512 return ring.getZERO(); 1513 } 1514 if (S.isZERO()) { 1515 return ring.getZERO(); 1516 } 1517 if (this.isZERO()) { 1518 return this; 1519 } 1520 assert (ring.nvar == S.ring.nvar); 1521 if (this instanceof GenSolvablePolynomial && S instanceof GenSolvablePolynomial) { 1522 //throw new RuntimeException("wrong method dispatch in JRE "); 1523 logger.debug("warn: wrong method dispatch in JRE multiply(S) - trying to fix"); 1524 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1525 GenSolvablePolynomial<C> Sp = (GenSolvablePolynomial<C>) S; 1526 return T.multiply(Sp); 1527 } 1528 GenPolynomial<C> p = ring.getZERO().copy(); 1529 SortedMap<ExpVector, C> pv = p.val; 1530 for (Map.Entry<ExpVector, C> m1 : val.entrySet()) { 1531 C c1 = m1.getValue(); 1532 ExpVector e1 = m1.getKey(); 1533 for (Map.Entry<ExpVector, C> m2 : S.val.entrySet()) { 1534 C c2 = m2.getValue(); 1535 ExpVector e2 = m2.getKey(); 1536 C c = c1.multiply(c2); // check non zero if not domain 1537 if (!c.isZERO()) { 1538 ExpVector e = e1.sum(e2); 1539 C c0 = pv.get(e); 1540 if (c0 == null) { 1541 pv.put(e, c); 1542 } else { 1543 c0 = c0.sum(c); 1544 if (!c0.isZERO()) { 1545 pv.put(e, c0); 1546 } else { 1547 pv.remove(e); 1548 } 1549 } 1550 } 1551 } 1552 } 1553 return p; 1554 } 1555 1556 1557 /** 1558 * GenPolynomial multiplication. Product with coefficient ring element. 1559 * @param s coefficient. 1560 * @return this*s. 1561 */ 1562 public GenPolynomial<C> multiply(C s) { 1563 if (s == null||s.isZERO()) { 1564 return ring.getZERO(); 1565 } 1566 if (this.isZERO()) { 1567 return this; 1568 } 1569 if (this instanceof GenSolvablePolynomial) { 1570 //throw new RuntimeException("wrong method dispatch in JRE "); 1571 logger.debug("warn: wrong method dispatch in JRE multiply(s) - trying to fix"); 1572 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1573 return T.multiply(s); 1574 } 1575 GenPolynomial<C> p = ring.getZERO().copy(); 1576 SortedMap<ExpVector, C> pv = p.val; 1577 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1578 C a = m.getValue(); 1579 ExpVector e = m.getKey(); 1580 C c = a.multiply(s); // check non zero if not domain 1581 if (!c.isZERO()) { 1582 pv.put(e, c); // or m1.setValue( c ) 1583 } 1584 } 1585 return p; 1586 } 1587 1588 1589 /** 1590 * GenPolynomial left multiplication. Left product with coefficient 1591 * ring element. 1592 * @param s coefficient. 1593 * @return s*this. 1594 */ 1595 public GenPolynomial<C> multiplyLeft(C s) { 1596 if (s == null||s.isZERO()) { 1597 return ring.getZERO(); 1598 } 1599 if (this.isZERO()) { 1600 return this; 1601 } 1602 if (this instanceof GenSolvablePolynomial) { 1603 //throw new RuntimeException("wrong method dispatch in JRE "); 1604 logger.debug("warn: wrong method dispatch in JRE multiply(s) - trying to fix"); 1605 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1606 return T.multiplyLeft(s); 1607 } 1608 GenPolynomial<C> p = ring.getZERO().copy(); 1609 SortedMap<ExpVector, C> pv = p.val; 1610 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1611 C a = m.getValue(); 1612 ExpVector e = m.getKey(); 1613 C c = s.multiply(a); 1614 if (!c.isZERO()) { 1615 pv.put(e, c); 1616 } 1617 } 1618 return p; 1619 } 1620 1621 1622 /** 1623 * GenPolynomial monic, i.e. leadingCoefficient == 1. If leadingCoefficient 1624 * is not invertible returns this unmodified. 1625 * @return monic(this). 1626 */ 1627 public GenPolynomial<C> monic() { 1628 if (this.isZERO()) { 1629 return this; 1630 } 1631 C lc = leadingBaseCoefficient(); 1632 if (!lc.isUnit()) { 1633 //System.out.println("lc = "+lc); 1634 return this; 1635 } 1636 C lm = lc.inverse(); 1637 return multiplyLeft(lm); 1638 } 1639 1640 1641 /** 1642 * GenPolynomial multiplication. Product with ring element and exponent 1643 * vector. 1644 * @param s coefficient. 1645 * @param e exponent. 1646 * @return this * s x<sup>e</sup>. 1647 */ 1648 public GenPolynomial<C> multiply(C s, ExpVector e) { 1649 if (s == null) { 1650 return ring.getZERO(); 1651 } 1652 if (s.isZERO()) { 1653 return ring.getZERO(); 1654 } 1655 if (this.isZERO()) { 1656 return this; 1657 } 1658 if (e == null) { // exp vector of zero polynomial 1659 return ring.getZERO(); 1660 } 1661 if (this instanceof GenSolvablePolynomial) { 1662 //throw new RuntimeException("wrong method dispatch in JRE "); 1663 logger.debug("warn: wrong method dispatch in JRE multiply(s,e) - trying to fix"); 1664 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1665 return T.multiply(s, e); 1666 } 1667 GenPolynomial<C> p = ring.getZERO().copy(); 1668 SortedMap<ExpVector, C> pv = p.val; 1669 for (Map.Entry<ExpVector, C> m1 : val.entrySet()) { 1670 C c1 = m1.getValue(); 1671 ExpVector e1 = m1.getKey(); 1672 C c = c1.multiply(s); // check non zero if not domain 1673 if (!c.isZERO()) { 1674 ExpVector e2 = e1.sum(e); 1675 pv.put(e2, c); 1676 } 1677 } 1678 return p; 1679 } 1680 1681 1682 /** 1683 * GenPolynomial multiplication. Product with exponent vector. 1684 * @param e exponent (!= null). 1685 * @return this * x<sup>e</sup>. 1686 */ 1687 public GenPolynomial<C> multiply(ExpVector e) { 1688 if (e == null) { // exp vector of zero polynomial 1689 return ring.getZERO(); 1690 } 1691 // assert e != null. This is seldom allowed. 1692 if (this.isZERO()) { 1693 return this; 1694 } 1695 if (this instanceof GenSolvablePolynomial) { 1696 //throw new RuntimeException("wrong method dispatch in JRE "); 1697 logger.debug("warn: wrong method dispatch in JRE multiply(e) - trying to fix"); 1698 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1699 return T.multiply(e); 1700 } 1701 GenPolynomial<C> p = ring.getZERO().copy(); 1702 SortedMap<ExpVector, C> pv = p.val; 1703 for (Map.Entry<ExpVector, C> m1 : val.entrySet()) { 1704 C c1 = m1.getValue(); 1705 ExpVector e1 = m1.getKey(); 1706 ExpVector e2 = e1.sum(e); 1707 pv.put(e2, c1); 1708 } 1709 return p; 1710 } 1711 1712 1713 /** 1714 * GenPolynomial multiplication. Product with 'monomial'. 1715 * @param m 'monomial'. 1716 * @return this * m. 1717 */ 1718 public GenPolynomial<C> multiply(Map.Entry<ExpVector, C> m) { 1719 if (m == null) { 1720 return ring.getZERO(); 1721 } 1722 return multiply(m.getValue(), m.getKey()); 1723 } 1724 1725 1726 /** 1727 * GenPolynomial division. Division by coefficient ring element. Fails, if 1728 * exact division is not possible. 1729 * @param s coefficient. 1730 * @return s**(-1) * this. 1731 */ 1732 public GenPolynomial<C> divide(C s) { 1733 if (s == null || s.isZERO()) { 1734 throw new ArithmeticException("division by zero"); 1735 } 1736 if (this.isZERO()) { 1737 return this; 1738 } 1739 //C t = s.inverse(); 1740 //return multiply(t); 1741 GenPolynomial<C> p = ring.getZERO().copy(); 1742 SortedMap<ExpVector, C> pv = p.val; 1743 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1744 ExpVector e = m.getKey(); 1745 C c1 = m.getValue(); 1746 C c = c1.divide(s); 1747 if (debug) { 1748 C x = c1.remainder(s); 1749 if (!x.isZERO()) { 1750 logger.info("divide x = " + x); 1751 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1752 } 1753 } 1754 if (c.isZERO()) { 1755 throw new ArithmeticException("no exact division: " + c1 + "/" + s + ", in " + this); 1756 } 1757 pv.put(e, c); // or m1.setValue( c ) 1758 } 1759 return p; 1760 } 1761 1762 1763 /** 1764 * GenPolynomial right division. Right division by coefficient ring element. Fails, if 1765 * exact division is not possible. 1766 * @param s coefficient. 1767 * @return this * s**(-1). 1768 */ 1769 public GenPolynomial<C> rightDivideCoeff(C s) { 1770 if (s == null || s.isZERO()) { 1771 throw new ArithmeticException("division by zero"); 1772 } 1773 if (this.isZERO()) { 1774 return this; 1775 } 1776 //C t = s.inverse(); 1777 //return multiply(t); 1778 GenPolynomial<C> p = ring.getZERO().copy(); 1779 SortedMap<ExpVector, C> pv = p.val; 1780 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1781 ExpVector e = m.getKey(); 1782 C c1 = m.getValue(); 1783 C c = c1.rightDivide(s); 1784 if (debug) { 1785 C x = c1.rightRemainder(s); 1786 if (!x.isZERO()) { 1787 logger.info("divide x = " + x); 1788 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1789 } 1790 } 1791 if (c.isZERO()) { 1792 throw new ArithmeticException("no exact division: " + c1 + "/" + s + ", in " + this); 1793 } 1794 pv.put(e, c); // or m1.setValue( c ) 1795 } 1796 return p; 1797 } 1798 1799 1800 /** 1801 * GenPolynomial left division. Left division by coefficient ring element. Fails, if 1802 * exact division is not possible. 1803 * @param s coefficient. 1804 * @return s**(-1) * this. 1805 */ 1806 public GenPolynomial<C> leftDivideCoeff(C s) { 1807 if (s == null || s.isZERO()) { 1808 throw new ArithmeticException("division by zero"); 1809 } 1810 if (this.isZERO()) { 1811 return this; 1812 } 1813 //C t = s.inverse(); 1814 //return multiply(t); 1815 GenPolynomial<C> p = ring.getZERO().copy(); 1816 SortedMap<ExpVector, C> pv = p.val; 1817 for (Map.Entry<ExpVector, C> m : val.entrySet()) { 1818 ExpVector e = m.getKey(); 1819 C c1 = m.getValue(); 1820 C c = c1.leftDivide(s); 1821 if (debug) { 1822 C x = c1.leftRemainder(s); 1823 if (!x.isZERO()) { 1824 logger.info("divide x = " + x); 1825 throw new ArithmeticException("no exact division: " + c1 + "/" + s); 1826 } 1827 } 1828 if (c.isZERO()) { 1829 throw new ArithmeticException("no exact division: " + c1 + "/" + s + ", in " + this); 1830 } 1831 pv.put(e, c); // or m1.setValue( c ) 1832 } 1833 return p; 1834 } 1835 1836 1837 /** 1838 * GenPolynomial division with remainder. Fails, if exact division by 1839 * leading base coefficient is not possible. Meaningful only for univariate 1840 * polynomials over fields, but works in any case. 1841 * @param S nonzero GenPolynomial with invertible leading coefficient. 1842 * @return [ quotient , remainder ] with this = quotient * S + remainder and 1843 * deg(remainder) < deg(S) or remiander = 0. 1844 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 1845 */ 1846 @SuppressWarnings("unchecked") 1847 public GenPolynomial<C>[] quotientRemainder(GenPolynomial<C> S) { 1848 if (S == null || S.isZERO()) { 1849 throw new ArithmeticException("division by zero"); 1850 } 1851 C c = S.leadingBaseCoefficient(); 1852 if (!c.isUnit()) { 1853 throw new ArithmeticException("lbcf not invertible " + c); 1854 } 1855 C ci = c.inverse(); 1856 assert (ring.nvar == S.ring.nvar); 1857 ExpVector e = S.leadingExpVector(); 1858 GenPolynomial<C> h; 1859 GenPolynomial<C> q = ring.getZERO().copy(); 1860 GenPolynomial<C> r = this.copy(); 1861 while (!r.isZERO()) { 1862 ExpVector f = r.leadingExpVector(); 1863 if (f.multipleOf(e)) { 1864 C a = r.leadingBaseCoefficient(); 1865 f = f.subtract(e); 1866 a = a.multiply(ci); 1867 q = q.sum(a, f); 1868 h = S.multiply(a, f); 1869 r = r.subtract(h); 1870 } else { 1871 break; 1872 } 1873 } 1874 GenPolynomial<C>[] ret = new GenPolynomial[2]; 1875 ret[0] = q; 1876 ret[1] = r; 1877 return ret; 1878 } 1879 1880 1881 /** 1882 * GenPolynomial division. Fails, if exact division by leading base 1883 * coefficient is not possible. Meaningful only for univariate polynomials 1884 * over fields, but works in any case. 1885 * @param S nonzero GenPolynomial with invertible leading coefficient. 1886 * @return quotient with this = quotient * S + remainder. 1887 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 1888 */ 1889 public GenPolynomial<C> divide(GenPolynomial<C> S) { 1890 if (this instanceof GenSolvablePolynomial || S instanceof GenSolvablePolynomial) { 1891 //throw new RuntimeException("wrong method dispatch in JRE "); 1892 //logger.debug("warn: wrong method dispatch in JRE multiply(S) - trying to fix"); 1893 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1894 GenSolvablePolynomial<C> Sp = (GenSolvablePolynomial<C>) S; 1895 return T.quotientRemainder(Sp)[0]; 1896 } 1897 return quotientRemainder(S)[0]; 1898 } 1899 1900 1901 /** 1902 * GenPolynomial remainder. Fails, if exact division by leading base 1903 * coefficient is not possible. Meaningful only for univariate polynomials 1904 * over fields, but works in any case. 1905 * @param S nonzero GenPolynomial with invertible leading coefficient. 1906 * @return remainder with this = quotient * S + remainder. 1907 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 1908 */ 1909 public GenPolynomial<C> remainder(GenPolynomial<C> S) { 1910 if (this instanceof GenSolvablePolynomial || S instanceof GenSolvablePolynomial) { 1911 //throw new RuntimeException("wrong method dispatch in JRE "); 1912 //logger.debug("warn: wrong method dispatch in JRE multiply(S) - trying to fix"); 1913 GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this; 1914 GenSolvablePolynomial<C> Sp = (GenSolvablePolynomial<C>) S; 1915 return T.quotientRemainder(Sp)[1]; 1916 } 1917 if (S == null || S.isZERO()) { 1918 throw new ArithmeticException("division by zero"); 1919 } 1920 C c = S.leadingBaseCoefficient(); 1921 if (!c.isUnit()) { 1922 throw new ArithmeticException("lbc not invertible " + c); 1923 } 1924 C ci = c.inverse(); 1925 assert (ring.nvar == S.ring.nvar); 1926 ExpVector e = S.leadingExpVector(); 1927 GenPolynomial<C> h; 1928 GenPolynomial<C> r = this.copy(); 1929 while (!r.isZERO()) { 1930 ExpVector f = r.leadingExpVector(); 1931 if (f.multipleOf(e)) { 1932 C a = r.leadingBaseCoefficient(); 1933 f = f.subtract(e); 1934 //logger.info("red div = " + e); 1935 a = a.multiply(ci); 1936 h = S.multiply(a, f); 1937 r = r.subtract(h); 1938 } else { 1939 break; 1940 } 1941 } 1942 return r; 1943 } 1944 1945 1946 /** 1947 * GenPolynomial greatest common divisor. Only for univariate polynomials 1948 * over fields. 1949 * @param S GenPolynomial. 1950 * @return gcd(this,S). 1951 */ 1952 public GenPolynomial<C> gcd(GenPolynomial<C> S) { 1953 if (S == null || S.isZERO()) { 1954 return this; 1955 } 1956 if (this.isZERO()) { 1957 return S; 1958 } 1959 if (ring.nvar != 1) { 1960 throw new IllegalArgumentException("not univariate polynomials" + ring); 1961 } 1962 GenPolynomial<C> x; 1963 GenPolynomial<C> q = this; 1964 GenPolynomial<C> r = S; 1965 while (!r.isZERO()) { 1966 x = q.remainder(r); 1967 q = r; 1968 r = x; 1969 } 1970 return q.monic(); // normalize 1971 } 1972 1973 1974 /** 1975 * GenPolynomial extended greatest comon divisor. Only for univariate 1976 * polynomials over fields. 1977 * @param S GenPolynomial. 1978 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 1979 */ 1980 @SuppressWarnings("unchecked") 1981 public GenPolynomial<C>[] egcd(GenPolynomial<C> S) { 1982 GenPolynomial<C>[] ret = new GenPolynomial[3]; 1983 ret[0] = null; 1984 ret[1] = null; 1985 ret[2] = null; 1986 if (S == null || S.isZERO()) { 1987 ret[0] = this; 1988 ret[1] = this.ring.getONE(); 1989 ret[2] = this.ring.getZERO(); 1990 return ret; 1991 } 1992 if (this.isZERO()) { 1993 ret[0] = S; 1994 ret[1] = this.ring.getZERO(); 1995 ret[2] = this.ring.getONE(); 1996 return ret; 1997 } 1998 if (ring.nvar != 1) { 1999 throw new IllegalArgumentException( 2000 this.getClass().getName() + " not univariate polynomials" + ring); 2001 } 2002 if (this.isConstant() && S.isConstant()) { 2003 C t = this.leadingBaseCoefficient(); 2004 C s = S.leadingBaseCoefficient(); 2005 C[] gg = t.egcd(s); 2006 //System.out.println("coeff gcd = " + Arrays.toString(gg)); 2007 GenPolynomial<C> z = this.ring.getZERO(); 2008 ret[0] = z.sum(gg[0]); 2009 ret[1] = z.sum(gg[1]); 2010 ret[2] = z.sum(gg[2]); 2011 return ret; 2012 } 2013 GenPolynomial<C>[] qr; 2014 GenPolynomial<C> q = this; 2015 GenPolynomial<C> r = S; 2016 GenPolynomial<C> c1 = ring.getONE().copy(); 2017 GenPolynomial<C> d1 = ring.getZERO().copy(); 2018 GenPolynomial<C> c2 = ring.getZERO().copy(); 2019 GenPolynomial<C> d2 = ring.getONE().copy(); 2020 GenPolynomial<C> x1; 2021 GenPolynomial<C> x2; 2022 while (!r.isZERO()) { 2023 qr = q.quotientRemainder(r); 2024 q = qr[0]; 2025 x1 = c1.subtract(q.multiply(d1)); 2026 x2 = c2.subtract(q.multiply(d2)); 2027 c1 = d1; 2028 c2 = d2; 2029 d1 = x1; 2030 d2 = x2; 2031 q = r; 2032 r = qr[1]; 2033 } 2034 // normalize ldcf(q) to 1, i.e. make monic 2035 C g = q.leadingBaseCoefficient(); 2036 if (g.isUnit()) { 2037 C h = g.inverse(); 2038 q = q.multiply(h); 2039 c1 = c1.multiply(h); 2040 c2 = c2.multiply(h); 2041 } 2042 //assert ( ((c1.multiply(this)).sum( c2.multiply(S)).equals(q) )); 2043 ret[0] = q; 2044 ret[1] = c1; 2045 ret[2] = c2; 2046 return ret; 2047 } 2048 2049 2050 /** 2051 * GenPolynomial half extended greatest comon divisor. Only for univariate 2052 * polynomials over fields. 2053 * @param S GenPolynomial. 2054 * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S). 2055 */ 2056 @SuppressWarnings("unchecked") 2057 public GenPolynomial<C>[] hegcd(GenPolynomial<C> S) { 2058 GenPolynomial<C>[] ret = new GenPolynomial[2]; 2059 ret[0] = null; 2060 ret[1] = null; 2061 if (S == null || S.isZERO()) { 2062 ret[0] = this; 2063 ret[1] = this.ring.getONE(); 2064 return ret; 2065 } 2066 if (this.isZERO()) { 2067 ret[0] = S; 2068 return ret; 2069 } 2070 if (ring.nvar != 1) { 2071 throw new IllegalArgumentException( 2072 this.getClass().getName() + " not univariate polynomials" + ring); 2073 } 2074 GenPolynomial<C>[] qr; 2075 GenPolynomial<C> q = this; 2076 GenPolynomial<C> r = S; 2077 GenPolynomial<C> c1 = ring.getONE().copy(); 2078 GenPolynomial<C> d1 = ring.getZERO().copy(); 2079 GenPolynomial<C> x1; 2080 while (!r.isZERO()) { 2081 qr = q.quotientRemainder(r); 2082 q = qr[0]; 2083 x1 = c1.subtract(q.multiply(d1)); 2084 c1 = d1; 2085 d1 = x1; 2086 q = r; 2087 r = qr[1]; 2088 } 2089 // normalize ldcf(q) to 1, i.e. make monic 2090 C g = q.leadingBaseCoefficient(); 2091 if (g.isUnit()) { 2092 C h = g.inverse(); 2093 q = q.multiply(h); 2094 c1 = c1.multiply(h); 2095 } 2096 //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); 2097 ret[0] = q; 2098 ret[1] = c1; 2099 return ret; 2100 } 2101 2102 2103 /** 2104 * GenPolynomial inverse. Required by RingElem. Throws not invertible 2105 * exception. 2106 */ 2107 public GenPolynomial<C> inverse() { 2108 if (isUnit()) { // only possible if ldbcf is unit 2109 C c = leadingBaseCoefficient().inverse(); 2110 return ring.getONE().multiply(c); 2111 } 2112 throw new NotInvertibleException("element not invertible " + this + " :: " + ring); 2113 } 2114 2115 2116 /** 2117 * GenPolynomial modular inverse. Only for univariate polynomials over 2118 * fields. 2119 * @param m GenPolynomial. 2120 * @return a with with a*this = 1 mod m. 2121 */ 2122 public GenPolynomial<C> modInverse(GenPolynomial<C> m) { 2123 if (this.isZERO()) { 2124 throw new NotInvertibleException("zero is not invertible"); 2125 } 2126 GenPolynomial<C>[] hegcd = this.hegcd(m); 2127 GenPolynomial<C> a = hegcd[0]; 2128 if (!a.isUnit()) { // gcd != 1 2129 throw new AlgebraicNotInvertibleException("element not invertible, gcd != 1", m, a, m.divide(a)); 2130 } 2131 GenPolynomial<C> b = hegcd[1]; 2132 if (b.isZERO()) { // when m divides this, e.g. m.isUnit() 2133 throw new NotInvertibleException("element not invertible, divisible by modul"); 2134 } 2135 return b; 2136 } 2137 2138 2139 /** 2140 * Extend variables. Used e.g. in module embedding. Extend all ExpVectors by 2141 * i elements and multiply by x_j^k. 2142 * @param pfac extended polynomial ring factory (by i variables). 2143 * @param j index of variable to be used for multiplication. 2144 * @param k exponent for x_j. 2145 * @return extended polynomial. 2146 */ 2147 public GenPolynomial<C> extend(GenPolynomialRing<C> pfac, int j, long k) { 2148 if (ring.equals(pfac)) { // nothing to do 2149 return this; 2150 } 2151 GenPolynomial<C> Cp = pfac.getZERO().copy(); 2152 if (this.isZERO()) { 2153 return Cp; 2154 } 2155 int i = pfac.nvar - ring.nvar; 2156 Map<ExpVector, C> C = Cp.val; //getMap(); 2157 Map<ExpVector, C> A = val; 2158 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2159 ExpVector e = y.getKey(); 2160 C a = y.getValue(); 2161 ExpVector f = e.extend(i, j, k); 2162 C.put(f, a); 2163 } 2164 return Cp; 2165 } 2166 2167 2168 /** 2169 * Extend lower variables. Used e.g. in module embedding. Extend all 2170 * ExpVectors by i lower elements and multiply by x_j^k. 2171 * @param pfac extended polynomial ring factory (by i variables). 2172 * @param j index of variable to be used for multiplication. 2173 * @param k exponent for x_j. 2174 * @return extended polynomial. 2175 */ 2176 public GenPolynomial<C> extendLower(GenPolynomialRing<C> pfac, int j, long k) { 2177 if (ring.equals(pfac)) { // nothing to do 2178 return this; 2179 } 2180 GenPolynomial<C> Cp = pfac.getZERO().copy(); 2181 if (this.isZERO()) { 2182 return Cp; 2183 } 2184 int i = pfac.nvar - ring.nvar; 2185 Map<ExpVector, C> C = Cp.val; //getMap(); 2186 Map<ExpVector, C> A = val; 2187 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2188 ExpVector e = y.getKey(); 2189 C a = y.getValue(); 2190 ExpVector f = e.extendLower(i, j, k); 2191 C.put(f, a); 2192 } 2193 return Cp; 2194 } 2195 2196 2197 /** 2198 * Contract variables. Used e.g. in module embedding. Remove i elements of 2199 * each ExpVector. 2200 * @param pfac contracted polynomial ring factory (by i variables). 2201 * @return Map of exponents and contracted polynomials. <b>Note:</b> could 2202 * return SortedMap 2203 */ 2204 public Map<ExpVector, GenPolynomial<C>> contract(GenPolynomialRing<C> pfac) { 2205 GenPolynomial<C> zero = pfac.getZERO(); //not pfac.coFac; 2206 TermOrder t = new TermOrder(TermOrder.INVLEX); 2207 Map<ExpVector, GenPolynomial<C>> B = new TreeMap<ExpVector, GenPolynomial<C>>( 2208 t.getAscendComparator()); 2209 if (this.isZERO()) { 2210 return B; 2211 } 2212 int i = ring.nvar - pfac.nvar; 2213 Map<ExpVector, C> A = val; 2214 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2215 ExpVector e = y.getKey(); 2216 C a = y.getValue(); 2217 ExpVector f = e.contract(0, i); 2218 ExpVector g = e.contract(i, e.length() - i); 2219 GenPolynomial<C> p = B.get(f); 2220 if (p == null) { 2221 p = zero; 2222 } 2223 p = p.sum(a, g); 2224 B.put(f, p); 2225 } 2226 return B; 2227 } 2228 2229 2230 /** 2231 * Contract variables to coefficient polynomial. Remove i elements of each 2232 * ExpVector, removed elements must be zero. 2233 * @param pfac contracted polynomial ring factory (by i variables). 2234 * @return contracted coefficient polynomial. 2235 */ 2236 public GenPolynomial<C> contractCoeff(GenPolynomialRing<C> pfac) { 2237 Map<ExpVector, GenPolynomial<C>> ms = contract(pfac); 2238 GenPolynomial<C> c = pfac.getZERO(); 2239 for (Map.Entry<ExpVector, GenPolynomial<C>> m : ms.entrySet()) { 2240 if (m.getKey().isZERO()) { 2241 c = m.getValue(); 2242 } else { 2243 throw new RuntimeException("wrong coefficient contraction " + m + ", pol = " + c); 2244 } 2245 } 2246 return c; 2247 } 2248 2249 2250 /** 2251 * Extend univariate to multivariate polynomial. This is an univariate 2252 * polynomial in variable i of the polynomial ring, it is extended to the 2253 * given polynomial ring. 2254 * @param pfac extended polynomial ring factory. 2255 * @param i index of the variable of this polynomial in pfac. 2256 * @return extended multivariate polynomial. 2257 */ 2258 public GenPolynomial<C> extendUnivariate(GenPolynomialRing<C> pfac, int i) { 2259 if (i < 0 || pfac.nvar < i) { 2260 throw new IllegalArgumentException("index " + i + "out of range " + pfac.nvar); 2261 } 2262 if (ring.nvar != 1) { 2263 throw new IllegalArgumentException("polynomial not univariate " + ring.nvar); 2264 } 2265 if (this.isONE()) { 2266 return pfac.getONE(); 2267 } 2268 int j = pfac.nvar - 1 - i; 2269 GenPolynomial<C> Cp = pfac.getZERO().copy(); 2270 if (this.isZERO()) { 2271 return Cp; 2272 } 2273 Map<ExpVector, C> C = Cp.val; //getMap(); 2274 Map<ExpVector, C> A = val; 2275 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2276 ExpVector e = y.getKey(); 2277 long n = e.getVal(0); 2278 C a = y.getValue(); 2279 ExpVector f = ExpVector.create(pfac.nvar, j, n); 2280 C.put(f, a); // assert not contained 2281 } 2282 return Cp; 2283 } 2284 2285 2286 /** 2287 * Make homogeneous. 2288 * @param pfac extended polynomial ring factory (by 1 variable). 2289 * @return homogeneous polynomial. 2290 */ 2291 public GenPolynomial<C> homogenize(GenPolynomialRing<C> pfac) { 2292 if (ring.equals(pfac)) { // not implemented 2293 throw new UnsupportedOperationException("case with same ring not implemented"); 2294 } 2295 GenPolynomial<C> Cp = pfac.getZERO().copy(); 2296 if (this.isZERO()) { 2297 return Cp; 2298 } 2299 long deg = totalDegree(); 2300 //int i = pfac.nvar - ring.nvar; 2301 Map<ExpVector, C> C = Cp.val; //getMap(); 2302 Map<ExpVector, C> A = val; 2303 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2304 ExpVector e = y.getKey(); 2305 C a = y.getValue(); 2306 long d = deg - e.totalDeg(); 2307 ExpVector f = e.extend(1, 0, d); 2308 C.put(f, a); 2309 } 2310 return Cp; 2311 } 2312 2313 2314 /** 2315 * Dehomogenize. 2316 * @param pfac contracted polynomial ring factory (by 1 variable). 2317 * @return in homogeneous polynomial. 2318 */ 2319 public GenPolynomial<C> deHomogenize(GenPolynomialRing<C> pfac) { 2320 if (ring.equals(pfac)) { // not implemented 2321 throw new UnsupportedOperationException("case with same ring not implemented"); 2322 } 2323 GenPolynomial<C> Cp = pfac.getZERO().copy(); 2324 if (this.isZERO()) { 2325 return Cp; 2326 } 2327 Map<ExpVector, C> C = Cp.val; //getMap(); 2328 Map<ExpVector, C> A = val; 2329 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2330 ExpVector e = y.getKey(); 2331 C a = y.getValue(); 2332 ExpVector f = e.contract(1, pfac.nvar); 2333 C.put(f, a); 2334 } 2335 return Cp; 2336 } 2337 2338 2339 /** 2340 * Reverse variables. Used e.g. in opposite rings. 2341 * @return polynomial with reversed variables. 2342 */ 2343 public GenPolynomial<C> reverse(GenPolynomialRing<C> oring) { 2344 GenPolynomial<C> Cp = oring.getZERO().copy(); 2345 if (this.isZERO()) { 2346 return Cp; 2347 } 2348 int k = -1; 2349 if (oring.tord.getEvord2() != 0 && oring.partial) { 2350 k = oring.tord.getSplit(); 2351 } 2352 2353 Map<ExpVector, C> C = Cp.val; //getMap(); 2354 Map<ExpVector, C> A = val; 2355 ExpVector f; 2356 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2357 ExpVector e = y.getKey(); 2358 if (k >= 0) { 2359 f = e.reverse(k); 2360 } else { 2361 f = e.reverse(); 2362 } 2363 C a = y.getValue(); 2364 C.put(f, a); 2365 } 2366 return Cp; 2367 } 2368 2369 2370 /** 2371 * GenPolynomial inflate. Only for univariate 2372 * polynomials over fields. 2373 * @param e exponent. 2374 * @return this(x**e) 2375 */ 2376 public GenPolynomial<C> inflate(long e) { 2377 if (e == 1) { 2378 return this; 2379 } 2380 if (this.isZERO()) { 2381 return this; 2382 } 2383 if (ring.nvar != 1) { 2384 throw new IllegalArgumentException( 2385 this.getClass().getName() + " not univariate polynomial" + ring); 2386 } 2387 GenPolynomial<C> Cp = ring.getZERO().copy(); 2388 Map<ExpVector, C> C = Cp.val; //getMap(); 2389 Map<ExpVector, C> A = val; 2390 ExpVector f; 2391 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 2392 ExpVector g = y.getKey(); 2393 f = g.scalarMultiply(e); 2394 C a = y.getValue(); 2395 C.put(f, a); 2396 } 2397 return Cp; 2398 } 2399 2400 2401 /** 2402 * Iterator over coefficients. 2403 * @return val.values().iterator(). 2404 */ 2405 public Iterator<C> coefficientIterator() { 2406 return val.values().iterator(); 2407 } 2408 2409 2410 /** 2411 * Iterator over exponents. 2412 * @return val.keySet().iterator(). 2413 */ 2414 public Iterator<ExpVector> exponentIterator() { 2415 return val.keySet().iterator(); 2416 } 2417 2418 2419 /** 2420 * Iterator over monomials. 2421 * @return a PolyIterator. 2422 */ 2423 public Iterator<Monomial<C>> iterator() { 2424 return new PolyIterator<C>(val); 2425 } 2426 2427 2428 /** 2429 * Map a unary function to the coefficients. 2430 * @param f evaluation functor. 2431 * @return new polynomial with coefficients f(this(e)). 2432 */ 2433 public GenPolynomial<C> map(final UnaryFunctor<? super C, C> f) { 2434 GenPolynomial<C> n = ring.getZERO().copy(); 2435 SortedMap<ExpVector, C> nv = n.val; 2436 for (Monomial<C> m : this) { 2437 //logger.info("m = " + m); 2438 C c = f.eval(m.c); 2439 if (c != null && !c.isZERO()) { 2440 nv.put(m.e, c); 2441 } 2442 } 2443 return n; 2444 } 2445 2446 2447 /** 2448 * Returns the number of bits in the representation of this polynomial. 2449 * @return number of bits in the representation of this polynomial, 2450 * including sign bits. 2451 */ 2452 public long bitLength() { 2453 if (blen < 0L) { 2454 long n = 0L; 2455 for (Monomial<C> m : this) { 2456 n += m.e.bitLength(); 2457 //n += m.c.bitLength(); // TODO add bitLength to Element 2458 try { // hack 2459 Method method = m.c.getClass().getMethod("bitLength", (Class<?>[]) null); 2460 n += (Long) method.invoke(m.c, (Object[]) null); 2461 } catch (NoSuchMethodException e) { 2462 logger.error("Exception, class: " + m.c.getClass()); 2463 throw new RuntimeException(e); 2464 } catch (IllegalAccessException e) { 2465 logger.error("Exception, class: " + m.c.getClass()); 2466 throw new RuntimeException(e); 2467 } catch (InvocationTargetException e) { 2468 logger.error("Exception, class: " + m.c.getClass()); 2469 throw new RuntimeException(e); 2470 } 2471 } 2472 blen = n; 2473 //System.out.println("bitLength(poly) = " + blen); 2474 } 2475 return blen; 2476 } 2477 2478 //private void writeObject(java.io.ObjectOutputStream out) throws IOException { 2479 // out.defaultWriteObject(); 2480 //} 2481 2482 2483 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { 2484 in.defaultReadObject(); 2485 blen = -1; 2486 hash = -1; 2487 } 2488}