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