001/*
002 * $Id$
003 */
004
005package edu.jas.poly;
006
007
008import java.io.IOException;
009import java.io.Reader;
010import java.io.StringReader;
011import java.math.BigInteger;
012import java.util.ArrayList;
013import java.util.Arrays;
014import java.util.Iterator;
015import java.util.List;
016import java.util.Random;
017import java.util.SortedMap;
018import java.util.concurrent.atomic.AtomicLong;
019
020import org.apache.logging.log4j.LogManager;
021import org.apache.logging.log4j.Logger;
022
023import edu.jas.arith.ModIntegerRing;
024import edu.jas.kern.PreemptStatus;
025import edu.jas.kern.PrettyPrint;
026import edu.jas.kern.Scripting;
027import edu.jas.structure.RingElem;
028import edu.jas.structure.RingFactory;
029import edu.jas.util.CartesianProduct;
030import edu.jas.util.CartesianProductInfinite;
031import edu.jas.util.LongIterable;
032import edu.jas.vector.GenVector;
033
034
035/**
036 * GenPolynomialRing generic polynomial factory. It implements RingFactory for
037 * n-variate ordered polynomials over coefficients C. The variables commute with
038 * each other and with the coefficients. For non-commutative coefficients some
039 * care is taken to respect the multiplication order.
040 *
041 * Almost immutable object, except variable names.
042 * @param <C> coefficient type
043 * @author Heinz Kredel
044 */
045
046public class GenPolynomialRing<C extends RingElem<C>>
047                implements RingFactory<GenPolynomial<C>>, Iterable<GenPolynomial<C>> {
048
049
050    /**
051     * The factory for the coefficients.
052     */
053    public final RingFactory<C> coFac;
054
055
056    /**
057     * The number of variables.
058     */
059    public final int nvar;
060
061
062    /**
063     * The term order.
064     */
065    public final TermOrder tord;
066
067
068    /**
069     * True for partially reversed variables.
070     */
071    protected boolean partial;
072
073
074    /**
075     * The names of the variables. This value can be modified.
076     */
077    protected String[] vars;
078
079
080    /**
081     * Counter to distinguish new variables.
082     */
083    private static AtomicLong varCounter = new AtomicLong(0L);
084
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() << 9);
421        h += Arrays.hashCode(vars);
422        //System.out.println("GenPolynomialRing.hashCode: " + h);
423        return h;
424    }
425
426
427    /**
428     * Get the number of polynomial creations.
429     * @return creations.
430     */
431    public int getCreations() {
432        return creations;
433    }
434
435
436    /**
437     * Get the variable names.
438     * @return vars.
439     */
440    public String[] getVars() {
441        return Arrays.copyOf(vars, vars.length); // > Java-5
442    }
443
444
445    /**
446     * Set the variable names.
447     * @return old vars.
448     */
449    public String[] setVars(String[] v) {
450        if (v.length != nvar) {
451            throw new IllegalArgumentException(
452                            "v not matching number of variables: " + Arrays.toString(v) + ", nvar " + nvar);
453        }
454        String[] t = vars;
455        vars = Arrays.copyOf(v, v.length); // > Java-5 
456        return t;
457    }
458
459
460    /**
461     * Get a String representation of the variable names.
462     * @return names seperated by commas.
463     */
464    public String varsToString() {
465        if (vars == null) {
466            return "#" + nvar;
467        }
468        //return Arrays.toString(vars);
469        return ExpVector.varsToString(vars);
470    }
471
472
473    /**
474     * Get the zero element from the coefficients.
475     * @return 0 as C.
476     */
477    public C getZEROCoefficient() {
478        return coFac.getZERO();
479    }
480
481
482    /**
483     * Get the one element from the coefficients.
484     * @return 1 as C.
485     */
486    public C getONECoefficient() {
487        return coFac.getONE();
488    }
489
490
491    /**
492     * Get the zero element.
493     * @return 0 as GenPolynomial<C>.
494     */
495    public GenPolynomial<C> getZERO() {
496        return ZERO;
497    }
498
499
500    /**
501     * Get the one element.
502     * @return 1 as GenPolynomial<C>.
503     */
504    public GenPolynomial<C> getONE() {
505        return ONE;
506    }
507
508
509    /**
510     * Query if this ring is commutative.
511     * @return true if this ring is commutative, else false.
512     */
513    public boolean isCommutative() {
514        return coFac.isCommutative();
515    }
516
517
518    /**
519     * Query if this ring is associative.
520     * @return true if this ring is associative, else false.
521     */
522    public boolean isAssociative() {
523        return coFac.isAssociative();
524    }
525
526
527    /**
528     * Query if this ring is a field.
529     * @return false.
530     */
531    public boolean isField() {
532        if (isField > 0) {
533            return true;
534        }
535        if (isField == 0) {
536            return false;
537        }
538        if (coFac.isField() && nvar == 0) {
539            isField = 1;
540            return true;
541        }
542        isField = 0;
543        return false;
544    }
545
546
547    /**
548     * Characteristic of this ring.
549     * @return characteristic of this ring.
550     */
551    public java.math.BigInteger characteristic() {
552        return coFac.characteristic();
553    }
554
555
556    /**
557     * Get a (constant) GenPolynomial&lt;C&gt; element from a coefficient value.
558     * @param a coefficient.
559     * @return a GenPolynomial&lt;C&gt;.
560     */
561    public GenPolynomial<C> valueOf(C a) {
562        return new GenPolynomial<C>(this, a);
563    }
564
565
566    /**
567     * Get a GenPolynomial&lt;C&gt; element from an exponent vector.
568     * @param e exponent vector.
569     * @return a GenPolynomial&lt;C&gt;.
570     */
571    public GenPolynomial<C> valueOf(ExpVector e) {
572        if (e == null) {
573            return getZERO();
574        }
575        return new GenPolynomial<C>(this, coFac.getONE(), e);
576    }
577
578
579    /**
580     * Get a GenPolynomial&lt;C&gt; element from a list of exponent vectors.
581     * @param E list of exponent vector.
582     * @return a GenPolynomial&lt;C&gt;.
583     */
584    public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) {
585        if (E == null) {
586            return null;
587        }
588        List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size());
589        for (ExpVector e : E) {
590            GenPolynomial<C> p = valueOf(e);
591            P.add(p);
592        }
593        return P;
594    }
595
596
597    /**
598     * Get a GenPolynomial&lt;C&gt; element from a coeffcient and an exponent
599     * vector.
600     * @param a coefficient.
601     * @param e exponent vector.
602     * @return a GenPolynomial&lt;C&gt;.
603     */
604    public GenPolynomial<C> valueOf(C a, ExpVector e) {
605        return new GenPolynomial<C>(this, a, e);
606    }
607
608
609    /**
610     * Get a GenPolynomial&lt;C&gt; element from a monomial.
611     * @param m monomial.
612     * @return a GenPolynomial&lt;C&gt;.
613     */
614    public GenPolynomial<C> valueOf(Monomial<C> m) {
615        return new GenPolynomial<C>(this, m.c, m.e);
616    }
617
618
619    /**
620     * Get a (constant) GenPolynomial&lt;C&gt; element from a long value.
621     * @param a long.
622     * @return a GenPolynomial&lt;C&gt;.
623     */
624    public GenPolynomial<C> fromInteger(long a) {
625        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
626    }
627
628
629    /**
630     * Get a (constant) GenPolynomial&lt;C&gt; element from a BigInteger value.
631     * @param a BigInteger.
632     * @return a GenPolynomial&lt;C&gt;.
633     */
634    public GenPolynomial<C> fromInteger(BigInteger a) {
635        return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero);
636    }
637
638
639    /**
640     * Get a GenPolynomial&lt;C&gt; from a GenVector&lt;C&gt;.
641     * @param a GenVector&lt;C&gt;.
642     * @return a GenPolynomial&lt;C&gt;.
643     */
644    public GenPolynomial<C> fromVector(GenVector<C> a) {
645        if (a == null || a.isZERO()) {
646            return ZERO;
647        }
648        if (nvar != 1) {
649            throw new IllegalArgumentException("no univariate polynomial ring");
650        }
651        GenPolynomial<C> ret = copy(ZERO);
652        SortedMap<ExpVector, C> tm = ret.val;
653        long i = -1;
654        for (C m : a.val) {
655            i++;
656            if (m.isZERO()) {
657                continue;
658            }
659            ExpVector e = ExpVector.create(1, 0, i);
660            tm.put(e, m);
661        }
662        return ret;
663    }
664
665
666    /**
667     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
668     * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
669     * @param n number of terms.
670     * @return a random polynomial.
671     */
672    public GenPolynomial<C> random(int n) {
673        return random(n, random);
674    }
675
676
677    /**
678     * Random polynomial. Generates a random polynomial with k = 5, l = n, d =
679     * n, q = (nvar == 1) ? 0.5 : 0.3.
680     * @param n number of terms.
681     * @param rnd is a source for random bits.
682     * @return a random polynomial.
683     */
684    public GenPolynomial<C> random(int n, Random rnd) {
685        if (nvar == 1) {
686            return random(3, n, n, 0.5f, rnd);
687        }
688        return random(3, n, n, 0.3f, rnd);
689    }
690
691
692    /**
693     * Generate a random polynomial.
694     * @param k bitsize of random coefficients.
695     * @param l number of terms.
696     * @param d maximal degree in each variable.
697     * @param q density of nozero exponents.
698     * @return a random polynomial.
699     */
700    public GenPolynomial<C> random(int k, int l, int d, float q) {
701        return random(k, l, d, q, random);
702    }
703
704
705    /**
706     * Generate a random polynomial.
707     * @param k bitsize of random coefficients.
708     * @param l number of terms.
709     * @param d maximal degree in each variable.
710     * @param q density of nozero exponents.
711     * @param rnd is a source for random bits.
712     * @return a random polynomial.
713     */
714    public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) {
715        GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 
716        ExpVector e;
717        C a;
718        // add l random coeffs and exponents
719        for (int i = 0; i < l; i++) {
720            e = ExpVector.random(nvar, d, q, rnd);
721            a = coFac.random(k, rnd);
722            r = r.sum(a, e); // somewhat inefficient but clean
723            //System.out.println("e = " + e + " a = " + a);
724        }
725        // System.out.println("r = " + r);
726        return r;
727    }
728
729
730    /**
731     * Copy polynomial c.
732     * @param c
733     * @return a copy of c.
734     */
735    public GenPolynomial<C> copy(GenPolynomial<C> c) {
736        //System.out.println("GP copy = " + this);
737        return new GenPolynomial<C>(this, c.val);
738    }
739
740
741    /**
742     * Copy polynomial list.
743     * @param L polynomial list
744     * @return a copy of L in this ring.
745     */
746    public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) {
747        if (L == null) {
748            return L;
749        }
750        List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size());
751        for (GenPolynomial<C> a : L) {
752            R.add(copy(a));
753        }
754        return R;
755    }
756
757
758    /**
759     * Parse a polynomial with the use of GenPolynomialTokenizer.
760     * @param s String.
761     * @return GenPolynomial from s.
762     */
763    public GenPolynomial<C> parse(String s) {
764        String val = s;
765        if (!s.contains("|")) {
766            val = val.replace("{", "").replace("}", "");
767        }
768        return parse(new StringReader(val));
769    }
770
771
772    /**
773     * Parse a polynomial with the use of GenPolynomialTokenizer.
774     * @param r Reader.
775     * @return next GenPolynomial from r.
776     */
777    @SuppressWarnings({ "unchecked", "cast" })
778    public GenPolynomial<C> parse(Reader r) {
779        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r);
780        GenPolynomial<C> p = null;
781        try {
782            p = (GenPolynomial<C>) pt.nextPolynomial();
783        } catch (IOException e) {
784            logger.error("{} parse {}", e, this);
785            p = ZERO;
786        }
787        return p;
788    }
789
790
791    /**
792     * Generate univariate polynomial in a given variable with given exponent.
793     * @param x the name of a variable.
794     * @return x as univariate polynomial.
795     */
796    public GenPolynomial<C> univariate(String x) {
797        return univariate(x, 1L);
798    }
799
800
801    /**
802     * Generate univariate polynomial in a given variable with given exponent.
803     * @param x the name of the variable.
804     * @param e the exponent of the variable.
805     * @return x^e as univariate polynomial.
806     */
807    public GenPolynomial<C> univariate(String x, long e) {
808        if (vars == null) { // should not happen
809            throw new IllegalArgumentException("no variables defined for polynomial ring");
810        }
811        if (x == null || x.isEmpty()) {
812            throw new IllegalArgumentException("no variable name given");
813        }
814        int i;
815        for (i = 0; i < vars.length; i++) {
816            if (x.equals(vars[i])) { // use HashMap or TreeMap
817                break;
818            }
819        }
820        if (i >= vars.length) {
821            throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring");
822        }
823        return univariate(0, nvar - i - 1, e);
824    }
825
826
827    /**
828     * Generate univariate polynomial in a given variable.
829     * @param i the index of the variable.
830     * @return X_i as univariate polynomial.
831     */
832    public GenPolynomial<C> univariate(int i) {
833        return univariate(0, i, 1L);
834    }
835
836
837    /**
838     * Generate univariate polynomial in a given variable with given exponent.
839     * @param i the index of the variable.
840     * @param e the exponent of the variable.
841     * @return X_i^e as univariate polynomial.
842     */
843    public GenPolynomial<C> univariate(int i, long e) {
844        return univariate(0, i, e);
845    }
846
847
848    /**
849     * Generate univariate polynomial in a given variable with given exponent.
850     * @param modv number of module variables.
851     * @param i the index of the variable.
852     * @param e the exponent of the variable.
853     * @return X_i^e as univariate polynomial.
854     */
855    public GenPolynomial<C> univariate(int modv, int i, long e) {
856        GenPolynomial<C> p = getZERO();
857        int r = nvar - modv;
858        if (0 <= i && i < r) {
859            C one = coFac.getONE();
860            ExpVector f = ExpVector.create(r, i, e);
861            if (modv > 0) {
862                f = f.extend(modv, 0, 0l);
863            }
864            p = p.sum(one, f);
865        }
866        return p;
867    }
868
869
870    /**
871     * Get the generating elements excluding the generators for the coefficient
872     * ring.
873     * @return a list of generating elements for this ring.
874     */
875    public List<GenPolynomial<C>> getGenerators() {
876        List<? extends GenPolynomial<C>> univs = univariateList();
877        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1);
878        gens.add(getONE());
879        gens.addAll(univs);
880        return gens;
881    }
882
883
884    /**
885     * Get a list of the generating elements.
886     * @return list of generators for the algebraic structure.
887     * @see edu.jas.structure.ElemFactory#generators()
888     */
889    public List<GenPolynomial<C>> generators() {
890        List<? extends C> cogens = coFac.generators();
891        List<? extends GenPolynomial<C>> univs = univariateList();
892        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
893        for (C c : cogens) {
894            gens.add(getONE().multiply(c));
895        }
896        gens.addAll(univs);
897        return gens;
898    }
899
900
901    /**
902     * Get a list of the generating elements excluding the module variables.
903     * @param modv number of module variables
904     * @return list of generators for the polynomial ring.
905     */
906    public List<GenPolynomial<C>> generators(int modv) {
907        List<? extends C> cogens = coFac.generators();
908        List<? extends GenPolynomial<C>> univs = univariateList(modv);
909        List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size());
910        for (C c : cogens) {
911            gens.add(getONE().multiply(c));
912        }
913        gens.addAll(univs);
914        return gens;
915    }
916
917
918    /**
919     * Is this structure finite or infinite.
920     * @return true if this structure is finite, else false.
921     * @see edu.jas.structure.ElemFactory#isFinite()
922     */
923    public boolean isFinite() {
924        return (nvar == 0) && coFac.isFinite();
925    }
926
927
928    /**
929     * Generate list of univariate polynomials in all variables.
930     * @return List(X_1,...,X_n) a list of univariate polynomials.
931     */
932    public List<? extends GenPolynomial<C>> univariateList() {
933        return univariateList(0, 1L);
934    }
935
936
937    /**
938     * Generate list of univariate polynomials in all variables.
939     * @param modv number of module variables.
940     * @return List(X_1,...,X_n) a list of univariate polynomials.
941     */
942    public List<? extends GenPolynomial<C>> univariateList(int modv) {
943        return univariateList(modv, 1L);
944    }
945
946
947    /**
948     * Generate list of univariate polynomials in all variables with given
949     * exponent.
950     * @param modv number of module variables.
951     * @param e the exponent of the variables.
952     * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
953     */
954    public List<? extends GenPolynomial<C>> univariateList(int modv, long e) {
955        List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar);
956        int nm = nvar - modv;
957        for (int i = 0; i < nm; i++) {
958            GenPolynomial<C> p = univariate(modv, nm - 1 - i, e);
959            pols.add(p);
960        }
961        return pols;
962    }
963
964
965    /**
966     * Extend variables. Used e.g. in module embedding. Extend number of
967     * variables by i.
968     * @param i number of variables to extend.
969     * @return extended polynomial ring factory.
970     */
971    public GenPolynomialRing<C> extend(int i) {
972        return extend(i, false);
973    }
974
975
976    /**
977     * Extend variables. Used e.g. in module embedding. Extend number of
978     * variables by i.
979     * @param i number of variables to extend.
980     * @param top true for TOP term order, false for POT term order.
981     * @return extended polynomial ring factory.
982     */
983    public GenPolynomialRing<C> extend(int i, boolean top) {
984        // add module variable names
985        String[] v = newVars("e", i);
986        return extend(v, top);
987    }
988
989
990    /**
991     * Extend variables. Used e.g. in module embedding. Extend number of
992     * variables by length(vn).
993     * @param vn names for extended variables.
994     * @return extended polynomial ring factory.
995     */
996    public GenPolynomialRing<C> extend(String[] vn) {
997        return extend(vn, false);
998    }
999
1000
1001    /**
1002     * Extend variables. Used e.g. in module embedding. Extend number of
1003     * variables by length(vn).
1004     * @param vn names for extended variables.
1005     * @param top true for TOP term order, false for POT term order.
1006     * @return extended polynomial ring factory.
1007     */
1008    public GenPolynomialRing<C> extend(String[] vn, boolean top) {
1009        if (vn == null || vars == null) {
1010            throw new IllegalArgumentException("vn and vars may not be null");
1011        }
1012        int i = vn.length;
1013        String[] v = new String[vars.length + i];
1014        for (int k = 0; k < vars.length; k++) {
1015            v[k] = vars[k];
1016        }
1017        for (int k = 0; k < vn.length; k++) {
1018            v[vars.length + k] = vn[k];
1019        }
1020        TermOrder to = tord.extend(nvar, i, top);
1021        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1022        return pfac;
1023    }
1024
1025
1026    /**
1027     * Extend lower variables. Extend number of variables by i.
1028     * @param i number of variables to extend.
1029     * @return extended polynomial ring factory.
1030     */
1031    public GenPolynomialRing<C> extendLower(int i) {
1032        String[] v = newVars("e", i);
1033        return extendLower(v);
1034    }
1035
1036
1037    /**
1038     * Extend lower variables. Extend number of variables by length(vn).
1039     * @param vn names for extended lower variables.
1040     * @return extended polynomial ring factory.
1041     */
1042    public GenPolynomialRing<C> extendLower(String[] vn) {
1043        return extendLower(vn, false);
1044    }
1045
1046
1047    /**
1048     * Extend lower variables. Extend number of variables by length(vn).
1049     * @param vn names for extended lower variables.
1050     * @param top true for TOP term order, false for POT term order.
1051     * @return extended polynomial ring factory.
1052     */
1053    public GenPolynomialRing<C> extendLower(String[] vn, boolean top) {
1054        if (vn == null || vars == null) {
1055            throw new IllegalArgumentException("vn and vars may not be null");
1056        }
1057        int i = vn.length;
1058        String[] v = new String[vars.length + i];
1059        for (int k = 0; k < vn.length; k++) {
1060            v[k] = vn[k];
1061        }
1062        for (int k = 0; k < vars.length; k++) {
1063            v[vn.length + k] = vars[k];
1064        }
1065        TermOrder to = tord.extendLower(nvar, i, top);
1066        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v);
1067        return pfac;
1068    }
1069
1070
1071    /**
1072     * Contract variables. Used e.g. in module embedding. Contract number of
1073     * variables by i.
1074     * @param i number of variables to remove.
1075     * @return contracted polynomial ring factory.
1076     */
1077    public GenPolynomialRing<C> contract(int i) {
1078        String[] v = null;
1079        if (vars != null) {
1080            v = new String[vars.length - i];
1081            for (int j = 0; j < vars.length - i; j++) {
1082                v[j] = vars[j];
1083            }
1084        }
1085        TermOrder to = tord.contract(i, nvar - i);
1086        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v);
1087        return pfac;
1088    }
1089
1090
1091    /**
1092     * Recursive representation as polynomial with i main variables.
1093     * @param i number of main variables.
1094     * @return recursive polynomial ring factory.
1095     */
1096    public GenPolynomialRing<GenPolynomial<C>> recursive(int i) {
1097        if (i <= 0 || i >= nvar) {
1098            throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar);
1099        }
1100        GenPolynomialRing<C> cfac = contract(i);
1101        String[] v = null;
1102        if (vars != null) {
1103            v = new String[i];
1104            int k = 0;
1105            for (int j = nvar - i; j < nvar; j++) {
1106                v[k++] = vars[j];
1107            }
1108        }
1109        TermOrder to = tord.contract(0, i); // ??
1110        GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v);
1111        return pfac;
1112    }
1113
1114
1115    /**
1116     * Distributive representation as polynomial with all main variables.
1117     * @return distributive polynomial ring factory.
1118     */
1119    @SuppressWarnings("unchecked")
1120    public GenPolynomialRing<C> distribute() {
1121        if (!(coFac instanceof GenPolynomialRing)) {
1122            return this;
1123        }
1124        RingFactory cf = coFac;
1125        RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf;
1126        GenPolynomialRing cr = (GenPolynomialRing) cfp;
1127        GenPolynomialRing<C> pfac;
1128        if (cr.vars != null) {
1129            pfac = extend(cr.vars);
1130        } else {
1131            pfac = extend(cr.nvar);
1132        }
1133        return pfac;
1134    }
1135
1136
1137    /**
1138     * Reverse variables. Used e.g. in opposite rings.
1139     * @return polynomial ring factory with reversed variables.
1140     */
1141    public GenPolynomialRing<C> reverse() {
1142        return reverse(false);
1143    }
1144
1145
1146    /**
1147     * Reverse variables. Used e.g. in opposite rings.
1148     * @param partial true for partialy reversed term orders.
1149     * @return polynomial ring factory with reversed variables.
1150     */
1151    public GenPolynomialRing<C> reverse(boolean partial) {
1152        String[] v = null;
1153        if (vars != null) { // vars are not inversed
1154            v = new String[vars.length];
1155            int k = tord.getSplit();
1156            if (partial && k < vars.length) {
1157                // copy upper
1158                for (int j = 0; j < k; j++) {
1159                    //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper
1160                    v[vars.length - k + j] = vars[vars.length - k + j];
1161                }
1162                // reverse lower
1163                for (int j = 0; j < vars.length - k; j++) {
1164                    //v[j] = vars[j]; // copy upper
1165                    v[j] = vars[vars.length - k - j - 1];
1166                }
1167            } else {
1168                for (int j = 0; j < vars.length; j++) {
1169                    v[j] = vars[vars.length - 1 - j];
1170                }
1171            }
1172            //System.out.println("vars = " + Arrays.toString(vars));
1173            //System.out.println("v    = " + Arrays.toString(v));
1174        }
1175        TermOrder to = tord.reverse(partial);
1176        GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v);
1177        pfac.partial = partial;
1178        return pfac;
1179    }
1180
1181
1182    /**
1183     * Get PolynomialComparator.
1184     * @return polynomial comparator.
1185     */
1186    public PolynomialComparator<C> getComparator() {
1187        return new PolynomialComparator<C>(tord, false);
1188    }
1189
1190
1191    /**
1192     * Get PolynomialComparator.
1193     * @param rev for reverse comparator.
1194     * @return polynomial comparator.
1195     */
1196    public PolynomialComparator<C> getComparator(boolean rev) {
1197        return new PolynomialComparator<C>(tord, rev);
1198    }
1199
1200
1201    /**
1202     * New variable names. Generate new names for variables,
1203     * @param prefix name prefix.
1204     * @param n number of variables.
1205     * @return new variable names.
1206     */
1207    public static String[] newVars(String prefix, int n) {
1208        String[] vars = new String[n];
1209        for (int i = 0; i < n; i++) {
1210            long m = varCounter.getAndIncrement();
1211            vars[i] = prefix + m;
1212        }
1213        return vars;
1214    }
1215
1216
1217    /**
1218     * New variable names. Generate new names for variables,
1219     * @param prefix name prefix.
1220     * @return new variable names.
1221     */
1222    public String[] newVars(String prefix) {
1223        return newVars(prefix, nvar);
1224    }
1225
1226
1227    /**
1228     * New variable names. Generate new names for variables,
1229     * @param n number of variables.
1230     * @return new variable names.
1231     */
1232    public static String[] newVars(int n) {
1233        return newVars("x", n);
1234    }
1235
1236
1237    /**
1238     * New variable names. Generate new names for variables,
1239     * @return new variable names.
1240     */
1241    public String[] newVars() {
1242        return newVars(nvar);
1243    }
1244
1245
1246    /*
1247     * Add variable names.
1248     * @param vars variable names to be recorded.
1249    public static void addVars(String[] vars) {
1250        if (vars == null) {
1251            return;
1252        }
1253        // synchronized (knownVars) {
1254        //   for (int i = 0; i < vars.length; i++) {
1255        //      knownVars.add(vars[i]); // eventualy names 'overwritten'
1256        //   }
1257        // }
1258    }
1259     */
1260
1261
1262    /**
1263     * Permute variable names.
1264     * @param vars variable names.
1265     * @param P permutation.
1266     * @return P(vars).
1267     */
1268    public static String[] permuteVars(List<Integer> P, String[] vars) {
1269        if (vars == null || vars.length <= 1) {
1270            return vars;
1271        }
1272        String[] b = new String[vars.length];
1273        int j = 0;
1274        for (Integer i : P) {
1275            b[j++] = vars[i];
1276        }
1277        return b;
1278    }
1279
1280
1281    /**
1282     * Permutation of polynomial ring variables.
1283     * @param P permutation.
1284     * @return P(this).
1285     */
1286    public GenPolynomialRing<C> permutation(List<Integer> P) {
1287        if (nvar <= 1) {
1288            return this;
1289        }
1290        TermOrder tp = tord.permutation(P);
1291        if (vars == null) {
1292            return new GenPolynomialRing<C>(coFac, nvar, tp);
1293        }
1294        String[] v1 = new String[vars.length];
1295        for (int i = 0; i < v1.length; i++) {
1296            v1[i] = vars[v1.length - 1 - i];
1297        }
1298        String[] vp = permuteVars(P, v1);
1299        String[] v2 = new String[vp.length];
1300        for (int i = 0; i < vp.length; i++) {
1301            v2[i] = vp[vp.length - 1 - i];
1302        }
1303        return new GenPolynomialRing<C>(coFac, nvar, tp, v2);
1304    }
1305
1306
1307    /**
1308     * Get a GenPolynomial iterator.
1309     * @return an iterator over all polynomials.
1310     */
1311    public Iterator<GenPolynomial<C>> iterator() {
1312        if (coFac.isFinite()) {
1313            return new GenPolynomialIterator<C>(this);
1314        }
1315        logger.warn("ring of coefficients {} is infinite, constructing iterator only over monomials", coFac);
1316        return new GenPolynomialMonomialIterator<C>(this);
1317        //throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1318    }
1319
1320}
1321
1322
1323/**
1324 * Polynomial iterator.
1325 * @author Heinz Kredel
1326 */
1327class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1328
1329
1330    /**
1331     * data structure.
1332     */
1333    final GenPolynomialRing<C> ring;
1334
1335
1336    final Iterator<List<Long>> eviter;
1337
1338
1339    final List<ExpVector> powers;
1340
1341
1342    final List<Iterable<C>> coeffiter;
1343
1344
1345    Iterator<List<C>> itercoeff;
1346
1347
1348    GenPolynomial<C> current;
1349
1350
1351    /**
1352     * Polynomial iterator constructor.
1353     */
1354    @SuppressWarnings("unchecked")
1355    public GenPolynomialIterator(GenPolynomialRing<C> fac) {
1356        ring = fac;
1357        LongIterable li = new LongIterable();
1358        li.setNonNegativeIterator();
1359        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1360        for (int i = 0; i < ring.nvar; i++) {
1361            tlist.add(li);
1362        }
1363        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1364        eviter = ei.iterator();
1365        RingFactory<C> cf = ring.coFac;
1366        coeffiter = new ArrayList<Iterable<C>>();
1367        if (cf instanceof Iterable && cf.isFinite()) {
1368            Iterable<C> cfi = (Iterable<C>) cf;
1369            coeffiter.add(cfi);
1370        } else {
1371            throw new IllegalArgumentException("only for finite iterable coefficients implemented");
1372        }
1373        CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1374        itercoeff = tuples.iterator();
1375        powers = new ArrayList<ExpVector>();
1376        ExpVector e = ExpVector.create(eviter.next());
1377        powers.add(e);
1378        //System.out.println("new e = " + e);
1379        //System.out.println("powers = " + powers);
1380        List<C> c = itercoeff.next();
1381        //System.out.println("coeffs = " + c);
1382        current = new GenPolynomial<C>(ring, c.get(0), e);
1383    }
1384
1385
1386    /**
1387     * Test for availability of a next element.
1388     * @return true if the iteration has more elements, else false.
1389     */
1390    public boolean hasNext() {
1391        return true;
1392    }
1393
1394
1395    /**
1396     * Get next polynomial.
1397     * @return next polynomial.
1398     */
1399    public synchronized GenPolynomial<C> next() {
1400        GenPolynomial<C> res = current;
1401        if (!itercoeff.hasNext()) {
1402            ExpVector e = ExpVector.create(eviter.next());
1403            powers.add(0, e); // add new ev at beginning
1404            //System.out.println("new e = " + e);
1405            //System.out.println("powers = " + powers);
1406            if (coeffiter.size() == 1) { // shorten frist iterator by one element
1407                coeffiter.add(coeffiter.get(0));
1408                Iterable<C> it = coeffiter.get(0);
1409                List<C> elms = new ArrayList<C>();
1410                for (C elm : it) {
1411                    elms.add(elm);
1412                }
1413                elms.remove(0);
1414                coeffiter.set(0, elms);
1415            } else {
1416                coeffiter.add(coeffiter.get(1));
1417            }
1418            CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter);
1419            itercoeff = tuples.iterator();
1420        }
1421        List<C> coeffs = itercoeff.next();
1422        //      while ( coeffs.get(0).isZERO() ) {
1423        //             System.out.println(" skip zero ");
1424        //          coeffs = itercoeff.next(); // skip tuples with zero in first component
1425        //      }
1426        //System.out.println("coeffs = " + coeffs);
1427        GenPolynomial<C> pol = ring.getZERO().copy();
1428        int i = 0;
1429        for (ExpVector f : powers) {
1430            C c = coeffs.get(i++);
1431            if (c.isZERO()) {
1432                continue;
1433            }
1434            if (pol.val.get(f) != null) {
1435                System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f));
1436                throw new RuntimeException("error in iterator");
1437            }
1438            pol.doPutToMap(f, c);
1439        }
1440        current = pol;
1441        return res;
1442    }
1443
1444
1445    /**
1446     * Remove an element if allowed.
1447     */
1448    public void remove() {
1449        throw new UnsupportedOperationException("cannnot remove elements");
1450    }
1451}
1452
1453
1454/**
1455 * Polynomial monomial iterator.
1456 * @author Heinz Kredel
1457 */
1458class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> {
1459
1460
1461    /**
1462     * data structure.
1463     */
1464    final GenPolynomialRing<C> ring;
1465
1466
1467    final Iterator<List> iter;
1468
1469
1470    GenPolynomial<C> current;
1471
1472
1473    /**
1474     * Polynomial iterator constructor.
1475     */
1476    @SuppressWarnings("unchecked")
1477    public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) {
1478        ring = fac;
1479        LongIterable li = new LongIterable();
1480        li.setNonNegativeIterator();
1481        List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar);
1482        for (int i = 0; i < ring.nvar; i++) {
1483            tlist.add(li);
1484        }
1485        CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist);
1486        //Iterator<List<Long>> eviter = ei.iterator();
1487
1488        RingFactory<C> cf = ring.coFac;
1489        Iterable<C> coeffiter;
1490        if (cf instanceof Iterable && !cf.isFinite()) {
1491            Iterable<C> cfi = (Iterable<C>) cf;
1492            coeffiter = cfi;
1493        } else {
1494            throw new IllegalArgumentException("only for infinite iterable coefficients implemented");
1495        }
1496
1497        // Cantor iterator for exponents and coeffcients
1498        List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter
1499        eci.add(ei);
1500        eci.add(coeffiter);
1501        CartesianProductInfinite ecp = new CartesianProductInfinite(eci);
1502        iter = ecp.iterator();
1503
1504        List ec = iter.next();
1505        List<Long> ecl = (List<Long>) ec.get(0);
1506        C c = (C) ec.get(1); // zero
1507        ExpVector e = ExpVector.create(ecl);
1508        //System.out.println("exp    = " + e);
1509        //System.out.println("coeffs = " + c);
1510        current = new GenPolynomial<C>(ring, c, e);
1511    }
1512
1513
1514    /**
1515     * Test for availability of a next element.
1516     * @return true if the iteration has more elements, else false.
1517     */
1518    public boolean hasNext() {
1519        return true;
1520    }
1521
1522
1523    /**
1524     * Get next polynomial.
1525     * @return next polynomial.
1526     */
1527    @SuppressWarnings("unchecked")
1528    public synchronized GenPolynomial<C> next() {
1529        GenPolynomial<C> res = current;
1530
1531        List ec = iter.next();
1532        C c = (C) ec.get(1);
1533        while (c.isZERO()) { // zero already done in first next
1534            ec = iter.next();
1535            c = (C) ec.get(1);
1536        }
1537        List<Long> ecl = (List<Long>) ec.get(0);
1538        ExpVector e = ExpVector.create(ecl);
1539        //System.out.println("exp    = " + e);
1540        //System.out.println("coeffs = " + c);
1541        current = new GenPolynomial<C>(ring, c, e);
1542
1543        return res;
1544    }
1545
1546
1547    /**
1548     * Remove an element if allowed.
1549     */
1550    public void remove() {
1551        throw new UnsupportedOperationException("cannnot remove elements");
1552    }
1553}