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