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