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