001/*
002 * $Id$
003 */
004
005package edu.jas.poly;
006
007
008import java.io.IOException;
009import java.io.Reader;
010import java.io.StringReader;
011import java.math.BigInteger;
012import java.util.ArrayList;
013import java.util.Arrays;
014import java.util.Iterator;
015import java.util.List;
016import java.util.Random;
017import java.util.SortedMap;
018import java.util.concurrent.atomic.AtomicLong;
019
020import org.apache.logging.log4j.LogManager;
021import org.apache.logging.log4j.Logger;
022
023import edu.jas.arith.ModIntegerRing;
024import edu.jas.kern.PreemptStatus;
025import edu.jas.kern.PrettyPrint;
026import edu.jas.kern.Scripting;
027import edu.jas.structure.RingElem;
028import edu.jas.structure.RingFactory;
029import edu.jas.util.CartesianProduct;
030import edu.jas.util.CartesianProductInfinite;
031import edu.jas.util.LongIterable;
032import edu.jas.vector.GenVector;
033import edu.jas.vector.GenMatrix;
034import edu.jas.vector.GenMatrixRing;
035
036
037/**
038 * GenPolynomialRing generic polynomial factory. It implements RingFactory for
039 * n-variate ordered polynomials over coefficients C. The variables commute with
040 * each other and with the coefficients. For non-commutative coefficients some
041 * care is taken to respect the multiplication order.
042 *
043 * Almost immutable object, except variable names.
044 * @param <C> coefficient type
045 * @author Heinz Kredel
046 */
047
048public class GenPolynomialRing<C extends RingElem<C>>
049                implements RingFactory<GenPolynomial<C>>, Iterable<GenPolynomial<C>> {
050
051
052    /**
053     * The factory for the coefficients.
054     */
055    public final RingFactory<C> coFac;
056
057
058    /**
059     * The number of variables.
060     */
061    public final int nvar;
062
063
064    /**
065     * The term order.
066     */
067    public final TermOrder tord;
068
069
070    /**
071     * True for partially reversed variables.
072     */
073    protected boolean partial;
074
075
076    /**
077     * The names of the variables. This value can be modified.
078     */
079    protected String[] vars;
080
081
082    /**
083     * Counter to distinguish new variables.
084     */
085    private static AtomicLong varCounter = new AtomicLong(0L);
086
087
088    /**
089     * The constant polynomial 0 for this ring.
090     */
091    public /*final*/ GenPolynomial<C> ZERO; // volatile not meaningful by DL
092
093
094    /**
095     * The constant polynomial 1 for this ring.
096     */
097    public /*final*/ GenPolynomial<C> ONE; // volatile not meaningful by DL
098
099
100    /**
101     * The constant exponent vector 0 for this ring.
102     */
103    public final ExpVector evzero; // volatile not meaningful by DL
104
105
106    /**
107     * A default random sequence generator.
108     */
109    protected final static Random random = new Random();
110
111
112    /**
113     * Indicator if this ring is a field.
114     */
115    protected int isField = -1; // initially unknown
116
117
118    /**
119     * Log4j logger object.
120     */
121    private static final Logger logger = LogManager.getLogger(GenPolynomialRing.class);
122
123
124    /**
125     * Count for number of polynomial creations.
126     */
127    static int creations = 0;
128
129
130    /**
131     * Flag to enable if preemptive interrupt is checked.
132     */
133    volatile boolean checkPreempt = PreemptStatus.isAllowed();
134
135
136    /**
137     * The constructor creates a polynomial factory object with the default term
138     * order.
139     * @param cf factory for coefficients of type C.
140     * @param n number of variables.
141     */
142    public GenPolynomialRing(RingFactory<C> cf, int n) {
143        this(cf, n, new TermOrder(), null);
144    }
145
146
147    /**
148     * The constructor creates a polynomial factory object.
149     * @param cf factory for coefficients of type C.
150     * @param n number of variables.
151     * @param t a term order.
152     */
153    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t) {
154        this(cf, n, t, null);
155    }
156
157
158    /**
159     * The constructor creates a polynomial factory object.
160     * @param cf factory for coefficients of type C.
161     * @param v names for the variables.
162     */
163    public GenPolynomialRing(RingFactory<C> cf, String[] v) {
164        this(cf, v.length, v);
165    }
166
167
168    /**
169     * The constructor creates a polynomial factory object.
170     * @param cf factory for coefficients of type C.
171     * @param n number of variables.
172     * @param v names for the variables.
173     */
174    public GenPolynomialRing(RingFactory<C> cf, int n, String[] v) {
175        this(cf, n, new TermOrder(), v);
176    }
177
178
179    /**
180     * The constructor creates a polynomial factory object.
181     * @param cf factory for coefficients of type C.
182     * @param t a term order.
183     * @param v names for the variables.
184     */
185    public GenPolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) {
186        this(cf, v.length, t, v);
187    }
188
189
190    /**
191     * The constructor creates a polynomial factory object.
192     * @param cf factory for coefficients of type C.
193     * @param v names for the variables.
194     * @param t a term order.
195     */
196    public GenPolynomialRing(RingFactory<C> cf, String[] v, TermOrder t) {
197        this(cf, v.length, t, v);
198    }
199
200
201    /**
202     * The constructor creates a polynomial factory object.
203     * @param cf factory for coefficients of type C.
204     * @param n number of variables.
205     * @param t a term order.
206     * @param v names for the variables.
207     */
208    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) {
209        coFac = cf;
210        nvar = n;
211        tord = t;
212        partial = false;
213        if (v == null) {
214            vars = null;
215        } else {
216            vars = Arrays.copyOf(v, v.length); // > Java-5
217        }
218        C coeff = coFac.getONE();
219        synchronized (this) {
220           evzero = ExpVector.create(nvar);
221           ZERO = new GenPolynomial<C>(this);
222           ONE = new GenPolynomial<C>(this, coeff, evzero);
223        }
224        //logger.debug("ZERO {} {}", ZERO.toString(), ZERO.val);
225        //System.out.println("thread@ZERO: " + Thread.currentThread());
226        if (vars == null) {
227            if (PrettyPrint.isTrue()) {
228                vars = newVars("x", nvar);
229            }
230        } else {
231            if (vars.length != nvar) {
232                throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar);
233            }
234            // addVars(vars);
235        }
236    }
237
238
239    /**
240     * The constructor creates a polynomial factory object with the the same
241     * term order, number of variables and variable names as the given
242     * polynomial factory, only the coefficient factories differ.
243     * @param cf factory for coefficients of type C.
244     * @param o other polynomial ring.
245     */
246    public GenPolynomialRing(RingFactory<C> cf, GenPolynomialRing o) {
247        this(cf, o.nvar, o.tord, o.vars);
248    }
249
250
251    /**
252     * The constructor creates a polynomial factory object with the the same
253     * coefficient factory, number of variables and variable names as the given
254     * polynomial factory, only the term order differs.
255     * @param to term order.
256     * @param o other polynomial ring.
257     */
258    public GenPolynomialRing(GenPolynomialRing<C> o, TermOrder to) {
259        this(o.coFac, o.nvar, to, o.vars);
260    }
261
262
263    /**
264     * Copy this factory.
265     * @return a clone of this.
266     */
267    public GenPolynomialRing<C> copy() {
268        return new GenPolynomialRing<C>(coFac, this);
269    }
270
271
272    /**
273     * Get the String representation.
274     * @see java.lang.Object#toString()
275     */
276    @SuppressWarnings("cast")
277    @Override
278    public String toString() {
279        String res = null;
280        if (PrettyPrint.isTrue()) { // wrong: && coFac != null
281            String scf = coFac.getClass().getSimpleName();
282            if (coFac instanceof AlgebraicNumberRing) {
283                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
284                res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]";
285            }
286            if (coFac instanceof GenPolynomialRing) {
287                GenPolynomialRing rf = (GenPolynomialRing) coFac;
288                //String[] v = rf.vars;
289                //RingFactory cf = rf.coFac;
290                //String cs;
291                //if (cf instanceof ModIntegerRing) {
292                //    cs = cf.toString();
293                //} else {
294                //    cs = " " + cf.getClass().getSimpleName();
295                //}
296                //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } ";
297                res = "IntFunc" + "( " + rf.toString() + " )";
298            }
299            if (((Object) coFac) instanceof ModIntegerRing) {
300                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
301                res = "Mod " + mn.getModul() + " ";
302            }
303            if (res == null) {
304                res = coFac.toString();
305                if (res.matches("[0-9].*")) {
306                    res = scf;
307                }
308            }
309            res += "( " + varsToString() + " ) " + tord.toString() + " ";
310        } else {
311            res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " ";
312            if (coFac instanceof AlgebraicNumberRing) {
313                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
314                res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]";
315            }
316            if (coFac instanceof GenPolynomialRing) {
317                GenPolynomialRing rf = (GenPolynomialRing) coFac;
318                //String[] v = rf.vars;
319                //RingFactory cf = rf.coFac;
320                //String cs;
321                //if (cf instanceof ModIntegerRing) {
322                //    cs = cf.toString();
323                //} else {
324                //    cs = " " + cf.getClass().getSimpleName();
325                //}
326                //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } ";
327                res = "IntFunc" + "( " + rf.toString() + " )";
328            }
329            if (((Object) coFac) instanceof ModIntegerRing) {
330                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
331                res = "Mod " + mn.getModul() + " ";
332            }
333            //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]";
334            res += "( " + varsToString() + " ) " + tord.toString() + " ]";
335        }
336        return res;
337    }
338
339
340    /**
341     * Get a scripting compatible string representation.
342     * @return script compatible representation for this Element.
343     * @see edu.jas.structure.Element#toScript()
344     */
345    @Override
346    public String toScript() {
347        StringBuffer s = new StringBuffer();
348        switch (Scripting.getLang()) {
349        case Ruby:
350            s.append("PolyRing.new(");
351            break;
352        case Python:
353        default:
354            s.append("PolyRing(");
355        }
356        if (coFac instanceof RingElem) {
357            s.append(((RingElem<C>) coFac).toScriptFactory());
358        } else {
359            s.append(coFac.toScript().trim());
360        }
361        s.append(",\"" + varsToString() + "\"");
362        String to = tord.toScript();
363        s.append("," + to);
364        s.append(")");
365        return s.toString();
366    }
367
368
369    /**
370     * Get a scripting compatible string representation of an ExpVector of this
371     * ring.
372     * @param e exponent vector
373     * @return script compatible representation for the ExpVector.
374     */
375    public String toScript(ExpVector e) {
376        if (e == null) {
377            return "null";
378        }
379        if (vars != null) {
380            return e.toScript(vars);
381        }
382        return e.toScript();
383    }
384
385
386    /**
387     * Comparison with any other object.
388     * @see java.lang.Object#equals(java.lang.Object)
389     */
390    @Override
391    @SuppressWarnings("unchecked")
392    public boolean equals(Object other) {
393        if (other == null) {
394            return false;
395        }
396        if (!(other instanceof GenPolynomialRing)) {
397            return false;
398        }
399        GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other;
400        if (nvar != oring.nvar) {
401            return false;
402        }
403        if (!coFac.equals(oring.coFac)) {
404            return false;
405        }
406        if (!tord.equals(oring.tord)) {
407            return false;
408        }
409        // same variables required ?
410        if (!Arrays.deepEquals(vars, oring.vars)) {
411            return false;
412        }
413        return true;
414    }
415
416
417    /**
418     * Hash code for this polynomial ring.
419     * @see java.lang.Object#hashCode()
420     */
421    @Override
422    public int hashCode() {
423        int h;
424        h = (nvar << 27);
425        h += (coFac.hashCode() << 11);
426        h += (tord.hashCode() << 9);
427        h += Arrays.hashCode(vars);
428        //System.out.println("GenPolynomialRing.hashCode: " + h);
429        return h;
430    }
431
432
433    /**
434     * Get the number of polynomial creations.
435     * @return creations.
436     */
437    public int getCreations() {
438        return creations;
439    }
440
441
442    /**
443     * Get the variable names.
444     * @return vars.
445     */
446    public String[] getVars() {
447        return Arrays.copyOf(vars, vars.length); // > Java-5
448    }
449
450
451    /**
452     * Set the variable names.
453     * @return old vars.
454     */
455    public String[] setVars(String[] v) {
456        if (v.length != nvar) {
457            throw new IllegalArgumentException(
458                            "v not matching number of variables: " + Arrays.toString(v) + ", nvar " + nvar);
459        }
460        String[] t = vars;
461        vars = Arrays.copyOf(v, v.length); // > Java-5 
462        return t;
463    }
464
465
466    /**
467     * Get a String representation of the variable names.
468     * @return names separated by commas.
469     */
470    public String varsToString() {
471        if (vars == null) {
472            return "#" + nvar;
473        }
474        //return Arrays.toString(vars);
475        return ExpVector.varsToString(vars);
476    }
477
478
479    /**
480     * Get the zero element from the coefficients.
481     * @return 0 as C.
482     */
483    public C getZEROCoefficient() {
484        return coFac.getZERO();
485    }
486
487
488    /**
489     * Get the one element from the coefficients.
490     * @return 1 as C.
491     */
492    public C getONECoefficient() {
493        return coFac.getONE();
494    }
495
496
497    /**
498     * Get the zero element.
499     * @return 0 as GenPolynomial<C>.
500     */
501    public synchronized GenPolynomial<C> getZERO() {
502        if (ZERO == null || !ZERO.isZERO()) { // happened since May 5 2022
503            // Name        : java-11-openjdk-headless, java-17-openjdk-headless
504            // Version     : 11.0.15.0, 17.0.4
505            // Release     : 150000.3.80.1, 150400.3.3.1
506            GenPolynomial<C> x = ZERO;
507            ZERO = new GenPolynomial<C>(this);
508            logger.info("warn: ZERO@get |{}| wrong fix to {}", x, ZERO);
509        }
510        return ZERO;
511    }
512
513
514    /**
515     * Get the one element.
516     * @return 1 as GenPolynomial<C>.
517     */
518    public synchronized GenPolynomial<C> getONE() {
519        if (ONE == null || !ONE.isONE()) {
520           ONE = new GenPolynomial<C>(this, coFac.getONE(), evzero);
521           logger.info("warn: ONE@get {}", ONE);
522        }
523        return ONE;
524    }
525
526
527    /**
528     * Query if this ring is commutative.
529     * @return true if this ring is commutative, else false.
530     */
531    public boolean isCommutative() {
532        return coFac.isCommutative();
533    }
534
535
536    /**
537     * Query if this ring is associative.
538     * @return true if this ring is associative, else false.
539     */
540    public boolean isAssociative() {
541        return coFac.isAssociative();
542    }
543
544
545    /**
546     * Query if this ring is a field.
547     * @return false.
548     */
549    public boolean isField() {
550        if (isField > 0) {
551            return true;
552        }
553        if (isField == 0) {
554            return false;
555        }
556        if (coFac.isField() && nvar == 0) {
557            isField = 1;
558            return true;
559        }
560        isField = 0;
561        return false;
562    }
563
564
565    /**
566     * Characteristic of this ring.
567     * @return characteristic of this ring.
568     */
569    public java.math.BigInteger characteristic() {
570        return coFac.characteristic();
571    }
572
573
574    /**
575     * Get a (constant) GenPolynomial&lt;C&gt; element from a coefficient value.
576     * @param a coefficient.
577     * @return a GenPolynomial&lt;C&gt;.
578     */
579    public GenPolynomial<C> valueOf(C a) {
580        return new GenPolynomial<C>(this, a);
581    }
582
583
584    /**
585     * Get a GenPolynomial&lt;C&gt; element from an exponent vector.
586     * @param e exponent vector.
587     * @return a GenPolynomial&lt;C&gt;.
588     */
589    public GenPolynomial<C> valueOf(ExpVector e) {
590        if (e == null) {
591            return getZERO();
592        }
593        return new GenPolynomial<C>(this, coFac.getONE(), e);
594    }
595
596
597    /**
598     * Get a GenPolynomial&lt;C&gt; element from a list of exponent vectors.
599     * @param E list of exponent vector.
600     * @return a GenPolynomial&lt;C&gt;.
601     */
602    public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) {
603        if (E == null) {
604            return null;
605        }
606        List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size());
607        for (ExpVector e : E) {
608            GenPolynomial<C> p = valueOf(e);
609            P.add(p);
610        }
611        return P;
612    }
613
614
615    /**
616     * Get a GenPolynomial&lt;C&gt; element from a coefficient and an exponent
617     * vector.
618     * @param a coefficient.
619     * @param e exponent vector.
620     * @return a GenPolynomial&lt;C&gt;.
621     */
622    public GenPolynomial<C> valueOf(C a, ExpVector e) {
623        return new GenPolynomial<C>(this, a, e);
624    }
625
626
627    /**
628     * Get a GenPolynomial&lt;C&gt; element from a monomial.
629     * @param m monomial.
630     * @return a GenPolynomial&lt;C&gt;.
631     */
632    public GenPolynomial<C> valueOf(Monomial<C> m) {
633        return new GenPolynomial<C>(this, m.c, m.e);
634    }
635
636
637    /**
638     * Get a (constant) GenPolynomial&lt;C&gt; element from a long value.
639     * @param a long.
640     * @return a GenPolynomial&lt;C&gt;.
641     */
642    public GenPolynomial<C> fromInteger(long a) {
643        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
644    }
645
646
647    /**
648     * Get a (constant) GenPolynomial&lt;C&gt; element from a BigInteger value.
649     * @param a BigInteger.
650     * @return a GenPolynomial&lt;C&gt;.
651     */
652    public GenPolynomial<C> fromInteger(BigInteger a) {
653        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
654    }
655
656
657    /**
658     * Get a GenPolynomial&lt;C&gt; from a GenVector&lt;C&gt;.
659     * @param a GenVector&lt;C&gt;.
660     * @return a GenPolynomial&lt;C&gt;.
661     */
662    public GenPolynomial<C> fromVector(GenVector<C> a) {
663        if (a == null || a.isZERO()) {
664            return ZERO;
665        }
666        if (nvar != 1) {
667            throw new IllegalArgumentException("no univariate polynomial ring");
668        }
669        GenPolynomial<C> ret = copy(ZERO);
670        SortedMap<ExpVector, C> tm = ret.val;
671        long i = -1;
672        for (C m : a.val) {
673            i++;
674            if (m.isZERO()) {
675                continue;
676            }
677            ExpVector e = ExpVector.create(1, 0, i);
678            tm.put(e, m);
679        }
680        return ret;
681    }
682
683
684    /**
685     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
686     * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
687     * @param n number of terms.
688     * @return a random polynomial.
689     */
690    public GenPolynomial<C> random(int n) {
691        return random(n, random);
692    }
693
694
695    /**
696     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
697     * n, q = (nvar == 1) ? 0.5 : 0.3.
698     * @param n number of terms.
699     * @param rnd is a source for random bits.
700     * @return a random polynomial.
701     */
702    public GenPolynomial<C> random(int n, Random rnd) {
703        if (nvar == 1) {
704            return random(3, n, n, 0.5f, rnd);
705        }
706        return random(3, n, n, 0.3f, rnd);
707    }
708
709
710    /**
711     * Generate a random polynomial.
712     * @param k bitsize of random coefficients.
713     * @param l number of terms.
714     * @param d maximal degree in each variable.
715     * @param q density of nozero exponents.
716     * @return a random polynomial.
717     */
718    public GenPolynomial<C> random(int k, int l, int d, float q) {
719        return random(k, l, d, q, random);
720    }
721
722
723    /**
724     * Generate a random polynomial.
725     * @param k bitsize of random coefficients.
726     * @param l number of terms.
727     * @param d maximal degree in each variable.
728     * @param q density of nozero exponents.
729     * @param rnd is a source for random bits.
730     * @return a random polynomial.
731     */
732    public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) {
733        GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 
734        ExpVector e;
735        C a;
736        // add l random coeffs and exponents
737        for (int i = 0; i < l; i++) {
738            e = ExpVector.random(nvar, d, q, rnd);
739            a = coFac.random(k, rnd);
740            r = r.sum(a, e); // somewhat inefficient but clean
741            //System.out.println("e = " + e + " a = " + a);
742        }
743        // System.out.println("r = " + r);
744        return r;
745    }
746
747
748    /**
749     * Copy polynomial c.
750     * @param c
751     * @return a copy of c.
752     */
753    public GenPolynomial<C> copy(GenPolynomial<C> c) {
754        //System.out.println("GP copy = " + this);
755        return new GenPolynomial<C>(this, c.val);
756    }
757
758
759    /**
760     * Copy polynomial list.
761     * @param L polynomial list
762     * @return a copy of L in this ring.
763     */
764    public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) {
765        if (L == null) {
766            return L;
767        }
768        List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size());
769        for (GenPolynomial<C> a : L) {
770            R.add(copy(a));
771        }
772        return R;
773    }
774
775
776    /**
777     * Parse a polynomial with the use of GenPolynomialTokenizer.
778     * @param s String.
779     * @return GenPolynomial from s.
780     */
781    public GenPolynomial<C> parse(String s) {
782        String val = s;
783        if (!s.contains("|")) {
784            val = val.replace("{", "").replace("}", "");
785        }
786        return parse(new StringReader(val));
787    }
788
789
790    /**
791     * Parse a polynomial with the use of GenPolynomialTokenizer.
792     * @param r Reader.
793     * @return next GenPolynomial from r.
794     */
795    @SuppressWarnings({ "unchecked", "cast" })
796    public GenPolynomial<C> parse(Reader r) {
797        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r);
798        GenPolynomial<C> p = null;
799        try {
800            p = (GenPolynomial<C>) pt.nextPolynomial();
801        } catch (IOException e) {
802            logger.error("{} parse {}", e, this);
803            p = ZERO;
804        }
805        return p;
806    }
807
808
809    /**
810     * Generate univariate polynomial in a given variable with given exponent.
811     * @param x the name of a variable.
812     * @return x as univariate polynomial.
813     */
814    public GenPolynomial<C> univariate(String x) {
815        return univariate(x, 1L);
816    }
817
818
819    /**
820     * Generate univariate polynomial in a given variable with given exponent.
821     * @param x the name of the variable.
822     * @param e the exponent of the variable.
823     * @return x^e as univariate polynomial.
824     */
825    public GenPolynomial<C> univariate(String x, long e) {
826        if (vars == null) { // should not happen
827            throw new IllegalArgumentException("no variables defined for polynomial ring");
828        }
829        if (x == null || x.isEmpty()) {
830            throw new IllegalArgumentException("no variable name given");
831        }
832        int i;
833        for (i = 0; i < vars.length; i++) {
834            if (x.equals(vars[i])) { // use HashMap or TreeMap
835                break;
836            }
837        }
838        if (i >= vars.length) {
839            throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring");
840        }
841        return univariate(0, nvar - i - 1, e);
842    }
843
844
845    /**
846     * Generate univariate polynomial in a given variable.
847     * @param i the index of the variable.
848     * @return X_i as univariate polynomial.
849     */
850    public GenPolynomial<C> univariate(int i) {
851        return univariate(0, i, 1L);
852    }
853
854
855    /**
856     * Generate univariate polynomial in a given variable with given exponent.
857     * @param i the index of the variable.
858     * @param e the exponent of the variable.
859     * @return X_i^e as univariate polynomial.
860     */
861    public GenPolynomial<C> univariate(int i, long e) {
862        return univariate(0, i, e);
863    }
864
865
866    /**
867     * Generate univariate polynomial in a given variable with given exponent.
868     * @param modv number of module variables.
869     * @param i the index of the variable.
870     * @param e the exponent of the variable.
871     * @return X_i^e as univariate polynomial.
872     */
873    public GenPolynomial<C> univariate(int modv, int i, long e) {
874        GenPolynomial<C> p = getZERO();
875        int r = nvar - modv;
876        if (0 <= i && i < r) {
877            C one = coFac.getONE();
878            ExpVector f = ExpVector.create(r, i, e);
879            if (modv > 0) {
880                f = f.extend(modv, 0, 0l);
881            }
882            p = p.sum(one, f);
883        }
884        return p;
885    }
886
887
888    /**
889     * Get the generating elements excluding the generators for the coefficient
890     * ring.
891     * @return a list of generating elements for this ring.
892     */
893    public List<GenPolynomial<C>> getGenerators() {
894        List<? extends GenPolynomial<C>> univs = univariateList();
895        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1);
896        gens.add(getONE());
897        gens.addAll(univs);
898        return gens;
899    }
900
901
902    /**
903     * Get a list of the generating elements.
904     * @return list of generators for the algebraic structure.
905     * @see edu.jas.structure.ElemFactory#generators()
906     */
907    public List<GenPolynomial<C>> generators() {
908        List<? extends C> cogens = coFac.generators();
909        List<? extends GenPolynomial<C>> univs = univariateList();
910        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
911        for (C c : cogens) {
912            gens.add(getONE().multiply(c));
913        }
914        gens.addAll(univs);
915        return gens;
916    }
917
918
919    /**
920     * Get a list of the generating elements excluding the module variables.
921     * @param modv number of module variables
922     * @return list of generators for the polynomial ring.
923     */
924    public List<GenPolynomial<C>> generators(int modv) {
925        List<? extends C> cogens = coFac.generators();
926        List<? extends GenPolynomial<C>> univs = univariateList(modv);
927        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
928        for (C c : cogens) {
929            gens.add(getONE().multiply(c));
930        }
931        gens.addAll(univs);
932        return gens;
933    }
934
935
936    /**
937     * Is this structure finite or infinite.
938     * @return true if this structure is finite, else false.
939     * @see edu.jas.structure.ElemFactory#isFinite()
940     */
941    public boolean isFinite() {
942        return (nvar == 0) && coFac.isFinite();
943    }
944
945
946    /**
947     * Generate list of univariate polynomials in all variables.
948     * @return List(X_1,...,X_n) a list of univariate polynomials.
949     */
950    public List<? extends GenPolynomial<C>> univariateList() {
951        return univariateList(0, 1L);
952    }
953
954
955    /**
956     * Generate list of univariate polynomials in all variables.
957     * @param modv number of module variables.
958     * @return List(X_1,...,X_n) a list of univariate polynomials.
959     */
960    public List<? extends GenPolynomial<C>> univariateList(int modv) {
961        return univariateList(modv, 1L);
962    }
963
964
965    /**
966     * Generate list of univariate polynomials in all variables with given
967     * exponent.
968     * @param modv number of module variables.
969     * @param e the exponent of the variables.
970     * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
971     */
972    public List<? extends GenPolynomial<C>> univariateList(int modv, long e) {
973        List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar);
974        int nm = nvar - modv;
975        for (int i = 0; i < nm; i++) {
976            GenPolynomial<C> p = univariate(modv, nm - 1 - i, e);
977            pols.add(p);
978        }
979        return pols;
980    }
981
982
983    /**
984     * Extend variables. Used e.g. in module embedding. Extend number of
985     * variables by i.
986     * @param i number of variables to extend.
987     * @return extended polynomial ring factory.
988     */
989    public GenPolynomialRing<C> extend(int i) {
990        return extend(i, false);
991    }
992
993
994    /**
995     * Extend variables. Used e.g. in module embedding. Extend number of
996     * variables by i.
997     * @param i number of variables to extend.
998     * @param top true for TOP term order, false for POT term order.
999     * @return extended polynomial ring factory.
1000     */
1001    public GenPolynomialRing<C> extend(int i, boolean top) {
1002        // add module variable names
1003        String[] v = newVars("e", i);
1004        return extend(v, top);
1005    }
1006
1007
1008    /**
1009     * Extend variables. Used e.g. in module embedding. Extend number of
1010     * variables by length(vn).
1011     * @param vn names for extended variables.
1012     * @return extended polynomial ring factory.
1013     */
1014    public GenPolynomialRing<C> extend(String[] vn) {
1015        return extend(vn, false);
1016    }
1017
1018
1019    /**
1020     * Extend variables. Used e.g. in module embedding. Extend number of
1021     * variables by length(vn).
1022     * @param vn names for extended variables.
1023     * @param top true for TOP term order, false for POT term order.
1024     * @return extended polynomial ring factory.
1025     */
1026    public GenPolynomialRing<C> extend(String[] vn, boolean top) {
1027        if (vn == null || vars == null) {
1028            throw new IllegalArgumentException("vn and vars may not be null");
1029        }
1030        int i = vn.length;
1031        String[] v = new String[vars.length + i];
1032        for (int k = 0; k < vars.length; k++) {
1033            v[k] = vars[k];
1034        }
1035        for (int k = 0; k < vn.length; k++) {
1036            v[vars.length + k] = vn[k];
1037        }
1038        TermOrder to = tord.extend(nvar, i, top);
1039        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1040        return pfac;
1041    }
1042
1043
1044    /**
1045     * Extend lower variables. Extend number of variables by i.
1046     * @param i number of variables to extend.
1047     * @return extended polynomial ring factory.
1048     */
1049    public GenPolynomialRing<C> extendLower(int i) {
1050        String[] v = newVars("e", i);
1051        return extendLower(v);
1052    }
1053
1054
1055    /**
1056     * Extend lower variables. Extend number of variables by length(vn).
1057     * @param vn names for extended lower variables.
1058     * @return extended polynomial ring factory.
1059     */
1060    public GenPolynomialRing<C> extendLower(String[] vn) {
1061        return extendLower(vn, false);
1062    }
1063
1064
1065    /**
1066     * Extend lower variables. Extend number of variables by length(vn).
1067     * @param vn names for extended lower variables.
1068     * @param top true for TOP term order, false for POT term order.
1069     * @return extended polynomial ring factory.
1070     */
1071    public GenPolynomialRing<C> extendLower(String[] vn, boolean top) {
1072        if (vn == null || vars == null) {
1073            throw new IllegalArgumentException("vn and vars may not be null");
1074        }
1075        int i = vn.length;
1076        String[] v = new String[vars.length + i];
1077        for (int k = 0; k < vn.length; k++) {
1078            v[k] = vn[k];
1079        }
1080        for (int k = 0; k < vars.length; k++) {
1081            v[vn.length + k] = vars[k];
1082        }
1083        TermOrder to = tord.extendLower(nvar, i, top);
1084        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1085        return pfac;
1086    }
1087
1088
1089    /**
1090     * Contract variables. Used e.g. in module embedding. Contract number of
1091     * variables by i.
1092     * @param i number of variables to remove.
1093     * @return contracted polynomial ring factory.
1094     */
1095    public GenPolynomialRing<C> contract(int i) {
1096        String[] v = null;
1097        if (vars != null) {
1098            v = new String[vars.length - i];
1099            for (int j = 0; j < vars.length - i; j++) {
1100                v[j] = vars[j];
1101            }
1102        }
1103        TermOrder to = tord.contract(i, nvar - i);
1104        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v);
1105        return pfac;
1106    }
1107
1108
1109    /**
1110     * Recursive representation as polynomial with i main variables.
1111     * @param i number of main variables.
1112     * @return recursive polynomial ring factory.
1113     */
1114    public GenPolynomialRing<GenPolynomial<C>> recursive(int i) {
1115        if (i <= 0 || i >= nvar) {
1116            throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar);
1117        }
1118        GenPolynomialRing<C> cfac = contract(i);
1119        String[] v = null;
1120        if (vars != null) {
1121            v = new String[i];
1122            int k = 0;
1123            for (int j = nvar - i; j < nvar; j++) {
1124                v[k++] = vars[j];
1125            }
1126        }
1127        TermOrder to = tord.contract(0, i); // ??
1128        GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v);
1129        return pfac;
1130    }
1131
1132
1133    /**
1134     * Distributive representation as polynomial with all main variables.
1135     * @return distributive polynomial ring factory.
1136     */
1137    @SuppressWarnings("unchecked")
1138    public GenPolynomialRing<C> distribute() {
1139        if (!(coFac instanceof GenPolynomialRing)) {
1140            return this;
1141        }
1142        RingFactory cf = coFac;
1143        RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf;
1144        GenPolynomialRing cr = (GenPolynomialRing) cfp;
1145        GenPolynomialRing<C> pfac;
1146        if (cr.vars != null) {
1147            pfac = extend(cr.vars);
1148        } else {
1149            pfac = extend(cr.nvar);
1150        }
1151        return pfac;
1152    }
1153
1154
1155    /**
1156     * Reverse variables. Used e.g. in opposite rings.
1157     * @return polynomial ring factory with reversed variables.
1158     */
1159    public GenPolynomialRing<C> reverse() {
1160        return reverse(false);
1161    }
1162
1163
1164    /**
1165     * Reverse variables. Used e.g. in opposite rings.
1166     * @param partial true for partially reversed term orders.
1167     * @return polynomial ring factory with reversed variables.
1168     */
1169    public GenPolynomialRing<C> reverse(boolean partial) {
1170        String[] v = null;
1171        if (vars != null) { // vars are not inversed
1172            v = new String[vars.length];
1173            int k = tord.getSplit();
1174            if (partial && k < vars.length) {
1175                // copy upper
1176                for (int j = 0; j < k; j++) {
1177                    //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper
1178                    v[vars.length - k + j] = vars[vars.length - k + j];
1179                }
1180                // reverse lower
1181                for (int j = 0; j < vars.length - k; j++) {
1182                    //v[j] = vars[j]; // copy upper
1183                    v[j] = vars[vars.length - k - j - 1];
1184                }
1185            } else {
1186                for (int j = 0; j < vars.length; j++) {
1187                    v[j] = vars[vars.length - 1 - j];
1188                }
1189            }
1190            //System.out.println("vars = " + Arrays.toString(vars));
1191            //System.out.println("v    = " + Arrays.toString(v));
1192        }
1193        TermOrder to = tord.reverse(partial);
1194        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v);
1195        pfac.partial = partial;
1196        return pfac;
1197    }
1198
1199
1200    /**
1201     * Get PolynomialComparator.
1202     * @return polynomial comparator.
1203     */
1204    public PolynomialComparator<C> getComparator() {
1205        return new PolynomialComparator<C>(tord, false);
1206    }
1207
1208
1209    /**
1210     * Get PolynomialComparator.
1211     * @param rev for reverse comparator.
1212     * @return polynomial comparator.
1213     */
1214    public PolynomialComparator<C> getComparator(boolean rev) {
1215        return new PolynomialComparator<C>(tord, rev);
1216    }
1217
1218
1219    /**
1220     * New variable names. Generate new names for variables,
1221     * @param prefix name prefix.
1222     * @param n number of variables.
1223     * @return new variable names.
1224     */
1225    public static String[] newVars(String prefix, int n) {
1226        String[] vars = new String[n];
1227        for (int i = 0; i < n; i++) {
1228            long m = varCounter.getAndIncrement();
1229            vars[i] = prefix + m;
1230        }
1231        return vars;
1232    }
1233
1234
1235    /**
1236     * New variable names. Generate new names for variables,
1237     * @param prefix name prefix.
1238     * @return new variable names.
1239     */
1240    public String[] newVars(String prefix) {
1241        return newVars(prefix, nvar);
1242    }
1243
1244
1245    /**
1246     * New variable names. Generate new names for variables,
1247     * @param n number of variables.
1248     * @return new variable names.
1249     */
1250    public static String[] newVars(int n) {
1251        return newVars("x", n);
1252    }
1253
1254
1255    /**
1256     * New variable names. Generate new names for variables,
1257     * @return new variable names.
1258     */
1259    public String[] newVars() {
1260        return newVars(nvar);
1261    }
1262
1263
1264    /*
1265     * Add variable names.
1266     * @param vars variable names to be recorded.
1267    public static void addVars(String[] vars) {
1268        if (vars == null) {
1269            return;
1270        }
1271        // synchronized (knownVars) {
1272        //   for (int i = 0; i < vars.length; i++) {
1273        //      knownVars.add(vars[i]); // eventually names 'overwritten'
1274        //   }
1275        // }
1276    }
1277     */
1278
1279
1280    /**
1281     * Permute variable names.
1282     * @param vars variable names.
1283     * @param P permutation.
1284     * @return P(vars).
1285     */
1286    public static String[] permuteVars(List<Integer> P, String[] vars) {
1287        if (vars == null || vars.length <= 1) {
1288            return vars;
1289        }
1290        String[] b = new String[vars.length];
1291        int j = 0;
1292        for (Integer i : P) {
1293            b[j++] = vars[i];
1294        }
1295        return b;
1296    }
1297
1298
1299    /**
1300     * Permutation of polynomial ring variables.
1301     * @param P permutation.
1302     * @return P(this).
1303     */
1304    public GenPolynomialRing<C> permutation(List<Integer> P) {
1305        if (nvar <= 1) {
1306            return this;
1307        }
1308        TermOrder tp = tord.permutation(P);
1309        if (vars == null) {
1310            return new GenPolynomialRing<C>(coFac, nvar, tp);
1311        }
1312        String[] v1 = new String[vars.length];
1313        for (int i = 0; i < v1.length; i++) {
1314            v1[i] = vars[v1.length - 1 - i];
1315        }
1316        String[] vp = permuteVars(P, v1);
1317        String[] v2 = new String[vp.length];
1318        for (int i = 0; i < vp.length; i++) {
1319            v2[i] = vp[vp.length - 1 - i];
1320        }
1321        return new GenPolynomialRing<C>(coFac, nvar, tp, v2);
1322    }
1323
1324
1325    /**
1326     * Characteristic polynomial of matrix.
1327     * <b>Note:</b> using Faddeev–LeVerrier algorithm
1328     * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm
1329     * @param A a square matrix.
1330     * @return characteristic polynomial of A.
1331     */
1332    public GenPolynomial<C> charPolynomial(GenMatrix<C> A) {
1333        if (A == null || A.isZERO()) {
1334            return ZERO;
1335        }
1336        if (nvar != 1) {
1337            throw new IllegalArgumentException("no univariate polynomial ring");
1338        }
1339        GenMatrixRing<C> mfac = A.ring;
1340        int n = mfac.rows;
1341        java.math.BigInteger c0 = coFac.characteristic();
1342        if (c0.signum() > 0 && c0.compareTo(java.math.BigInteger.valueOf(n)) <= 0) {
1343            throw new UnsupportedOperationException("characteristic <= n: " + c0 + " <= " + n);
1344        }
1345        GenPolynomial<C> ret = copy(ZERO);
1346        //SortedMap<ExpVector, C> tm = ret.val;
1347        GenMatrix<C> M = mfac.getZERO(); //new GenMatrix<C>(A.ring);
1348        GenMatrix<C> I = mfac.getONE();
1349        ExpVector e = ExpVector.create(1, 0, n);
1350        C one = coFac.getONE();
1351        ret = ret.sum(one, e);
1352        C c = coFac.getONE();
1353        GenMatrix<C> Ms = null;
1354        GenMatrix<C> Mp = null, Mc;
1355        // M_0 = 0, c_n = 1
1356        // k = 1..n: M_k = A*M_{k-1} + c_{n-k+1}*I, c_{n-k} = -1/k*trace(A*M_k)
1357        for (int k = 1; k <= n; k++) {
1358            if (Ms == null) {
1359                Mp = A.multiply(M); // reuse A*Mp? todo
1360            } else {
1361                Mp = Ms;
1362            }
1363            Mc = I.multiply(c);
1364            Mp = Mp.sum(Mc);
1365            Ms = A.multiply(Mp);
1366            C cp = Ms.trace();
1367            C ki = coFac.fromInteger(k).inverse(); // characteristic != k
1368            cp = cp.multiply(ki).negate();
1369            M = Mp;
1370            c = cp;
1371            e = ExpVector.create(1, 0, n-k);
1372            ret = ret.sum(c, e);
1373            //System.out.println("k = " + k + ", c = " + c + ", M = " + M);
1374        }
1375        // only for demonstrating how to get the determinant, trace and inverse:
1376        // C det = coFac.getZERO(); //ret.trailingBaseCoefficient();
1377        // //System.out.println("n = " + n + ", deg = " + ret.degree());
1378        // if (n % 2 != 0) {
1379        //     det = det.negate();
1380        // }
1381        // if (! det.isZERO()) {
1382        //     C d = det.inverse();
1383        //     if ((n-1) % 2 != 0) {
1384        //         d = d.negate();
1385        //     }
1386        //     Mc = Mp.multiply(d);
1387        // } else {
1388        //     Mc = null;
1389        // }
1390        // //System.out.println("det = " + det + ", trace = " + c + ", A^{-1} = " + Mc);
1391        return ret;
1392    }
1393
1394
1395    /**
1396     * Determinant of matrix from characteristic polynomial.
1397     * <b>Note:</b> using Faddeev–LeVerrier algorithm
1398     * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm
1399     * @param P characteristic polynomial of a matrix.
1400     * @return determinant from characteristic polynomial.
1401     */
1402    public C determinantFromCharPol(GenPolynomial<C> P) {
1403        C det = coFac.getZERO();
1404        if (P == null || P.isZERO()) {
1405            return det;
1406        }
1407        det = P.trailingBaseCoefficient();
1408        if (P.degree() % 2 != 0) {
1409            det = det.negate();
1410        }
1411        return det;
1412    }
1413
1414
1415    /**
1416     * Determinant of matrix via characteristic polynomial.
1417     * <b>Note:</b> using Faddeev–LeVerrier algorithm
1418     * @see https://en.wikipedia.org/wiki/Faddeev%E2%80%93LeVerrier_algorithm
1419     * @param A square matrix.
1420     * @return determinant of A from characteristic polynomial of A.
1421     */
1422    public C determinant(GenMatrix<C> A) {
1423        GenPolynomial<C> P = charPolynomial(A);
1424        return determinantFromCharPol(P);
1425    }
1426
1427
1428    /**
1429     * Trace of matrix from characteristic polynomial.
1430     * @param P characteristic polynomial of a matrix.
1431     * @return trace from characteristic polynomial.
1432     */
1433    public C traceFromCharPol(GenPolynomial<C> P) {
1434        if (P == null || P.isZERO()) {
1435            return coFac.getZERO();
1436        }
1437        long n = P.degree();
1438        ExpVector e = ExpVector.create(1, 0, n-1);
1439        C t = P.coefficient(e).negate();
1440        return t;
1441    }
1442
1443
1444    /**
1445     * Get a GenPolynomial iterator.
1446     * @return an iterator over all polynomials.
1447     */
1448    public Iterator<GenPolynomial<C>> iterator() {
1449        if (coFac.isFinite()) {
1450            return new GenPolynomialIterator<C>(this);
1451        }
1452        logger.warn("ring of coefficients {} is infinite, constructing iterator only over monomials", coFac);
1453        return new GenPolynomialMonomialIterator<C>(this);
1454        //throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1455    }
1456
1457}
1458
1459
1460/**
1461 * Polynomial iterator.
1462 * @author Heinz Kredel
1463 */
1464class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1465
1466
1467    /**
1468     * data structure.
1469     */
1470    final GenPolynomialRing<C> ring;
1471
1472
1473    final Iterator<List<Long>> eviter;
1474
1475
1476    final List<ExpVector> powers;
1477
1478
1479    final List<Iterable<C>> coeffiter;
1480
1481
1482    Iterator<List<C>> itercoeff;
1483
1484
1485    GenPolynomial<C> current;
1486
1487
1488    /**
1489     * Polynomial iterator constructor.
1490     */
1491    @SuppressWarnings("unchecked")
1492    public GenPolynomialIterator(GenPolynomialRing<C> fac) {
1493        ring = fac;
1494        LongIterable li = new LongIterable();
1495        li.setNonNegativeIterator();
1496        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1497        for (int i = 0; i < ring.nvar; i++) {
1498            tlist.add(li);
1499        }
1500        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1501        eviter = ei.iterator();
1502        RingFactory<C> cf = ring.coFac;
1503        coeffiter = new ArrayList<Iterable<C>>();
1504        if (cf instanceof Iterable && cf.isFinite()) {
1505            Iterable<C> cfi = (Iterable<C>) cf;
1506            coeffiter.add(cfi);
1507        } else {
1508            throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1509        }
1510        CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1511        itercoeff = tuples.iterator();
1512        powers = new ArrayList<ExpVector>();
1513        ExpVector e = ExpVector.create(eviter.next());
1514        powers.add(e);
1515        //System.out.println("new e = " + e);
1516        //System.out.println("powers = " + powers);
1517        List<C> c = itercoeff.next();
1518        //System.out.println("coeffs = " + c);
1519        current = new GenPolynomial<C>(ring, c.get(0), e);
1520    }
1521
1522
1523    /**
1524     * Test for availability of a next element.
1525     * @return true if the iteration has more elements, else false.
1526     */
1527    public boolean hasNext() {
1528        return true;
1529    }
1530
1531
1532    /**
1533     * Get next polynomial.
1534     * @return next polynomial.
1535     */
1536    public synchronized GenPolynomial<C> next() {
1537        GenPolynomial<C> res = current;
1538        if (!itercoeff.hasNext()) {
1539            ExpVector e = ExpVector.create(eviter.next());
1540            powers.add(0, e); // add new ev at beginning
1541            //System.out.println("new e = " + e);
1542            //System.out.println("powers = " + powers);
1543            if (coeffiter.size() == 1) { // shorten first iterator by one element
1544                coeffiter.add(coeffiter.get(0));
1545                Iterable<C> it = coeffiter.get(0);
1546                List<C> elms = new ArrayList<C>();
1547                for (C elm : it) {
1548                    elms.add(elm);
1549                }
1550                elms.remove(0);
1551                coeffiter.set(0, elms);
1552            } else {
1553                coeffiter.add(coeffiter.get(1));
1554            }
1555            CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1556            itercoeff = tuples.iterator();
1557        }
1558        List<C> coeffs = itercoeff.next();
1559        //      while ( coeffs.get(0).isZERO() ) {
1560        //             System.out.println(" skip zero ");
1561        //          coeffs = itercoeff.next(); // skip tuples with zero in first component
1562        //      }
1563        //System.out.println("coeffs = " + coeffs);
1564        GenPolynomial<C> pol = ring.getZERO().copy();
1565        int i = 0;
1566        for (ExpVector f : powers) {
1567            C c = coeffs.get(i++);
1568            if (c.isZERO()) {
1569                continue;
1570            }
1571            if (pol.val.get(f) != null) {
1572                System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f));
1573                throw new RuntimeException("error in iterator");
1574            }
1575            pol.doPutToMap(f, c);
1576        }
1577        current = pol;
1578        return res;
1579    }
1580
1581
1582    /**
1583     * Remove an element if allowed.
1584     */
1585    public void remove() {
1586        throw new UnsupportedOperationException("cannot remove elements");
1587    }
1588}
1589
1590
1591/**
1592 * Polynomial monomial iterator.
1593 * @author Heinz Kredel
1594 */
1595class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1596
1597
1598    /**
1599     * data structure.
1600     */
1601    final GenPolynomialRing<C> ring;
1602
1603
1604    final Iterator<List> iter;
1605
1606
1607    GenPolynomial<C> current;
1608
1609
1610    /**
1611     * Polynomial iterator constructor.
1612     */
1613    @SuppressWarnings("unchecked")
1614    public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) {
1615        ring = fac;
1616        LongIterable li = new LongIterable();
1617        li.setNonNegativeIterator();
1618        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1619        for (int i = 0; i < ring.nvar; i++) {
1620            tlist.add(li);
1621        }
1622        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1623        //Iterator<List<Long>> eviter = ei.iterator();
1624
1625        RingFactory<C> cf = ring.coFac;
1626        Iterable<C> coeffiter;
1627        if (cf instanceof Iterable && !cf.isFinite()) {
1628            Iterable<C> cfi = (Iterable<C>) cf;
1629            coeffiter = cfi;
1630        } else {
1631            throw new IllegalArgumentException("only for infinite iterable coefficients implemented");
1632        }
1633
1634        // Cantor iterator for exponents and coefficients
1635        List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter
1636        eci.add(ei);
1637        eci.add(coeffiter);
1638        CartesianProductInfinite ecp = new CartesianProductInfinite(eci);
1639        iter = ecp.iterator();
1640
1641        List ec = iter.next();
1642        List<Long> ecl = (List<Long>) ec.get(0);
1643        C c = (C) ec.get(1); // zero
1644        ExpVector e = ExpVector.create(ecl);
1645        //System.out.println("exp    = " + e);
1646        //System.out.println("coeffs = " + c);
1647        current = new GenPolynomial<C>(ring, c, e);
1648    }
1649
1650
1651    /**
1652     * Test for availability of a next element.
1653     * @return true if the iteration has more elements, else false.
1654     */
1655    public boolean hasNext() {
1656        return true;
1657    }
1658
1659
1660    /**
1661     * Get next polynomial.
1662     * @return next polynomial.
1663     */
1664    @SuppressWarnings("unchecked")
1665    public synchronized GenPolynomial<C> next() {
1666        GenPolynomial<C> res = current;
1667
1668        List ec = iter.next();
1669        C c = (C) ec.get(1);
1670        while (c.isZERO()) { // zero already done in first next
1671            ec = iter.next();
1672            c = (C) ec.get(1);
1673        }
1674        List<Long> ecl = (List<Long>) ec.get(0);
1675        ExpVector e = ExpVector.create(ecl);
1676        //System.out.println("exp    = " + e);
1677        //System.out.println("coeffs = " + c);
1678        current = new GenPolynomial<C>(ring, c, e);
1679
1680        return res;
1681    }
1682
1683
1684    /**
1685     * Remove an element if allowed.
1686     */
1687    public void remove() {
1688        throw new UnsupportedOperationException("cannot remove elements");
1689    }
1690}