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.concurrent.atomic.AtomicLong;
018
019import org.apache.logging.log4j.LogManager;
020import org.apache.logging.log4j.Logger;
021
022import edu.jas.arith.ModIntegerRing;
023import edu.jas.kern.PreemptStatus;
024import edu.jas.kern.PrettyPrint;
025import edu.jas.kern.Scripting;
026import edu.jas.structure.RingElem;
027import edu.jas.structure.RingFactory;
028import edu.jas.util.CartesianProduct;
029import edu.jas.util.CartesianProductInfinite;
030import edu.jas.util.LongIterable;
031
032
033/**
034 * GenPolynomialRing generic polynomial factory. It implements RingFactory for
035 * n-variate ordered polynomials over coefficients C. The variables commute with
036 * each other and with the coefficients. For non-commutative coefficients some
037 * care is taken to respect the multiplication order.
038 *
039 * Almost immutable object, except variable names.
040 * @param <C> coefficient type
041 * @author Heinz Kredel
042 */
043
044public class GenPolynomialRing<C extends RingElem<C>>
045                implements RingFactory<GenPolynomial<C>>, Iterable<GenPolynomial<C>> {
046
047
048    /**
049     * The factory for the coefficients.
050     */
051    public final RingFactory<C> coFac;
052
053
054    /**
055     * The number of variables.
056     */
057    public final int nvar;
058
059
060    /**
061     * The term order.
062     */
063    public final TermOrder tord;
064
065
066    /**
067     * True for partially reversed variables.
068     */
069    protected boolean partial;
070
071
072    /**
073     * The names of the variables. This value can be modified.
074     */
075    protected String[] vars;
076
077
078    /**
079     * Counter to distinguish new variables.
080     */
081    private static AtomicLong varCounter = new AtomicLong(0L);
082
083
084    /**
085     * The constant polynomial 0 for this ring.
086     */
087    public final GenPolynomial<C> ZERO;
088
089
090    /**
091     * The constant polynomial 1 for this ring.
092     */
093    public final GenPolynomial<C> ONE;
094
095
096    /**
097     * The constant exponent vector 0 for this ring.
098     */
099    public final ExpVector evzero;
100
101
102    /**
103     * A default random sequence generator.
104     */
105    protected final static Random random = new Random();
106
107
108    /**
109     * Indicator if this ring is a field.
110     */
111    protected int isField = -1; // initially unknown
112
113
114    /**
115     * Log4j logger object.
116     */
117    private static final Logger logger = LogManager.getLogger(GenPolynomialRing.class);
118
119
120    /**
121     * Count for number of polynomial creations.
122     */
123    static int creations = 0;
124
125
126    /**
127     * Flag to enable if preemptive interrrupt is checked.
128     */
129    final boolean checkPreempt = PreemptStatus.isAllowed();
130
131
132    /**
133     * The constructor creates a polynomial factory object with the default term
134     * order.
135     * @param cf factory for coefficients of type C.
136     * @param n number of variables.
137     */
138    public GenPolynomialRing(RingFactory<C> cf, int n) {
139        this(cf, n, new TermOrder(), null);
140    }
141
142
143    /**
144     * The constructor creates a polynomial factory object.
145     * @param cf factory for coefficients of type C.
146     * @param n number of variables.
147     * @param t a term order.
148     */
149    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t) {
150        this(cf, n, t, null);
151    }
152
153
154    /**
155     * The constructor creates a polynomial factory object.
156     * @param cf factory for coefficients of type C.
157     * @param v names for the variables.
158     */
159    public GenPolynomialRing(RingFactory<C> cf, String[] v) {
160        this(cf, v.length, v);
161    }
162
163
164    /**
165     * The constructor creates a polynomial factory object.
166     * @param cf factory for coefficients of type C.
167     * @param n number of variables.
168     * @param v names for the variables.
169     */
170    public GenPolynomialRing(RingFactory<C> cf, int n, String[] v) {
171        this(cf, n, new TermOrder(), v);
172    }
173
174
175    /**
176     * The constructor creates a polynomial factory object.
177     * @param cf factory for coefficients of type C.
178     * @param t a term order.
179     * @param v names for the variables.
180     */
181    public GenPolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) {
182        this(cf, v.length, t, v);
183    }
184
185
186    /**
187     * The constructor creates a polynomial factory object.
188     * @param cf factory for coefficients of type C.
189     * @param v names for the variables.
190     * @param t a term order.
191     */
192    public GenPolynomialRing(RingFactory<C> cf, String[] v, TermOrder t) {
193        this(cf, v.length, t, v);
194    }
195
196
197    /**
198     * The constructor creates a polynomial factory object.
199     * @param cf factory for coefficients of type C.
200     * @param n number of variables.
201     * @param t a term order.
202     * @param v names for the variables.
203     */
204    public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) {
205        coFac = cf;
206        nvar = n;
207        tord = t;
208        partial = false;
209        if (v == null) {
210            vars = null;
211        } else {
212            vars = Arrays.copyOf(v, v.length); // > Java-5
213        }
214        ZERO = new GenPolynomial<C>(this);
215        C coeff = coFac.getONE();
216        evzero = ExpVector.create(nvar);
217        ONE = new GenPolynomial<C>(this, coeff, evzero);
218        if (vars == null) {
219            if (PrettyPrint.isTrue()) {
220                vars = newVars("x", nvar);
221            }
222        } else {
223            if (vars.length != nvar) {
224                throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar);
225            }
226            // addVars(vars);
227        }
228    }
229
230
231    /**
232     * The constructor creates a polynomial factory object with the the same
233     * term order, number of variables and variable names as the given
234     * polynomial factory, only the coefficient factories differ.
235     * @param cf factory for coefficients of type C.
236     * @param o other polynomial ring.
237     */
238    public GenPolynomialRing(RingFactory<C> cf, GenPolynomialRing o) {
239        this(cf, o.nvar, o.tord, o.vars);
240    }
241
242
243    /**
244     * The constructor creates a polynomial factory object with the the same
245     * coefficient factory, number of variables and variable names as the given
246     * polynomial factory, only the term order differs.
247     * @param to term order.
248     * @param o other polynomial ring.
249     */
250    public GenPolynomialRing(GenPolynomialRing<C> o, TermOrder to) {
251        this(o.coFac, o.nvar, to, o.vars);
252    }
253
254
255    /**
256     * Copy this factory.
257     * @return a clone of this.
258     */
259    public GenPolynomialRing<C> copy() {
260        return new GenPolynomialRing<C>(coFac, this);
261    }
262
263
264    /**
265     * Get the String representation.
266     * @see java.lang.Object#toString()
267     */
268    @SuppressWarnings("cast")
269    @Override
270    public String toString() {
271        String res = null;
272        if (PrettyPrint.isTrue()) { // wrong: && coFac != null
273            String scf = coFac.getClass().getSimpleName();
274            if (coFac instanceof AlgebraicNumberRing) {
275                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
276                res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]";
277            }
278            if (coFac instanceof GenPolynomialRing) {
279                GenPolynomialRing rf = (GenPolynomialRing) coFac;
280                //String[] v = rf.vars;
281                //RingFactory cf = rf.coFac;
282                //String cs;
283                //if (cf instanceof ModIntegerRing) {
284                //    cs = cf.toString();
285                //} else {
286                //    cs = " " + cf.getClass().getSimpleName();
287                //}
288                //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } ";
289                res = "IntFunc" + "( " + rf.toString() + " )";
290            }
291            if (((Object) coFac) instanceof ModIntegerRing) {
292                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
293                res = "Mod " + mn.getModul() + " ";
294            }
295            if (res == null) {
296                res = coFac.toString();
297                if (res.matches("[0-9].*")) {
298                    res = scf;
299                }
300            }
301            res += "( " + varsToString() + " ) " + tord.toString() + " ";
302        } else {
303            res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " ";
304            if (coFac instanceof AlgebraicNumberRing) {
305                AlgebraicNumberRing an = (AlgebraicNumberRing) coFac;
306                res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]";
307            }
308            if (coFac instanceof GenPolynomialRing) {
309                GenPolynomialRing rf = (GenPolynomialRing) coFac;
310                //String[] v = rf.vars;
311                //RingFactory cf = rf.coFac;
312                //String cs;
313                //if (cf instanceof ModIntegerRing) {
314                //    cs = cf.toString();
315                //} else {
316                //    cs = " " + cf.getClass().getSimpleName();
317                //}
318                //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } ";
319                res = "IntFunc" + "( " + rf.toString() + " )";
320            }
321            if (((Object) coFac) instanceof ModIntegerRing) {
322                ModIntegerRing mn = (ModIntegerRing) ((Object) coFac);
323                res = "Mod " + mn.getModul() + " ";
324            }
325            //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]";
326            res += "( " + varsToString() + " ) " + tord.toString() + " ]";
327        }
328        return res;
329    }
330
331
332    /**
333     * Get a scripting compatible string representation.
334     * @return script compatible representation for this Element.
335     * @see edu.jas.structure.Element#toScript()
336     */
337    @Override
338    public String toScript() {
339        StringBuffer s = new StringBuffer();
340        switch (Scripting.getLang()) {
341        case Ruby:
342            s.append("PolyRing.new(");
343            break;
344        case Python:
345        default:
346            s.append("PolyRing(");
347        }
348        if (coFac instanceof RingElem) {
349            s.append(((RingElem<C>) coFac).toScriptFactory());
350        } else {
351            s.append(coFac.toScript().trim());
352        }
353        s.append(",\"" + varsToString() + "\"");
354        String to = tord.toScript();
355        s.append("," + to);
356        s.append(")");
357        return s.toString();
358    }
359
360
361    /**
362     * Get a scripting compatible string representation of an ExpVector of this
363     * ring.
364     * @param e exponent vector
365     * @return script compatible representation for the ExpVector.
366     */
367    public String toScript(ExpVector e) {
368        if (e == null) {
369            return "null";
370        }
371        if (vars != null) {
372            return e.toScript(vars);
373        }
374        return e.toScript();
375    }
376
377
378    /**
379     * Comparison with any other object.
380     * @see java.lang.Object#equals(java.lang.Object)
381     */
382    @Override
383    @SuppressWarnings("unchecked")
384    public boolean equals(Object other) {
385        if (other == null) {
386            return false;
387        }
388        if (!(other instanceof GenPolynomialRing)) {
389            return false;
390        }
391        GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other;
392        if (nvar != oring.nvar) {
393            return false;
394        }
395        if (!coFac.equals(oring.coFac)) {
396            return false;
397        }
398        if (!tord.equals(oring.tord)) {
399            return false;
400        }
401        // same variables required ?
402        if (!Arrays.deepEquals(vars, oring.vars)) {
403            return false;
404        }
405        return true;
406    }
407
408
409    /**
410     * Hash code for this polynomial ring.
411     * @see java.lang.Object#hashCode()
412     */
413    @Override
414    public int hashCode() {
415        int h;
416        h = (nvar << 27);
417        h += (coFac.hashCode() << 11);
418        h += (tord.hashCode() << 9);
419        h += Arrays.hashCode(vars);
420        //System.out.println("GenPolynomialRing.hashCode: " + h);
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(
450                            "v not matching number of variables: " + Arrays.toString(v) + ", 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        return extendLower(vn, false);
1015    }
1016
1017
1018    /**
1019     * Extend lower variables. Extend number of variables by length(vn).
1020     * @param vn names for extended lower variables.
1021     * @param top true for TOP term order, false for POT term order.
1022     * @return extended polynomial ring factory.
1023     */
1024    public GenPolynomialRing<C> extendLower(String[] vn, boolean top) {
1025        if (vn == null || vars == null) {
1026            throw new IllegalArgumentException("vn and vars may not be null");
1027        }
1028        int i = vn.length;
1029        String[] v = new String[vars.length + i];
1030        for (int k = 0; k < vn.length; k++) {
1031            v[k] = vn[k];
1032        }
1033        for (int k = 0; k < vars.length; k++) {
1034            v[vn.length + k] = vars[k];
1035        }
1036        TermOrder to = tord.extendLower(nvar, i, top);
1037        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1038        return pfac;
1039    }
1040
1041
1042    /**
1043     * Contract variables. Used e.g. in module embedding. Contract number of
1044     * variables by i.
1045     * @param i number of variables to remove.
1046     * @return contracted polynomial ring factory.
1047     */
1048    public GenPolynomialRing<C> contract(int i) {
1049        String[] v = null;
1050        if (vars != null) {
1051            v = new String[vars.length - i];
1052            for (int j = 0; j < vars.length - i; j++) {
1053                v[j] = vars[j];
1054            }
1055        }
1056        TermOrder to = tord.contract(i, nvar - i);
1057        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v);
1058        return pfac;
1059    }
1060
1061
1062    /**
1063     * Recursive representation as polynomial with i main variables.
1064     * @param i number of main variables.
1065     * @return recursive polynomial ring factory.
1066     */
1067    public GenPolynomialRing<GenPolynomial<C>> recursive(int i) {
1068        if (i <= 0 || i >= nvar) {
1069            throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar);
1070        }
1071        GenPolynomialRing<C> cfac = contract(i);
1072        String[] v = null;
1073        if (vars != null) {
1074            v = new String[i];
1075            int k = 0;
1076            for (int j = nvar - i; j < nvar; j++) {
1077                v[k++] = vars[j];
1078            }
1079        }
1080        TermOrder to = tord.contract(0, i); // ??
1081        GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v);
1082        return pfac;
1083    }
1084
1085
1086    /**
1087     * Distributive representation as polynomial with all main variables.
1088     * @return distributive polynomial ring factory.
1089     */
1090    @SuppressWarnings("unchecked")
1091    public GenPolynomialRing<C> distribute() {
1092        if (!(coFac instanceof GenPolynomialRing)) {
1093            return this;
1094        }
1095        RingFactory cf = coFac;
1096        RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf;
1097        GenPolynomialRing cr = (GenPolynomialRing) cfp;
1098        GenPolynomialRing<C> pfac;
1099        if (cr.vars != null) {
1100            pfac = extend(cr.vars);
1101        } else {
1102            pfac = extend(cr.nvar);
1103        }
1104        return pfac;
1105    }
1106
1107
1108    /**
1109     * Reverse variables. Used e.g. in opposite rings.
1110     * @return polynomial ring factory with reversed variables.
1111     */
1112    public GenPolynomialRing<C> reverse() {
1113        return reverse(false);
1114    }
1115
1116
1117    /**
1118     * Reverse variables. Used e.g. in opposite rings.
1119     * @param partial true for partialy reversed term orders.
1120     * @return polynomial ring factory with reversed variables.
1121     */
1122    public GenPolynomialRing<C> reverse(boolean partial) {
1123        String[] v = null;
1124        if (vars != null) { // vars are not inversed
1125            v = new String[vars.length];
1126            int k = tord.getSplit();
1127            if (partial && k < vars.length) {
1128                // copy upper
1129                for (int j = 0; j < k; j++) {
1130                    //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper
1131                    v[vars.length - k + j] = vars[vars.length - k + j];
1132                }
1133                // reverse lower
1134                for (int j = 0; j < vars.length - k; j++) {
1135                    //v[j] = vars[j]; // copy upper
1136                    v[j] = vars[vars.length - k - j - 1];
1137                }
1138            } else {
1139                for (int j = 0; j < vars.length; j++) {
1140                    v[j] = vars[vars.length - 1 - j];
1141                }
1142            }
1143            //System.out.println("vars = " + Arrays.toString(vars));
1144            //System.out.println("v    = " + Arrays.toString(v));
1145        }
1146        TermOrder to = tord.reverse(partial);
1147        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v);
1148        pfac.partial = partial;
1149        return pfac;
1150    }
1151
1152
1153    /**
1154     * Get PolynomialComparator.
1155     * @return polynomial comparator.
1156     */
1157    public PolynomialComparator<C> getComparator() {
1158        return new PolynomialComparator<C>(tord, false);
1159    }
1160
1161
1162    /**
1163     * Get PolynomialComparator.
1164     * @param rev for reverse comparator.
1165     * @return polynomial comparator.
1166     */
1167    public PolynomialComparator<C> getComparator(boolean rev) {
1168        return new PolynomialComparator<C>(tord, rev);
1169    }
1170
1171
1172    /**
1173     * New variable names. Generate new names for variables,
1174     * @param prefix name prefix.
1175     * @param n number of variables.
1176     * @return new variable names.
1177     */
1178    public static String[] newVars(String prefix, int n) {
1179        String[] vars = new String[n];
1180        for (int i = 0; i < n; i++) {
1181            long m = varCounter.getAndIncrement();
1182            vars[i] = prefix + m;
1183        }
1184        return vars;
1185    }
1186
1187
1188    /**
1189     * New variable names. Generate new names for variables,
1190     * @param prefix name prefix.
1191     * @return new variable names.
1192     */
1193    public String[] newVars(String prefix) {
1194        return newVars(prefix, nvar);
1195    }
1196
1197
1198    /**
1199     * New variable names. Generate new names for variables,
1200     * @param n number of variables.
1201     * @return new variable names.
1202     */
1203    public static String[] newVars(int n) {
1204        return newVars("x", n);
1205    }
1206
1207
1208    /**
1209     * New variable names. Generate new names for variables,
1210     * @return new variable names.
1211     */
1212    public String[] newVars() {
1213        return newVars(nvar);
1214    }
1215
1216
1217    /*
1218     * Add variable names.
1219     * @param vars variable names to be recorded.
1220    public static void addVars(String[] vars) {
1221        if (vars == null) {
1222            return;
1223        }
1224        // synchronized (knownVars) {
1225        //   for (int i = 0; i < vars.length; i++) {
1226        //      knownVars.add(vars[i]); // eventualy names 'overwritten'
1227        //   }
1228        // }
1229    }
1230     */
1231
1232
1233    /**
1234     * Permute variable names.
1235     * @param vars variable names.
1236     * @param P permutation.
1237     * @return P(vars).
1238     */
1239    public static String[] permuteVars(List<Integer> P, String[] vars) {
1240        if (vars == null || vars.length <= 1) {
1241            return vars;
1242        }
1243        String[] b = new String[vars.length];
1244        int j = 0;
1245        for (Integer i : P) {
1246            b[j++] = vars[i];
1247        }
1248        return b;
1249    }
1250
1251
1252    /**
1253     * Permutation of polynomial ring variables.
1254     * @param P permutation.
1255     * @return P(this).
1256     */
1257    public GenPolynomialRing<C> permutation(List<Integer> P) {
1258        if (nvar <= 1) {
1259            return this;
1260        }
1261        TermOrder tp = tord.permutation(P);
1262        if (vars == null) {
1263            return new GenPolynomialRing<C>(coFac, nvar, tp);
1264        }
1265        String[] v1 = new String[vars.length];
1266        for (int i = 0; i < v1.length; i++) {
1267            v1[i] = vars[v1.length - 1 - i];
1268        }
1269        String[] vp = permuteVars(P, v1);
1270        String[] v2 = new String[vp.length];
1271        for (int i = 0; i < vp.length; i++) {
1272            v2[i] = vp[vp.length - 1 - i];
1273        }
1274        return new GenPolynomialRing<C>(coFac, nvar, tp, v2);
1275    }
1276
1277
1278    /**
1279     * Get a GenPolynomial iterator.
1280     * @return an iterator over all polynomials.
1281     */
1282    public Iterator<GenPolynomial<C>> iterator() {
1283        if (coFac.isFinite()) {
1284            return new GenPolynomialIterator<C>(this);
1285        }
1286        logger.warn("ring of coefficients " + coFac
1287                        + " is infinite, constructing iterator only over monomials");
1288        return new GenPolynomialMonomialIterator<C>(this);
1289        //throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1290    }
1291
1292}
1293
1294
1295/**
1296 * Polynomial iterator.
1297 * @author Heinz Kredel
1298 */
1299class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1300
1301
1302    /**
1303     * data structure.
1304     */
1305    final GenPolynomialRing<C> ring;
1306
1307
1308    final Iterator<List<Long>> eviter;
1309
1310
1311    final List<ExpVector> powers;
1312
1313
1314    final List<Iterable<C>> coeffiter;
1315
1316
1317    Iterator<List<C>> itercoeff;
1318
1319
1320    GenPolynomial<C> current;
1321
1322
1323    /**
1324     * Polynomial iterator constructor.
1325     */
1326    @SuppressWarnings("unchecked")
1327    public GenPolynomialIterator(GenPolynomialRing<C> fac) {
1328        ring = fac;
1329        LongIterable li = new LongIterable();
1330        li.setNonNegativeIterator();
1331        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1332        for (int i = 0; i < ring.nvar; i++) {
1333            tlist.add(li);
1334        }
1335        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1336        eviter = ei.iterator();
1337        RingFactory<C> cf = ring.coFac;
1338        coeffiter = new ArrayList<Iterable<C>>();
1339        if (cf instanceof Iterable && cf.isFinite()) {
1340            Iterable<C> cfi = (Iterable<C>) cf;
1341            coeffiter.add(cfi);
1342        } else {
1343            throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1344        }
1345        CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1346        itercoeff = tuples.iterator();
1347        powers = new ArrayList<ExpVector>();
1348        ExpVector e = ExpVector.create(eviter.next());
1349        powers.add(e);
1350        //System.out.println("new e = " + e);
1351        //System.out.println("powers = " + powers);
1352        List<C> c = itercoeff.next();
1353        //System.out.println("coeffs = " + c);
1354        current = new GenPolynomial<C>(ring, c.get(0), e);
1355    }
1356
1357
1358    /**
1359     * Test for availability of a next element.
1360     * @return true if the iteration has more elements, else false.
1361     */
1362    public boolean hasNext() {
1363        return true;
1364    }
1365
1366
1367    /**
1368     * Get next polynomial.
1369     * @return next polynomial.
1370     */
1371    public synchronized GenPolynomial<C> next() {
1372        GenPolynomial<C> res = current;
1373        if (!itercoeff.hasNext()) {
1374            ExpVector e = ExpVector.create(eviter.next());
1375            powers.add(0, e); // add new ev at beginning
1376            //System.out.println("new e = " + e);
1377            //System.out.println("powers = " + powers);
1378            if (coeffiter.size() == 1) { // shorten frist iterator by one element
1379                coeffiter.add(coeffiter.get(0));
1380                Iterable<C> it = coeffiter.get(0);
1381                List<C> elms = new ArrayList<C>();
1382                for (C elm : it) {
1383                    elms.add(elm);
1384                }
1385                elms.remove(0);
1386                coeffiter.set(0, elms);
1387            } else {
1388                coeffiter.add(coeffiter.get(1));
1389            }
1390            CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1391            itercoeff = tuples.iterator();
1392        }
1393        List<C> coeffs = itercoeff.next();
1394        //      while ( coeffs.get(0).isZERO() ) {
1395        //             System.out.println(" skip zero ");
1396        //          coeffs = itercoeff.next(); // skip tuples with zero in first component
1397        //      }
1398        //System.out.println("coeffs = " + coeffs);
1399        GenPolynomial<C> pol = ring.getZERO().copy();
1400        int i = 0;
1401        for (ExpVector f : powers) {
1402            C c = coeffs.get(i++);
1403            if (c.isZERO()) {
1404                continue;
1405            }
1406            if (pol.val.get(f) != null) {
1407                System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f));
1408                throw new RuntimeException("error in iterator");
1409            }
1410            pol.doPutToMap(f, c);
1411        }
1412        current = pol;
1413        return res;
1414    }
1415
1416
1417    /**
1418     * Remove an element if allowed.
1419     */
1420    public void remove() {
1421        throw new UnsupportedOperationException("cannnot remove elements");
1422    }
1423}
1424
1425
1426/**
1427 * Polynomial monomial iterator.
1428 * @author Heinz Kredel
1429 */
1430class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1431
1432
1433    /**
1434     * data structure.
1435     */
1436    final GenPolynomialRing<C> ring;
1437
1438
1439    final Iterator<List> iter;
1440
1441
1442    GenPolynomial<C> current;
1443
1444
1445    /**
1446     * Polynomial iterator constructor.
1447     */
1448    @SuppressWarnings("unchecked")
1449    public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) {
1450        ring = fac;
1451        LongIterable li = new LongIterable();
1452        li.setNonNegativeIterator();
1453        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1454        for (int i = 0; i < ring.nvar; i++) {
1455            tlist.add(li);
1456        }
1457        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1458        //Iterator<List<Long>> eviter = ei.iterator();
1459
1460        RingFactory<C> cf = ring.coFac;
1461        Iterable<C> coeffiter;
1462        if (cf instanceof Iterable && !cf.isFinite()) {
1463            Iterable<C> cfi = (Iterable<C>) cf;
1464            coeffiter = cfi;
1465        } else {
1466            throw new IllegalArgumentException("only for infinite iterable coefficients implemented");
1467        }
1468
1469        // Cantor iterator for exponents and coeffcients
1470        List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter
1471        eci.add(ei);
1472        eci.add(coeffiter);
1473        CartesianProductInfinite ecp = new CartesianProductInfinite(eci);
1474        iter = ecp.iterator();
1475
1476        List ec = iter.next();
1477        List<Long> ecl = (List<Long>) ec.get(0);
1478        C c = (C) ec.get(1); // zero
1479        ExpVector e = ExpVector.create(ecl);
1480        //System.out.println("exp    = " + e);
1481        //System.out.println("coeffs = " + c);
1482        current = new GenPolynomial<C>(ring, c, e);
1483    }
1484
1485
1486    /**
1487     * Test for availability of a next element.
1488     * @return true if the iteration has more elements, else false.
1489     */
1490    public boolean hasNext() {
1491        return true;
1492    }
1493
1494
1495    /**
1496     * Get next polynomial.
1497     * @return next polynomial.
1498     */
1499    @SuppressWarnings("unchecked")
1500    public synchronized GenPolynomial<C> next() {
1501        GenPolynomial<C> res = current;
1502
1503        List ec = iter.next();
1504        C c = (C) ec.get(1);
1505        while (c.isZERO()) { // zero already done in first next
1506            ec = iter.next();
1507            c = (C) ec.get(1);
1508        }
1509        List<Long> ecl = (List<Long>) ec.get(0);
1510        ExpVector e = ExpVector.create(ecl);
1511        //System.out.println("exp    = " + e);
1512        //System.out.println("coeffs = " + c);
1513        current = new GenPolynomial<C>(ring, c, e);
1514
1515        return res;
1516    }
1517
1518
1519    /**
1520     * Remove an element if allowed.
1521     */
1522    public void remove() {
1523        throw new UnsupportedOperationException("cannnot remove elements");
1524    }
1525}