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