001    /*
002     * $Id: GenPolynomial.java 3749 2011-08-24 21:44:12Z kredel $
003     */
004    
005    package edu.jas.poly;
006    
007    
008    import java.util.Collections;
009    import java.util.Iterator;
010    import java.util.Map;
011    import java.util.SortedMap;
012    import java.util.TreeMap;
013    
014    import org.apache.log4j.Logger;
015    
016    import edu.jas.kern.PreemptingException;
017    import edu.jas.kern.PrettyPrint;
018    import edu.jas.structure.NotInvertibleException;
019    import edu.jas.structure.RingElem;
020    import edu.jas.structure.UnaryFunctor;
021    
022    
023    /**
024     * GenPolynomial generic polynomials implementing RingElem. n-variate ordered
025     * polynomials over C. Objects of this class are intended to be immutable. The
026     * implementation is based on TreeMap respectively SortedMap from exponents to
027     * coefficients. Only the coefficients are modeled with generic types, the
028     * exponents are fixed to ExpVector with long entries (this will eventually be
029     * changed in the future). C can also be a non integral domain, e.g. a
030     * ModInteger, i.e. it may contain zero divisors, since multiply() does now
031     * check for zeros. <b>Note:</b> multiply() now checks for wrong method dispatch
032     * for GenSolvablePolynomial.
033     * @param <C> coefficient type
034     * @author Heinz Kredel
035     */
036    public class GenPolynomial<C extends RingElem<C>> implements RingElem<GenPolynomial<C>>, /* not yet Polynomial<C> */
037    Iterable<Monomial<C>> {
038    
039    
040        /**
041         * The factory for the polynomial ring.
042         */
043        public final GenPolynomialRing<C> ring;
044    
045    
046        /**
047         * The data structure for polynomials.
048         */
049        protected final SortedMap<ExpVector, C> val; // do not change to TreeMap
050    
051    
052        private static final Logger logger = Logger.getLogger(GenPolynomial.class);
053    
054    
055        private final boolean debug = logger.isDebugEnabled();
056    
057    
058        // protected GenPolynomial() { ring = null; val = null; } // don't use
059    
060    
061        /**
062         * Private constructor for GenPolynomial.
063         * @param r polynomial ring factory.
064         * @param t TreeMap with correct ordering.
065         */
066        private GenPolynomial(GenPolynomialRing<C> r, TreeMap<ExpVector, C> t) {
067            ring = r;
068            val = t;
069            if (ring.checkPreempt) {
070                if (Thread.currentThread().isInterrupted()) {
071                    logger.debug("throw PreemptingException");
072                    throw new PreemptingException();
073                }
074            }
075        }
076    
077    
078        /**
079         * Constructor for zero GenPolynomial.
080         * @param r polynomial ring factory.
081         */
082        public GenPolynomial(GenPolynomialRing<C> r) {
083            this(r, new TreeMap<ExpVector, C>(r.tord.getDescendComparator()));
084        }
085    
086    
087        /**
088         * Constructor for GenPolynomial c * x<sup>e</sup>.
089         * @param r polynomial ring factory.
090         * @param c coefficient.
091         * @param e exponent.
092         */
093        public GenPolynomial(GenPolynomialRing<C> r, C c, ExpVector e) {
094            this(r);
095            if (!c.isZERO()) {
096                val.put(e, c);
097            }
098        }
099    
100    
101        /**
102         * Constructor for GenPolynomial c * x<sup>0</sup>.
103         * @param r polynomial ring factory.
104         * @param c coefficient.
105         */
106        public GenPolynomial(GenPolynomialRing<C> r, C c) {
107            this(r, c, r.evzero);
108        }
109    
110    
111        /**
112         * Constructor for GenPolynomial.
113         * @param r polynomial ring factory.
114         * @param v the SortedMap of some other polynomial.
115         */
116        protected GenPolynomial(GenPolynomialRing<C> r, SortedMap<ExpVector, C> v) {
117            this(r);
118            val.putAll(v); // assume no zero coefficients
119        }
120    
121    
122        /**
123         * Get the corresponding element factory.
124         * @return factory for this Element.
125         * @see edu.jas.structure.Element#factory()
126         */
127        public GenPolynomialRing<C> factory() {
128            return ring;
129        }
130    
131    
132        /**
133         * Clone this GenPolynomial.
134         * @see java.lang.Object#clone()
135         */
136        @Override
137        public GenPolynomial<C> clone() {
138            //return ring.copy(this);
139            return new GenPolynomial<C>(ring, this.val);
140        }
141    
142    
143        /**
144         * Length of GenPolynomial.
145         * @return number of coefficients of this GenPolynomial.
146         */
147        public int length() {
148            return val.size();
149        }
150    
151    
152        /**
153         * ExpVector to coefficient map of GenPolynomial.
154         * @return val as unmodifiable SortedMap.
155         */
156        public SortedMap<ExpVector, C> getMap() {
157            // return val;
158            return Collections.<ExpVector, C> unmodifiableSortedMap(val);
159        }
160    
161    
162        /**
163         * Put an ExpVector to coefficient entry into the internal map of this
164         * GenPolynomial. <b>Note:</b> Do not use this method unless you are
165         * constructing a new polynomial. this is modified and breaks the
166         * immutability promise of this class.
167         * @param c coefficient.
168         * @param e exponent.
169         */
170        public void doPutToMap(ExpVector e, C c) {
171            if (false && debug) {
172                C a = val.get(e);
173                if (a != null) {
174                    logger.info("map entry exists " + e + " to " + a + " new " + c);
175                }
176            }
177            if (!c.isZERO()) {
178                val.put(e, c);
179            }
180        }
181    
182    
183        /**
184         * Put an a sorted map of exponents to coefficients into the internal map of
185         * this GenPolynomial. <b>Note:</b> Do not use this method unless you are
186         * constructing a new polynomial. this is modified and breaks the
187         * immutability promise of this class.
188         * @param vals sorted map of exponents and coefficients.
189         */
190        public void doPutToMap(SortedMap<ExpVector, C> vals) {
191            for (Map.Entry<ExpVector, C> me : vals.entrySet()) {
192                ExpVector e = me.getKey();
193                if (false && debug) {
194                    C a = val.get(e);
195                    if (a != null) {
196                        logger.info("map entry exists " + e + " to " + a + " new " + me.getValue());
197                    }
198                }
199                C c = me.getValue();
200                if (!c.isZERO()) {
201                    val.put(e, c);
202                }
203            }
204        }
205    
206    
207        /**
208         * String representation of GenPolynomial.
209         * @see java.lang.Object#toString()
210         */
211        @Override
212        public String toString() {
213            if (ring.vars != null) {
214                return toString(ring.vars);
215            }
216            StringBuffer s = new StringBuffer();
217            s.append(this.getClass().getSimpleName() + ":");
218            s.append(ring.coFac.getClass().getSimpleName());
219            if (ring.coFac.characteristic().signum() != 0) {
220                s.append("(" + ring.coFac.characteristic() + ")");
221            }
222            s.append("[ ");
223            boolean first = true;
224            for (Map.Entry<ExpVector, C> m : val.entrySet()) {
225                if (first) {
226                    first = false;
227                } else {
228                    s.append(", ");
229                }
230                s.append(m.getValue().toString());
231                s.append(" ");
232                s.append(m.getKey().toString());
233            }
234            s.append(" ] "); // no not use: ring.toString() );
235            return s.toString();
236        }
237    
238    
239        /**
240         * String representation of GenPolynomial.
241         * @param v names for variables.
242         * @see java.lang.Object#toString()
243         */
244        public String toString(String[] v) {
245            StringBuffer s = new StringBuffer();
246            if (PrettyPrint.isTrue()) {
247                if (val.size() == 0) {
248                    s.append("0");
249                } else {
250                    // s.append( "( " );
251                    boolean first = true;
252                    for (Map.Entry<ExpVector, C> m : val.entrySet()) {
253                        C c = m.getValue();
254                        if (first) {
255                            first = false;
256                        } else {
257                            if (c.signum() < 0) {
258                                s.append(" - ");
259                                c = c.negate();
260                            } else {
261                                s.append(" + ");
262                            }
263                        }
264                        ExpVector e = m.getKey();
265                        if (!c.isONE() || e.isZERO()) {
266                            if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) {
267                                s.append("{ ");
268                            }
269                            s.append(c.toString());
270                            if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) {
271                                s.append(" }");
272                            }
273                            s.append(" ");
274                        }
275                        if (e != null && v != null) {
276                            s.append(e.toString(v));
277                        } else {
278                            s.append(e);
279                        }
280                    }
281                    //s.append(" )");
282                }
283            } else {
284                s.append(this.getClass().getSimpleName() + "[ ");
285                if (val.size() == 0) {
286                    s.append("0");
287                } else {
288                    boolean first = true;
289                    for (Map.Entry<ExpVector, C> m : val.entrySet()) {
290                        C c = m.getValue();
291                        if (first) {
292                            first = false;
293                        } else {
294                            if (c.signum() < 0) {
295                                s.append(" - ");
296                                c = c.negate();
297                            } else {
298                                s.append(" + ");
299                            }
300                        }
301                        ExpVector e = m.getKey();
302                        if (!c.isONE() || e.isZERO()) {
303                            s.append(c.toString());
304                            s.append(" ");
305                        }
306                        s.append(e.toString(v));
307                    }
308                }
309                s.append(" ] "); // no not use: ring.toString() );
310            }
311            return s.toString();
312        }
313    
314    
315        /**
316         * Get a scripting compatible string representation.
317         * @return script compatible representation for this Element.
318         * @see edu.jas.structure.Element#toScript()
319         */
320        //JAVA6only: @Override
321        public String toScript() {
322            // Python case
323            if (isZERO()) {
324                return "0";
325            }
326            StringBuffer s = new StringBuffer();
327            if (val.size() > 1) {
328                s.append("( ");
329            }
330            String[] v = ring.vars;
331            if (v == null) {
332                v = GenPolynomialRing.newVars("x", ring.nvar);
333            }
334            boolean parenthesis = false;
335            if (ring.coFac instanceof GenPolynomialRing || ring.coFac instanceof AlgebraicNumberRing
336            // || ring.coFac instanceof RealAlgebraicRing
337            ) {
338                // inactive: parenthesis = true;
339            }
340            boolean first = true;
341            for (Map.Entry<ExpVector, C> m : val.entrySet()) {
342                C c = m.getValue();
343                if (first) {
344                    first = false;
345                } else {
346                    if (c.signum() < 0) {
347                        s.append(" - ");
348                        c = c.negate();
349                    } else {
350                        s.append(" + ");
351                    }
352                }
353                ExpVector e = m.getKey();
354                if (!c.isONE() || e.isZERO()) {
355                    if (parenthesis) {
356                        s.append("( ");
357                    }
358                    s.append(c.toScript());
359                    if (parenthesis) {
360                        s.append(" )");
361                    }
362                    if (!e.isZERO()) {
363                        s.append(" * ");
364                    }
365                }
366                s.append(e.toScript(v));
367            }
368            if (val.size() > 1) {
369                s.append(" )");
370            }
371            return s.toString();
372        }
373    
374    
375        /**
376         * Get a scripting compatible string representation of the factory.
377         * @return script compatible representation for this ElemFactory.
378         * @see edu.jas.structure.Element#toScriptFactory()
379         */
380        //JAVA6only: @Override
381        public String toScriptFactory() {
382            // Python case
383            return factory().toScript();
384        }
385    
386    
387        /**
388         * Is GenPolynomial&lt;C&gt; zero.
389         * @return If this is 0 then true is returned, else false.
390         * @see edu.jas.structure.RingElem#isZERO()
391         */
392        public boolean isZERO() {
393            return (val.size() == 0);
394        }
395    
396    
397        /**
398         * Is GenPolynomial&lt;C&gt; one.
399         * @return If this is 1 then true is returned, else false.
400         * @see edu.jas.structure.RingElem#isONE()
401         */
402        public boolean isONE() {
403            if (val.size() != 1) {
404                return false;
405            }
406            C c = val.get(ring.evzero);
407            if (c == null) {
408                return false;
409            }
410            if (!c.isONE()) {
411                return false;
412            }
413            return true;
414        }
415    
416    
417        /**
418         * Is GenPolynomial&lt;C&gt; a unit.
419         * @return If this is a unit then true is returned, else false.
420         * @see edu.jas.structure.RingElem#isUnit()
421         */
422        public boolean isUnit() {
423            if (val.size() != 1) {
424                return false;
425            }
426            C c = val.get(ring.evzero);
427            if (c == null) {
428                return false;
429            }
430            if (c.isUnit()) {
431                return true;
432            }
433            return false;
434        }
435    
436    
437        /**
438         * Is GenPolynomial&lt;C&gt; a constant.
439         * @return If this is a constant polynomial then true is returned, else
440         *         false.
441         */
442        public boolean isConstant() {
443            if (val.size() != 1) {
444                return false;
445            }
446            C c = val.get(ring.evzero);
447            if (c == null) {
448                return false;
449            }
450            return true;
451        }
452    
453    
454        /**
455         * Comparison with any other object.
456         * @see java.lang.Object#equals(java.lang.Object)
457         */
458        @Override
459        @SuppressWarnings("unchecked")
460        public boolean equals(Object B) {
461            if (!(B instanceof GenPolynomial)) {
462                return false;
463            }
464            GenPolynomial<C> a = null;
465            try {
466                a = (GenPolynomial<C>) B;
467            } catch (ClassCastException ignored) {
468            }
469            if (a == null) {
470                return false;
471            }
472            return this.compareTo(a) == 0;
473        }
474    
475    
476        /**
477         * Hash code for this polynomial.
478         * @see java.lang.Object#hashCode()
479         */
480        @Override
481        public int hashCode() {
482            int h;
483            h = (ring.hashCode() << 27);
484            h += val.hashCode();
485            return h;
486        }
487    
488    
489        /**
490         * GenPolynomial comparison.
491         * @param b GenPolynomial.
492         * @return sign(this-b).
493         */
494        public int compareTo(GenPolynomial<C> b) {
495            if (b == null) {
496                return 1;
497            }
498            SortedMap<ExpVector, C> av = this.val;
499            SortedMap<ExpVector, C> bv = b.val;
500            Iterator<ExpVector> ai = av.keySet().iterator();
501            Iterator<ExpVector> bi = bv.keySet().iterator();
502            int s = 0;
503            int c = 0;
504            while (ai.hasNext() && bi.hasNext()) {
505                ExpVector ae = ai.next();
506                ExpVector be = bi.next();
507                s = ae.compareTo(be);
508                //System.out.println("s = " + s + ", " + ae + ", " +be);
509                if (s != 0) {
510                    return s;
511                }
512                if (c == 0) {
513                    C ac = av.get(ae);
514                    C bc = bv.get(be);
515                    c = ac.compareTo(bc);
516                }
517            }
518            if (ai.hasNext()) {
519                return 1;
520            }
521            if (bi.hasNext()) {
522                return -1;
523            }
524            // now all keys are equal
525            return c;
526        }
527    
528    
529        /**
530         * GenPolynomial signum.
531         * @return sign(ldcf(this)).
532         */
533        public int signum() {
534            if (this.isZERO()) {
535                return 0;
536            }
537            ExpVector t = val.firstKey();
538            C c = val.get(t);
539            return c.signum();
540        }
541    
542    
543        /**
544         * Number of variables.
545         * @return ring.nvar.
546         */
547        public int numberOfVariables() {
548            return ring.nvar;
549        }
550    
551    
552        /**
553         * Leading monomial.
554         * @return first map entry.
555         */
556        public Map.Entry<ExpVector, C> leadingMonomial() {
557            if (val.size() == 0)
558                return null;
559            Iterator<Map.Entry<ExpVector, C>> ai = val.entrySet().iterator();
560            return ai.next();
561        }
562    
563    
564        /**
565         * Leading exponent vector.
566         * @return first exponent.
567         */
568        public ExpVector leadingExpVector() {
569            if (val.size() == 0) {
570                return null; // ring.evzero or null ?;
571            }
572            return val.firstKey();
573        }
574    
575    
576        /**
577         * Trailing exponent vector.
578         * @return last exponent.
579         */
580        public ExpVector trailingExpVector() {
581            if (val.size() == 0) {
582                return null; // ring.evzero or null ?;
583            }
584            return val.lastKey();
585        }
586    
587    
588        /**
589         * Leading base coefficient.
590         * @return first coefficient.
591         */
592        public C leadingBaseCoefficient() {
593            if (val.size() == 0) {
594                return ring.coFac.getZERO();
595            }
596            return val.get(val.firstKey());
597        }
598    
599    
600        /**
601         * Trailing base coefficient.
602         * @return coefficient of constant term.
603         */
604        public C trailingBaseCoefficient() {
605            C c = val.get(ring.evzero);
606            if (c == null) {
607                return ring.coFac.getZERO();
608            }
609            return c;
610        }
611    
612    
613        /**
614         * Coefficient.
615         * @param e exponent.
616         * @return coefficient for given exponent.
617         */
618        public C coefficient(ExpVector e) {
619            C c = val.get(e);
620            if (c == null) {
621                c = ring.coFac.getZERO();
622            }
623            return c;
624        }
625    
626    
627        /**
628         * Reductum.
629         * @return this - leading monomial.
630         */
631        public GenPolynomial<C> reductum() {
632            if (val.size() <= 1) {
633                return ring.getZERO();
634            }
635            Iterator<ExpVector> ai = val.keySet().iterator();
636            ExpVector lt = ai.next();
637            lt = ai.next(); // size > 1
638            SortedMap<ExpVector, C> red = val.tailMap(lt);
639            return new GenPolynomial<C>(ring, red);
640        }
641    
642    
643        /**
644         * Degree in variable i.
645         * @return maximal degree in the variable i.
646         */
647        public long degree(int i) {
648            if (val.size() == 0) {
649                return 0; // 0 or -1 ?;
650            }
651            int j = ring.nvar - 1 - i;
652            long deg = 0;
653            for (ExpVector e : val.keySet()) {
654                long d = e.getVal(j);
655                if (d > deg) {
656                    deg = d;
657                }
658            }
659            return deg;
660        }
661    
662    
663        /**
664         * Maximal degree.
665         * @return maximal degree in any variables.
666         */
667        public long degree() {
668            if (val.size() == 0) {
669                return 0; // 0 or -1 ?;
670            }
671            long deg = 0;
672            for (ExpVector e : val.keySet()) {
673                long d = e.maxDeg();
674                if (d > deg) {
675                    deg = d;
676                }
677            }
678            return deg;
679        }
680    
681    
682        /**
683         * Maximal degree vector.
684         * @return maximal degree vector of all variables.
685         */
686        public ExpVector degreeVector() {
687            ExpVector deg = ring.evzero;
688            if (val.size() == 0) {
689                return deg;
690            }
691            for (ExpVector e : val.keySet()) {
692                deg = deg.lcm(e);
693            }
694            return deg;
695        }
696    
697    
698        /**
699         * GenPolynomial maximum norm.
700         * @return ||this||.
701         */
702        public C maxNorm() {
703            C n = ring.getZEROCoefficient();
704            for (C c : val.values()) {
705                C x = c.abs();
706                if (n.compareTo(x) < 0) {
707                    n = x;
708                }
709            }
710            return n;
711        }
712    
713    
714        /**
715         * GenPolynomial sum norm.
716         * @return sum of all absolute values of coefficients.
717         */
718        public C sumNorm() {
719            C n = ring.getZEROCoefficient();
720            for (C c : val.values()) {
721                C x = c.abs();
722                n = n.sum(x);
723            }
724            return n;
725        }
726    
727    
728        /**
729         * GenPolynomial summation.
730         * @param S GenPolynomial.
731         * @return this+S.
732         */
733        //public <T extends GenPolynomial<C>> T sum(T /*GenPolynomial<C>*/ S) {
734        public GenPolynomial<C> sum(GenPolynomial<C> S) {
735            if (S == null) {
736                return this;
737            }
738            if (S.isZERO()) {
739                return this;
740            }
741            if (this.isZERO()) {
742                return S;
743            }
744            assert (ring.nvar == S.ring.nvar);
745            GenPolynomial<C> n = this.clone(); //new GenPolynomial<C>(ring, val); 
746            SortedMap<ExpVector, C> nv = n.val;
747            SortedMap<ExpVector, C> sv = S.val;
748            for (ExpVector e : sv.keySet()) {
749                C x = nv.get(e);
750                C y = sv.get(e); // assert y != null
751                if (x != null) {
752                    x = x.sum(y);
753                    if (!x.isZERO()) {
754                        nv.put(e, x);
755                    } else {
756                        nv.remove(e);
757                    }
758                } else {
759                    nv.put(e, y);
760                }
761            }
762            return n;
763        }
764    
765    
766        /**
767         * GenPolynomial addition. This method is not very efficient, since this is
768         * copied.
769         * @param a coefficient.
770         * @param e exponent.
771         * @return this + a x<sup>e</sup>.
772         */
773        public GenPolynomial<C> sum(C a, ExpVector e) {
774            if (a == null) {
775                return this;
776            }
777            if (a.isZERO()) {
778                return this;
779            }
780            GenPolynomial<C> n = this.clone(); //new GenPolynomial<C>(ring, val); 
781            SortedMap<ExpVector, C> nv = n.val;
782            //if ( nv.size() == 0 ) { nv.put(e,a); return n; }
783            C x = nv.get(e);
784            if (x != null) {
785                x = x.sum(a);
786                if (!x.isZERO()) {
787                    nv.put(e, x);
788                } else {
789                    nv.remove(e);
790                }
791            } else {
792                nv.put(e, a);
793            }
794            return n;
795        }
796    
797    
798        /**
799         * GenPolynomial addition. This method is not very efficient, since this is
800         * copied.
801         * @param a coefficient.
802         * @return this + a x<sup>0</sup>.
803         */
804        public GenPolynomial<C> sum(C a) {
805            return sum(a, ring.evzero);
806        }
807    
808    
809        /**
810         * GenPolynomial subtraction.
811         * @param S GenPolynomial.
812         * @return this-S.
813         */
814        public GenPolynomial<C> subtract(GenPolynomial<C> S) {
815            if (S == null) {
816                return this;
817            }
818            if (S.isZERO()) {
819                return this;
820            }
821            if (this.isZERO()) {
822                return S.negate();
823            }
824            assert (ring.nvar == S.ring.nvar);
825            GenPolynomial<C> n = this.clone(); //new GenPolynomial<C>(ring, val); 
826            SortedMap<ExpVector, C> nv = n.val;
827            SortedMap<ExpVector, C> sv = S.val;
828            for (ExpVector e : sv.keySet()) {
829                C x = nv.get(e);
830                C y = sv.get(e); // assert y != null
831                if (x != null) {
832                    x = x.subtract(y);
833                    if (!x.isZERO()) {
834                        nv.put(e, x);
835                    } else {
836                        nv.remove(e);
837                    }
838                } else {
839                    nv.put(e, y.negate());
840                }
841            }
842            return n;
843        }
844    
845    
846        /**
847         * GenPolynomial subtraction. This method is not very efficient, since this
848         * is copied.
849         * @param a coefficient.
850         * @param e exponent.
851         * @return this - a x<sup>e</sup>.
852         */
853        public GenPolynomial<C> subtract(C a, ExpVector e) {
854            if (a == null) {
855                return this;
856            }
857            if (a.isZERO()) {
858                return this;
859            }
860            GenPolynomial<C> n = this.clone(); //new GenPolynomial<C>(ring, val); 
861            SortedMap<ExpVector, C> nv = n.val;
862            C x = nv.get(e);
863            if (x != null) {
864                x = x.subtract(a);
865                if (!x.isZERO()) {
866                    nv.put(e, x);
867                } else {
868                    nv.remove(e);
869                }
870            } else {
871                nv.put(e, a.negate());
872            }
873            return n;
874        }
875    
876    
877        /**
878         * GenPolynomial subtract. This method is not very efficient, since this is
879         * copied.
880         * @param a coefficient.
881         * @return this + a x<sup>0</sup>.
882         */
883        public GenPolynomial<C> subtract(C a) {
884            return subtract(a, ring.evzero);
885        }
886    
887    
888        /**
889         * GenPolynomial negation.
890         * @return -this.
891         */
892        public GenPolynomial<C> negate() {
893            GenPolynomial<C> n = ring.getZERO().clone();
894            //new GenPolynomial<C>(ring, ring.getZERO().val);
895            SortedMap<ExpVector, C> v = n.val;
896            for (Map.Entry<ExpVector, C> m : val.entrySet()) {
897                C x = m.getValue(); // != null, 0
898                v.put(m.getKey(), x.negate());
899                // or m.setValue( x.negate() ) if this cloned 
900            }
901            return n;
902        }
903    
904    
905        /**
906         * GenPolynomial absolute value, i.e. leadingCoefficient &gt; 0.
907         * @return abs(this).
908         */
909        public GenPolynomial<C> abs() {
910            if (leadingBaseCoefficient().signum() < 0) {
911                return this.negate();
912            }
913            return this;
914        }
915    
916    
917        /**
918         * GenPolynomial multiplication.
919         * @param S GenPolynomial.
920         * @return this*S.
921         */
922        public GenPolynomial<C> multiply(GenPolynomial<C> S) {
923            if (S == null) {
924                return ring.getZERO();
925            }
926            if (S.isZERO()) {
927                return ring.getZERO();
928            }
929            if (this.isZERO()) {
930                return this;
931            }
932            assert (ring.nvar == S.ring.nvar);
933            if (this instanceof GenSolvablePolynomial || S instanceof GenSolvablePolynomial) {
934                //throw new RuntimeException("wrong method dispatch in JRE ");
935                logger.warn("wrong method dispatch in JRE (S) - trying to fix");
936                GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this;
937                GenSolvablePolynomial<C> Sp = (GenSolvablePolynomial<C>) S;
938                return T.multiply(Sp);
939            }
940            GenPolynomial<C> p = ring.getZERO().clone();
941            SortedMap<ExpVector, C> pv = p.val;
942            for (Map.Entry<ExpVector, C> m1 : val.entrySet()) {
943                C c1 = m1.getValue();
944                ExpVector e1 = m1.getKey();
945                for (Map.Entry<ExpVector, C> m2 : S.val.entrySet()) {
946                    C c2 = m2.getValue();
947                    ExpVector e2 = m2.getKey();
948                    C c = c1.multiply(c2); // check non zero if not domain
949                    if (!c.isZERO()) {
950                        ExpVector e = e1.sum(e2);
951                        C c0 = pv.get(e);
952                        if (c0 == null) {
953                            pv.put(e, c);
954                        } else {
955                            c0 = c0.sum(c);
956                            if (!c0.isZERO()) {
957                                pv.put(e, c0);
958                            } else {
959                                pv.remove(e);
960                            }
961                        }
962                    }
963                }
964            }
965            return p;
966        }
967    
968    
969        /**
970         * GenPolynomial multiplication. Product with coefficient ring element.
971         * @param s coefficient.
972         * @return this*s.
973         */
974        public GenPolynomial<C> multiply(C s) {
975            if (s == null) {
976                return ring.getZERO();
977            }
978            if (s.isZERO()) {
979                return ring.getZERO();
980            }
981            if (this.isZERO()) {
982                return this;
983            }
984            GenPolynomial<C> p = ring.getZERO().clone();
985            SortedMap<ExpVector, C> pv = p.val;
986            for (Map.Entry<ExpVector, C> m1 : val.entrySet()) {
987                C c1 = m1.getValue();
988                ExpVector e1 = m1.getKey();
989                C c = c1.multiply(s); // check non zero if not domain
990                if (!c.isZERO()) {
991                    pv.put(e1, c); // or m1.setValue( c )
992                }
993            }
994            return p;
995        }
996    
997    
998        /**
999         * GenPolynomial monic, i.e. leadingCoefficient == 1. If leadingCoefficient
1000         * is not invertible returns this unmodified.
1001         * @return monic(this).
1002         */
1003        public GenPolynomial<C> monic() {
1004            if (this.isZERO()) {
1005                return this;
1006            }
1007            C lc = leadingBaseCoefficient();
1008            if (!lc.isUnit()) {
1009                //System.out.println("lc = "+lc);
1010                return this;
1011            }
1012            C lm = lc.inverse();
1013            return multiply(lm);
1014        }
1015    
1016    
1017        /**
1018         * GenPolynomial multiplication. Product with ring element and exponent
1019         * vector.
1020         * @param s coefficient.
1021         * @param e exponent.
1022         * @return this * s x<sup>e</sup>.
1023         */
1024        public GenPolynomial<C> multiply(C s, ExpVector e) {
1025            if (s == null) {
1026                return ring.getZERO();
1027            }
1028            if (s.isZERO()) {
1029                return ring.getZERO();
1030            }
1031            if (this.isZERO()) {
1032                return this;
1033            }
1034            if (this instanceof GenSolvablePolynomial) {
1035                //throw new RuntimeException("wrong method dispatch in JRE ");
1036                logger.warn("wrong method dispatch in JRE (s,e) - trying to fix");
1037                GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this;
1038                return T.multiply(s, e);
1039            }
1040            GenPolynomial<C> p = ring.getZERO().clone();
1041            SortedMap<ExpVector, C> pv = p.val;
1042            for (Map.Entry<ExpVector, C> m1 : val.entrySet()) {
1043                C c1 = m1.getValue();
1044                ExpVector e1 = m1.getKey();
1045                C c = c1.multiply(s); // check non zero if not domain
1046                if (!c.isZERO()) {
1047                    ExpVector e2 = e1.sum(e);
1048                    pv.put(e2, c);
1049                }
1050            }
1051            return p;
1052        }
1053    
1054    
1055        /**
1056         * GenPolynomial multiplication. Product with exponent vector.
1057         * @param e exponent (!= null).
1058         * @return this * x<sup>e</sup>.
1059         */
1060        public GenPolynomial<C> multiply(ExpVector e) {
1061            // assert e != null. This is never allowed.
1062            if (this.isZERO()) {
1063                return this;
1064            }
1065            if (this instanceof GenSolvablePolynomial) {
1066                //throw new RuntimeException("wrong method dispatch in JRE ");
1067                logger.warn("wrong method dispatch in JRE (e) - trying to fix");
1068                GenSolvablePolynomial<C> T = (GenSolvablePolynomial<C>) this;
1069                return T.multiply(e);
1070            }
1071            GenPolynomial<C> p = ring.getZERO().clone();
1072            SortedMap<ExpVector, C> pv = p.val;
1073            for (Map.Entry<ExpVector, C> m1 : val.entrySet()) {
1074                C c1 = m1.getValue();
1075                ExpVector e1 = m1.getKey();
1076                ExpVector e2 = e1.sum(e);
1077                pv.put(e2, c1);
1078            }
1079            return p;
1080        }
1081    
1082    
1083        /**
1084         * GenPolynomial multiplication. Product with 'monomial'.
1085         * @param m 'monomial'.
1086         * @return this * m.
1087         */
1088        public GenPolynomial<C> multiply(Map.Entry<ExpVector, C> m) {
1089            if (m == null) {
1090                return ring.getZERO();
1091            }
1092            return multiply(m.getValue(), m.getKey());
1093        }
1094    
1095    
1096        /**
1097         * GenPolynomial division. Division by coefficient ring element. Fails, if
1098         * exact division is not possible.
1099         * @param s coefficient.
1100         * @return this/s.
1101         */
1102        public GenPolynomial<C> divide(C s) {
1103            if (s == null || s.isZERO()) {
1104                throw new ArithmeticException(this.getClass().getName() + " division by zero");
1105            }
1106            if (this.isZERO()) {
1107                return this;
1108            }
1109            //C t = s.inverse();
1110            //return multiply(t);
1111            GenPolynomial<C> p = ring.getZERO().clone();
1112            SortedMap<ExpVector, C> pv = p.val;
1113            for (Map.Entry<ExpVector, C> m : val.entrySet()) {
1114                ExpVector e = m.getKey();
1115                C c1 = m.getValue();
1116                C c = c1.divide(s);
1117                if (false) {
1118                    C x = c1.remainder(s);
1119                    if (!x.isZERO()) {
1120                        System.out.println("divide x = " + x);
1121                        throw new ArithmeticException(this.getClass().getName() + " no exact division: " + c1
1122                                        + "/" + s);
1123                    }
1124                }
1125                if (c.isZERO()) {
1126                    throw new ArithmeticException(this.getClass().getName() + " no exact division: " + c1 + "/"
1127                                    + s + ", in " + this);
1128                }
1129                pv.put(e, c); // or m1.setValue( c )
1130            }
1131            return p;
1132        }
1133    
1134    
1135        /**
1136         * GenPolynomial division with remainder. Fails, if exact division by
1137         * leading base coefficient is not possible. Meaningful only for univariate
1138         * polynomials over fields, but works in any case.
1139         * @param S nonzero GenPolynomial with invertible leading coefficient.
1140         * @return [ quotient , remainder ] with this = quotient * S + remainder and
1141         *         deg(remainder) &lt; deg(S) or remiander = 0.
1142         * @see edu.jas.poly.PolyUtil#basePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
1143         *      .
1144         */
1145        @SuppressWarnings("unchecked")
1146        public GenPolynomial<C>[] quotientRemainder(GenPolynomial<C> S) {
1147            if (S == null || S.isZERO()) {
1148                throw new ArithmeticException(this.getClass().getName() + " division by zero");
1149            }
1150            C c = S.leadingBaseCoefficient();
1151            if (!c.isUnit()) {
1152                throw new ArithmeticException(this.getClass().getName() + " lbcf not invertible " + c);
1153            }
1154            C ci = c.inverse();
1155            assert (ring.nvar == S.ring.nvar);
1156            ExpVector e = S.leadingExpVector();
1157            GenPolynomial<C> h;
1158            GenPolynomial<C> q = ring.getZERO().clone();
1159            GenPolynomial<C> r = this.clone();
1160            while (!r.isZERO()) {
1161                ExpVector f = r.leadingExpVector();
1162                if (f.multipleOf(e)) {
1163                    C a = r.leadingBaseCoefficient();
1164                    f = f.subtract(e);
1165                    a = a.multiply(ci);
1166                    q = q.sum(a, f);
1167                    h = S.multiply(a, f);
1168                    r = r.subtract(h);
1169                } else {
1170                    break;
1171                }
1172            }
1173            GenPolynomial<C>[] ret = new GenPolynomial[2];
1174            ret[0] = q;
1175            ret[1] = r;
1176            return ret;
1177        }
1178    
1179    
1180        /**
1181         * GenPolynomial division with remainder. Fails, if exact division by
1182         * leading base coefficient is not possible. Meaningful only for univariate
1183         * polynomials over fields, but works in any case.
1184         * @param S nonzero GenPolynomial with invertible leading coefficient.
1185         * @return [ quotient , remainder ] with this = quotient * S + remainder and
1186         *         deg(remainder) &lt; deg(S) or remiander = 0.
1187         * @see edu.jas.poly.PolyUtil#basePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
1188         *      .
1189         * @deprecated use quotientRemainder()
1190         */
1191        @Deprecated
1192        public GenPolynomial<C>[] divideAndRemainder(GenPolynomial<C> S) {
1193            return quotientRemainder(S);
1194        }
1195    
1196    
1197        /**
1198         * GenPolynomial division. Fails, if exact division by leading base
1199         * coefficient is not possible. Meaningful only for univariate polynomials
1200         * over fields, but works in any case.
1201         * @param S nonzero GenPolynomial with invertible leading coefficient.
1202         * @return quotient with this = quotient * S + remainder.
1203         * @see edu.jas.poly.PolyUtil#basePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
1204         *      .
1205         */
1206        public GenPolynomial<C> divide(GenPolynomial<C> S) {
1207            return quotientRemainder(S)[0];
1208        }
1209    
1210    
1211        /**
1212         * GenPolynomial remainder. Fails, if exact division by leading base
1213         * coefficient is not possible. Meaningful only for univariate polynomials
1214         * over fields, but works in any case.
1215         * @param S nonzero GenPolynomial with invertible leading coefficient.
1216         * @return remainder with this = quotient * S + remainder.
1217         * @see edu.jas.poly.PolyUtil#basePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
1218         *      .
1219         */
1220        public GenPolynomial<C> remainder(GenPolynomial<C> S) {
1221            if (S == null || S.isZERO()) {
1222                throw new ArithmeticException(this.getClass().getName() + " division by zero");
1223            }
1224            C c = S.leadingBaseCoefficient();
1225            if (!c.isUnit()) {
1226                throw new ArithmeticException(this.getClass().getName() + " lbc not invertible " + c);
1227            }
1228            C ci = c.inverse();
1229            assert (ring.nvar == S.ring.nvar);
1230            ExpVector e = S.leadingExpVector();
1231            GenPolynomial<C> h;
1232            GenPolynomial<C> r = this.clone();
1233            while (!r.isZERO()) {
1234                ExpVector f = r.leadingExpVector();
1235                if (f.multipleOf(e)) {
1236                    C a = r.leadingBaseCoefficient();
1237                    f = f.subtract(e);
1238                    //logger.info("red div = " + e);
1239                    a = a.multiply(ci);
1240                    h = S.multiply(a, f);
1241                    r = r.subtract(h);
1242                } else {
1243                    break;
1244                }
1245            }
1246            return r;
1247        }
1248    
1249    
1250        /**
1251         * GenPolynomial greatest common divisor. Only for univariate polynomials
1252         * over fields.
1253         * @param S GenPolynomial.
1254         * @return gcd(this,S).
1255         */
1256        public GenPolynomial<C> gcd(GenPolynomial<C> S) {
1257            if (S == null || S.isZERO()) {
1258                return this;
1259            }
1260            if (this.isZERO()) {
1261                return S;
1262            }
1263            if (ring.nvar != 1) {
1264                throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials"
1265                                + ring);
1266            }
1267            GenPolynomial<C> x;
1268            GenPolynomial<C> q = this;
1269            GenPolynomial<C> r = S;
1270            while (!r.isZERO()) {
1271                x = q.remainder(r);
1272                q = r;
1273                r = x;
1274            }
1275            return q.monic(); // normalize
1276        }
1277    
1278    
1279        /**
1280         * GenPolynomial extended greatest comon divisor. Only for univariate
1281         * polynomials over fields.
1282         * @param S GenPolynomial.
1283         * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
1284         */
1285        @SuppressWarnings("unchecked")
1286        public GenPolynomial<C>[] egcd(GenPolynomial<C> S) {
1287            GenPolynomial<C>[] ret = new GenPolynomial[3];
1288            ret[0] = null;
1289            ret[1] = null;
1290            ret[2] = null;
1291            if (S == null || S.isZERO()) {
1292                ret[0] = this;
1293                ret[1] = this.ring.getONE();
1294                ret[2] = this.ring.getZERO();
1295                return ret;
1296            }
1297            if (this.isZERO()) {
1298                ret[0] = S;
1299                ret[1] = this.ring.getZERO();
1300                ret[2] = this.ring.getONE();
1301                return ret;
1302            }
1303            if (ring.nvar != 1) {
1304                throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials"
1305                                + ring);
1306            }
1307            if (this.isConstant() && S.isConstant()) {
1308                C t = this.leadingBaseCoefficient();
1309                C s = S.leadingBaseCoefficient();
1310                C[] gg = t.egcd(s);
1311                //System.out.println("coeff gcd = " + Arrays.toString(gg));
1312                GenPolynomial<C> z = this.ring.getZERO();
1313                ret[0] = z.sum(gg[0]);
1314                ret[1] = z.sum(gg[1]);
1315                ret[2] = z.sum(gg[2]);
1316                return ret;
1317            }
1318            GenPolynomial<C>[] qr;
1319            GenPolynomial<C> q = this;
1320            GenPolynomial<C> r = S;
1321            GenPolynomial<C> c1 = ring.getONE().clone();
1322            GenPolynomial<C> d1 = ring.getZERO().clone();
1323            GenPolynomial<C> c2 = ring.getZERO().clone();
1324            GenPolynomial<C> d2 = ring.getONE().clone();
1325            GenPolynomial<C> x1;
1326            GenPolynomial<C> x2;
1327            while (!r.isZERO()) {
1328                qr = q.quotientRemainder(r);
1329                q = qr[0];
1330                x1 = c1.subtract(q.multiply(d1));
1331                x2 = c2.subtract(q.multiply(d2));
1332                c1 = d1;
1333                c2 = d2;
1334                d1 = x1;
1335                d2 = x2;
1336                q = r;
1337                r = qr[1];
1338            }
1339            // normalize ldcf(q) to 1, i.e. make monic
1340            C g = q.leadingBaseCoefficient();
1341            if (g.isUnit()) {
1342                C h = g.inverse();
1343                q = q.multiply(h);
1344                c1 = c1.multiply(h);
1345                c2 = c2.multiply(h);
1346            }
1347            //assert ( ((c1.multiply(this)).sum( c2.multiply(S)).equals(q) )); 
1348            ret[0] = q;
1349            ret[1] = c1;
1350            ret[2] = c2;
1351            return ret;
1352        }
1353    
1354    
1355        /**
1356         * GenPolynomial half extended greatest comon divisor. Only for univariate
1357         * polynomials over fields.
1358         * @param S GenPolynomial.
1359         * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S).
1360         */
1361        @SuppressWarnings("unchecked")
1362        public GenPolynomial<C>[] hegcd(GenPolynomial<C> S) {
1363            GenPolynomial<C>[] ret = new GenPolynomial[2];
1364            ret[0] = null;
1365            ret[1] = null;
1366            if (S == null || S.isZERO()) {
1367                ret[0] = this;
1368                ret[1] = this.ring.getONE();
1369                return ret;
1370            }
1371            if (this.isZERO()) {
1372                ret[0] = S;
1373                return ret;
1374            }
1375            if (ring.nvar != 1) {
1376                throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials"
1377                                + ring);
1378            }
1379            GenPolynomial<C>[] qr;
1380            GenPolynomial<C> q = this;
1381            GenPolynomial<C> r = S;
1382            GenPolynomial<C> c1 = ring.getONE().clone();
1383            GenPolynomial<C> d1 = ring.getZERO().clone();
1384            GenPolynomial<C> x1;
1385            GenPolynomial<C> x2;
1386            while (!r.isZERO()) {
1387                qr = q.quotientRemainder(r);
1388                q = qr[0];
1389                x1 = c1.subtract(q.multiply(d1));
1390                c1 = d1;
1391                d1 = x1;
1392                q = r;
1393                r = qr[1];
1394            }
1395            // normalize ldcf(q) to 1, i.e. make monic
1396            C g = q.leadingBaseCoefficient();
1397            if (g.isUnit()) {
1398                C h = g.inverse();
1399                q = q.multiply(h);
1400                c1 = c1.multiply(h);
1401            }
1402            //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); 
1403            ret[0] = q;
1404            ret[1] = c1;
1405            return ret;
1406        }
1407    
1408    
1409        /**
1410         * GenPolynomial inverse. Required by RingElem. Throws not implemented
1411         * exception.
1412         */
1413        public GenPolynomial<C> inverse() {
1414            if (isUnit()) { // only possible if ldbcf is unit
1415                C c = leadingBaseCoefficient().inverse();
1416                return ring.getONE().multiply(c);
1417            }
1418            throw new NotInvertibleException("element not invertible " + this);
1419        }
1420    
1421    
1422        /**
1423         * GenPolynomial modular inverse. Only for univariate polynomials over
1424         * fields.
1425         * @param m GenPolynomial.
1426         * @return a with with a*this = 1 mod m.
1427         */
1428        public GenPolynomial<C> modInverse(GenPolynomial<C> m) {
1429            if (this.isZERO()) {
1430                throw new NotInvertibleException("zero is not invertible");
1431            }
1432            GenPolynomial<C>[] hegcd = this.hegcd(m);
1433            GenPolynomial<C> a = hegcd[0];
1434            if (!a.isUnit()) { // gcd != 1
1435                throw new AlgebraicNotInvertibleException("element not invertible, gcd != 1", m, a, m.divide(a));
1436            }
1437            GenPolynomial<C> b = hegcd[1];
1438            if (b.isZERO()) { // when m divides this, e.g. m.isUnit()
1439                throw new NotInvertibleException("element not invertible, divisible by modul");
1440            }
1441            return b;
1442        }
1443    
1444    
1445        /**
1446         * Extend variables. Used e.g. in module embedding. Extend all ExpVectors by
1447         * i elements and multiply by x_j^k.
1448         * @param pfac extended polynomial ring factory (by i variables).
1449         * @param j index of variable to be used for multiplication.
1450         * @param k exponent for x_j.
1451         * @return extended polynomial.
1452         */
1453        public GenPolynomial<C> extend(GenPolynomialRing<C> pfac, int j, long k) {
1454            if (ring.equals(pfac)) { // nothing to do
1455                return this;
1456            }
1457            GenPolynomial<C> Cp = pfac.getZERO().clone();
1458            if (this.isZERO()) {
1459                return Cp;
1460            }
1461            int i = pfac.nvar - ring.nvar;
1462            Map<ExpVector, C> C = Cp.val; //getMap();
1463            Map<ExpVector, C> A = val;
1464            for (Map.Entry<ExpVector, C> y : A.entrySet()) {
1465                ExpVector e = y.getKey();
1466                C a = y.getValue();
1467                ExpVector f = e.extend(i, j, k);
1468                C.put(f, a);
1469            }
1470            return Cp;
1471        }
1472    
1473    
1474        /**
1475         * Extend lower variables. Used e.g. in module embedding. Extend all
1476         * ExpVectors by i lower elements and multiply by x_j^k.
1477         * @param pfac extended polynomial ring factory (by i variables).
1478         * @param j index of variable to be used for multiplication.
1479         * @param k exponent for x_j.
1480         * @return extended polynomial.
1481         */
1482        public GenPolynomial<C> extendLower(GenPolynomialRing<C> pfac, int j, long k) {
1483            if (ring.equals(pfac)) { // nothing to do
1484                return this;
1485            }
1486            GenPolynomial<C> Cp = pfac.getZERO().clone();
1487            if (this.isZERO()) {
1488                return Cp;
1489            }
1490            int i = pfac.nvar - ring.nvar;
1491            Map<ExpVector, C> C = Cp.val; //getMap();
1492            Map<ExpVector, C> A = val;
1493            for (Map.Entry<ExpVector, C> y : A.entrySet()) {
1494                ExpVector e = y.getKey();
1495                C a = y.getValue();
1496                ExpVector f = e.extendLower(i, j, k);
1497                C.put(f, a);
1498            }
1499            return Cp;
1500        }
1501    
1502    
1503        /**
1504         * Contract variables. Used e.g. in module embedding. Remove i elements of
1505         * each ExpVector.
1506         * @param pfac contracted polynomial ring factory (by i variables).
1507         * @return Map of exponents and contracted polynomials. <b>Note:</b> could
1508         *         return SortedMap
1509         */
1510        public Map<ExpVector, GenPolynomial<C>> contract(GenPolynomialRing<C> pfac) {
1511            GenPolynomial<C> zero = pfac.getZERO();
1512            TermOrder t = new TermOrder(TermOrder.INVLEX);
1513            Map<ExpVector, GenPolynomial<C>> B = new TreeMap<ExpVector, GenPolynomial<C>>(t.getAscendComparator());
1514            if (this.isZERO()) {
1515                return B;
1516            }
1517            int i = ring.nvar - pfac.nvar;
1518            Map<ExpVector, C> A = val;
1519            for (Map.Entry<ExpVector, C> y : A.entrySet()) {
1520                ExpVector e = y.getKey();
1521                C a = y.getValue();
1522                ExpVector f = e.contract(0, i);
1523                ExpVector g = e.contract(i, e.length() - i);
1524                GenPolynomial<C> p = B.get(f);
1525                if (p == null) {
1526                    p = zero;
1527                }
1528                p = p.sum(a, g);
1529                B.put(f, p);
1530            }
1531            return B;
1532        }
1533    
1534    
1535        /**
1536         * Contract variables to coefficient polynomial. Remove i elements of each
1537         * ExpVector, removed elements must be zero.
1538         * @param pfac contracted polynomial ring factory (by i variables).
1539         * @return contracted coefficient polynomial.
1540         */
1541        public GenPolynomial<C> contractCoeff(GenPolynomialRing<C> pfac) {
1542            Map<ExpVector, GenPolynomial<C>> ms = contract(pfac);
1543            GenPolynomial<C> c = pfac.getZERO();
1544            for (Map.Entry<ExpVector, GenPolynomial<C>> m : ms.entrySet()) {
1545                if (m.getKey().isZERO()) {
1546                    c = m.getValue();
1547                } else {
1548                    throw new RuntimeException("wrong coefficient contraction " + m + ", pol =  " + c);
1549                }
1550            }
1551            return c;
1552        }
1553    
1554    
1555        /**
1556         * Extend univariate to multivariate polynomial. This is an univariate
1557         * polynomial in variable i of the polynomial ring, it is extended to the
1558         * given polynomial ring.
1559         * @param pfac extended polynomial ring factory.
1560         * @param i index of the variable of this polynomial in pfac.
1561         * @return extended multivariate polynomial.
1562         */
1563        public GenPolynomial<C> extendUnivariate(GenPolynomialRing<C> pfac, int i) {
1564            if (i < 0 || pfac.nvar < i) {
1565                throw new IllegalArgumentException("index " + i + "out of range " + pfac.nvar);
1566            }
1567            if (ring.nvar != 1) {
1568                throw new IllegalArgumentException("polynomial not univariate " + ring.nvar);
1569            }
1570            if (this.isONE()) {
1571                return pfac.getONE();
1572            }
1573            int j = pfac.nvar - 1 - i;
1574            GenPolynomial<C> Cp = pfac.getZERO().clone();
1575            if (this.isZERO()) {
1576                return Cp;
1577            }
1578            Map<ExpVector, C> C = Cp.val; //getMap();
1579            Map<ExpVector, C> A = val;
1580            for (Map.Entry<ExpVector, C> y : A.entrySet()) {
1581                ExpVector e = y.getKey();
1582                long n = e.getVal(0);
1583                C a = y.getValue();
1584                ExpVector f = ExpVector.create(pfac.nvar, j, n);
1585                C.put(f, a); // assert not contained
1586            }
1587            return Cp;
1588        }
1589    
1590    
1591        /**
1592         * Reverse variables. Used e.g. in opposite rings.
1593         * @return polynomial with reversed variables.
1594         */
1595        public GenPolynomial<C> reverse(GenPolynomialRing<C> oring) {
1596            GenPolynomial<C> Cp = oring.getZERO().clone();
1597            if (this.isZERO()) {
1598                return Cp;
1599            }
1600            int k = -1;
1601            if (oring.tord.getEvord2() != 0 && oring.partial) {
1602                k = oring.tord.getSplit();
1603            }
1604    
1605            Map<ExpVector, C> C = Cp.val; //getMap();
1606            Map<ExpVector, C> A = val;
1607            ExpVector f;
1608            for (Map.Entry<ExpVector, C> y : A.entrySet()) {
1609                ExpVector e = y.getKey();
1610                if (k >= 0) {
1611                    f = e.reverse(k);
1612                } else {
1613                    f = e.reverse();
1614                }
1615                C a = y.getValue();
1616                C.put(f, a);
1617            }
1618            return Cp;
1619        }
1620    
1621    
1622        /**
1623         * Iterator over coefficients.
1624         * @return val.values().iterator().
1625         */
1626        public Iterator<C> coefficientIterator() {
1627            return val.values().iterator();
1628        }
1629    
1630    
1631        /**
1632         * Iterator over exponents.
1633         * @return val.keySet().iterator().
1634         */
1635        public Iterator<ExpVector> exponentIterator() {
1636            return val.keySet().iterator();
1637        }
1638    
1639    
1640        /**
1641         * Iterator over monomials.
1642         * @return a PolyIterator.
1643         */
1644        public Iterator<Monomial<C>> iterator() {
1645            return new PolyIterator<C>(val);
1646        }
1647    
1648    
1649        /**
1650         * Map a unary function to the coefficients.
1651         * @param f evaluation functor.
1652         * @return new polynomial with coefficients f(this(e)).
1653         */
1654        public GenPolynomial<C> map(final UnaryFunctor<? super C, C> f) {
1655            GenPolynomial<C> n = ring.getZERO().clone();
1656            SortedMap<ExpVector, C> nv = n.val;
1657            for (Monomial<C> m : this) {
1658                //logger.info("m = " + m);
1659                C c = f.eval(m.c);
1660                if (c != null && !c.isZERO()) {
1661                    nv.put(m.e, c);
1662                }
1663            }
1664            return n;
1665        }
1666    
1667    }