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.List;
014import java.util.Map;
015import java.util.Random;
016
017import org.apache.logging.log4j.LogManager;
018import org.apache.logging.log4j.Logger;
019
020import edu.jas.kern.PrettyPrint;
021import edu.jas.kern.Scripting;
022import edu.jas.structure.GcdRingElem;
023import edu.jas.structure.QuotPair;
024import edu.jas.structure.QuotPairFactory;
025import edu.jas.structure.RingElem;
026import edu.jas.structure.RingFactory;
027
028
029/**
030 * QLRSolvablePolynomialRing generic recursive solvable polynomial factory
031 * implementing RingFactory and extending GenSolvablePolynomialRing factory.
032 * Factory for n-variate ordered solvable polynomials over solvable quotient,
033 * local and local-residue coefficients. The non-commutative multiplication
034 * relations are maintained in a relation table and the non-commutative
035 * multiplication relations between the coefficients and the main variables are
036 * maintained in a coefficient relation table. Almost immutable object, except
037 * variable names and relation table contents.
038 * @param <C> polynomial coefficient type
039 * @param <D> quotient coefficient type
040 * @author Heinz Kredel
041 */
042
043public class QLRSolvablePolynomialRing<C extends GcdRingElem<C> & QuotPair<GenPolynomial<D>>, D extends GcdRingElem<D>>
044                extends GenSolvablePolynomialRing<C> {
045
046
047    private static final Logger logger = LogManager.getLogger(QLRSolvablePolynomialRing.class);
048
049    //private static final boolean debug = logger.isDebugEnabled();
050
051
052    /**
053     * Recursive solvable polynomial ring with polynomial coefficients.
054     */
055    public final RecSolvablePolynomialRing<D> polCoeff;
056
057
058    /**
059     * The constant polynomial 0 for this ring. Hides super ZERO.
060     */
061    public /*final*/ QLRSolvablePolynomial<C, D> ZERO;
062
063
064    /**
065     * The constant polynomial 1 for this ring. Hides super ONE.
066     */
067    public /*final*/ QLRSolvablePolynomial<C, D> ONE;
068
069
070    /**
071     * Factory to create coefficients.
072     */
073    public final QuotPairFactory<GenPolynomial<D>, C> qpfac;
074
075
076    /**
077     * The constructor creates a solvable polynomial factory object with the
078     * default term order and commutative relations.
079     * @param cf factory for coefficients of type C.
080     * @param n number of variables.
081     */
082    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n) {
083        this(cf, n, new TermOrder(), null, null);
084    }
085
086
087    /**
088     * The constructor creates a solvable polynomial factory object with the
089     * default term order.
090     * @param cf factory for coefficients of type C.
091     * @param n number of variables.
092     * @param rt solvable multiplication relations.
093     */
094    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n, RelationTable<C> rt) {
095        this(cf, n, new TermOrder(), null, rt);
096    }
097
098
099    /**
100     * The constructor creates a solvable polynomial factory object with the
101     * given term order and commutative relations.
102     * @param cf factory for coefficients of type C.
103     * @param n number of variables.
104     * @param t a term order.
105     */
106    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n, TermOrder t) {
107        this(cf, n, t, null, null);
108    }
109
110
111    /**
112     * The constructor creates a solvable polynomial factory object with the
113     * given term order.
114     * @param cf factory for coefficients of type C.
115     * @param n number of variables.
116     * @param t a term order.
117     * @param rt solvable multiplication relations.
118     */
119    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n, TermOrder t, RelationTable<C> rt) {
120        this(cf, n, t, null, rt);
121    }
122
123
124    /**
125     * The constructor creates a solvable polynomial factory object with the
126     * given term order and commutative relations.
127     * @param cf factory for coefficients of type C.
128     * @param n number of variables.
129     * @param t a term order.
130     * @param v names for the variables.
131     */
132    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) {
133        this(cf, n, t, v, null);
134    }
135
136
137    /**
138     * The constructor creates a solvable polynomial factory object with the
139     * given term order and commutative relations.
140     * @param cf factory for coefficients of type C.
141     * @param t a term order.
142     * @param v names for the variables.
143     */
144    public QLRSolvablePolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) {
145        this(cf, v.length, t, v, null);
146    }
147
148
149    /**
150     * The constructor creates a solvable polynomial factory object with the
151     * default term order.
152     * @param cf factory for coefficients of type C.
153     * @param v names for the variables.
154     */
155    public QLRSolvablePolynomialRing(RingFactory<C> cf, String[] v) {
156        this(cf, v.length, new TermOrder(), v, null);
157    }
158
159
160    /**
161     * The constructor creates a solvable polynomial factory object with the the
162     * same term order, number of variables and variable names as the given
163     * polynomial factory, only the coefficient factories differ and the
164     * solvable multiplication relations are <b>empty</b>.
165     * @param cf factory for coefficients of type C.
166     * @param o other solvable polynomial ring.
167     */
168    public QLRSolvablePolynomialRing(RingFactory<C> cf, GenSolvablePolynomialRing o) {
169        this(cf, o.nvar, o.tord, o.getVars(), null);
170    }
171
172
173    /**
174     * The constructor creates a solvable polynomial factory object with the the
175     * same term order, number of variables and variable names as the given
176     * polynomial factory, only the coefficient factories differ and the
177     * solvable multiplication relations are <b>empty</b>.
178     * @param cf factory for coefficients of type C.
179     * @param o other solvable polynomial ring.
180     */
181    public QLRSolvablePolynomialRing(RingFactory<C> cf, QLRSolvablePolynomialRing o) {
182        this(cf, (GenSolvablePolynomialRing) o);
183    }
184
185
186    /**
187     * The constructor creates a solvable polynomial factory object with the
188     * given term order.
189     * @param cf factory for coefficients of type C.
190     * @param n number of variables.
191     * @param t a term order.
192     * @param v names for the variables.
193     * @param rt solvable multiplication relations.
194     */
195    @SuppressWarnings("unchecked")
196    public QLRSolvablePolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v, RelationTable<C> rt) {
197        super(cf, n, t, v, rt);
198        //if (rt == null) { // handled in super }
199        qpfac = (QuotPairFactory<GenPolynomial<D>, C>) cf; // crucial part of type
200        RingFactory<GenPolynomial<D>> cfring = qpfac.pairFactory(); // == coFac.ring
201        polCoeff = new RecSolvablePolynomialRing<D>(cfring, n, t, v);
202        if (table.size() > 0) {
203            List<GenSolvablePolynomial<GenPolynomial<D>>> nt
204                = new ArrayList<GenSolvablePolynomial<GenPolynomial<D>>>(); 
205            for (GenSolvablePolynomial<C> q : table.relationList()) {
206                nt.add( this.toPolyCoefficients(q) ); // only with den == 1
207            }
208            polCoeff.table.addSolvRelations(nt);
209        }
210        ZERO = new QLRSolvablePolynomial<C, D>(this);
211        C coeff = coFac.getONE();
212        ONE = new QLRSolvablePolynomial<C, D>(this, coeff, evzero);
213    }
214
215
216    /**
217     * Get the String representation.
218     * @see java.lang.Object#toString()
219     */
220    @Override
221    public String toString() {
222        String res = super.toString();
223        if (PrettyPrint.isTrue()) {
224            res += "\n" + polCoeff.coeffTable.toString(vars);
225            res += "\n" + polCoeff.table.toString(vars);
226        } else {
227            res += ", #rel = " + table.size() + " + " + polCoeff.coeffTable.size() + " + "
228                            + polCoeff.table.size();
229        }
230        return res;
231    }
232
233
234    /**
235     * Get a scripting compatible string representation.
236     * @return script compatible representation for this Element.
237     * @see edu.jas.structure.Element#toScript()
238     */
239    @Override
240    public String toScript() {
241        StringBuffer s = new StringBuffer();
242        switch (Scripting.getLang()) {
243        case Ruby:
244            s.append("SolvPolyRing.new(");
245            break;
246        case Python:
247        default:
248            s.append("SolvPolyRing(");
249        }
250        if (coFac instanceof RingElem) {
251            s.append(((RingElem<C>) coFac).toScriptFactory());
252        } else {
253            s.append(coFac.toScript().trim());
254        }
255        s.append(",\"" + varsToString() + "\",");
256        String to = tord.toScript();
257        s.append(to);
258        String rel = "";
259        if (table.size() > 0) {
260            rel = table.toScript();
261            s.append(",rel=");
262            s.append(rel);
263        }
264        // if (polCoeff.coeffTable.size() > 0) {
265        //     String crel = polCoeff.coeffTable.toScript();
266        //     s.append(",coeffrel=");
267        //     s.append(crel);
268        // }
269        // if (polCoeff.table.size() > 0) { // should not be printed
270        //     String polrel = polCoeff.table.toScript();
271        //     if (!rel.equals(polrel)) {
272        //         s.append(",polrel=");
273        //         s.append(polrel);
274        //     }
275        // }
276        s.append(")");
277        String cpol = polCoeff.toScript();
278        s.append("\n  # ");
279        s.append(cpol);
280        return s.toString();
281    }
282
283
284    /**
285     * Comparison with any other object.
286     * @see java.lang.Object#equals(java.lang.Object)
287     */
288    @Override
289    @SuppressWarnings("unchecked")
290    public boolean equals(Object other) {
291        if (!(other instanceof QLRSolvablePolynomialRing)) {
292            return false;
293        }
294        QLRSolvablePolynomialRing<C, D> oring = null;
295        try {
296            oring = (QLRSolvablePolynomialRing<C, D>) other;
297        } catch (ClassCastException ignored) {
298        }
299        if (oring == null) {
300            return false;
301        }
302        // do a super.equals( )
303        if (!super.equals(other)) {
304            return false;
305        }
306        // check same base relations
307        //if ( ! table.equals(oring.table) ) { // done in super
308        //    return false;
309        //}
310        if (!polCoeff.coeffTable.equals(oring.polCoeff.coeffTable)) {
311            return false;
312        }
313        return true;
314    }
315
316
317    /**
318     * Hash code for this polynomial ring.
319     * @see java.lang.Object#hashCode()
320     */
321    @Override
322    public int hashCode() {
323        int h;
324        h = super.hashCode();
325        h = 37 * h + table.hashCode(); // may be different after some computations
326        h = 37 * h + polCoeff.coeffTable.hashCode(); // may be different
327        return h;
328    }
329
330
331    /**
332     * Get the zero element.
333     * @return 0 as QLRSolvablePolynomial.
334     */
335    @Override
336    public QLRSolvablePolynomial<C, D> getZERO() {
337        if (ZERO == null || !ZERO.isZERO()) { // happened since May 5 2022
338            // Name        : java-11-openjdk-headless, java-17-openjdk-headless
339            // Version     : 11.0.15.0, 17.0.4
340            // Release     : 150000.3.80.1, 150400.3.3.1
341            QLRSolvablePolynomial<C, D> x = ZERO;
342            ZERO = new QLRSolvablePolynomial<C, D>(this);
343            logger.info("warn: ZERO@get |{}| wrong fix to {}", x, ZERO);
344        }
345        return ZERO;
346    }
347
348
349    /**
350     * Get the one element.
351     * @return 1 as QLRSolvablePolynomial.
352     */
353    @Override
354    public QLRSolvablePolynomial<C, D> getONE() {
355        if (ONE == null || !ONE.isONE()) {
356           ONE = new QLRSolvablePolynomial<C, D>(this, coFac.getONE(), evzero);
357           logger.info("warn: ONE@get {}", ONE);
358        }
359        return ONE;
360    }
361
362
363    /**
364     * Query if this ring is commutative.
365     * @return true if this ring is commutative, else false.
366     */
367    @Override
368    public boolean isCommutative() {
369        if (polCoeff.isCommutative()) {
370            return super.isCommutative();
371        }
372        return false;
373    }
374
375
376    /**
377     * Query if this ring is associative. Test if the relations between the mian
378     * variables and the coefficient generators define an associative solvable
379     * ring.
380     * @return true, if this ring is associative, else false.
381     */
382    @Override
383    @SuppressWarnings("unchecked")
384    public boolean isAssociative() {
385        if (!coFac.isAssociative()) {
386            return false;
387        }
388        //System.out.println("polCoeff = " + polCoeff.toScript());
389        if (!polCoeff.isAssociative()) { // not done via generators??
390            return false;
391        }
392        QLRSolvablePolynomial<C, D> Xi, Xj, Xk, p, q;
393        List<GenPolynomial<C>> gens = generators();
394        //System.out.println("QLR gens = " + gens);
395        int ngen = gens.size();
396        for (int i = 0; i < ngen; i++) {
397            Xi = (QLRSolvablePolynomial<C, D>) gens.get(i);
398            if (Xi.degree() == 0) {
399                C lbc = Xi.leadingBaseCoefficient();
400                if (lbc.numerator().degree() == 0 && lbc.denominator().degree() == 0) {
401                    //System.out.println("qlr assoc skip: Xi = " + lbc);
402                    continue; // skip
403                }
404            }
405            for (int j = i + 1; j < ngen; j++) {
406                Xj = (QLRSolvablePolynomial<C, D>) gens.get(j);
407                if (Xj.degree() == 0) {
408                    C lbc = Xi.leadingBaseCoefficient();
409                    if (lbc.numerator().degree() == 0 && lbc.denominator().degree() == 0) {
410                        //System.out.println("qlr assoc skip: Xj = " + lbc);
411                        continue; // skip
412                    }
413                }
414                for (int k = j + 1; k < ngen; k++) {
415                    Xk = (QLRSolvablePolynomial<C, D>) gens.get(k);
416                    if (Xi.degree() == 0 && Xj.degree() == 0 && Xk.degree() == 0) {
417                        //System.out.println("qlr assoc degree == 0");
418                        continue; // skip
419                    }
420                    try {
421                        p = Xk.multiply(Xj).multiply(Xi);
422                        q = Xk.multiply(Xj.multiply(Xi));
423                        //System.out.println("qlr assoc: p = " + p);
424                        //System.out.println("qlr assoc: q = " + q);
425                    } catch (IllegalArgumentException e) {
426                        System.out.println("qlr assoc: Xi = " + Xi);
427                        System.out.println("qlr assoc: Xj = " + Xj);
428                        System.out.println("qlr assoc: Xk = " + Xk);
429                        e.printStackTrace();
430                        continue;
431                    }
432                    if (!p.equals(q)) {
433                        if (logger.isInfoEnabled()) {
434                            //System.out.println("qlr assoc: Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi);
435                            logger.info("Xi = {}, Xj = {}, Xk = {}", Xi, Xj, Xk);
436                            logger.info("p = ( Xk * Xj ) * Xi = {}", p);
437                            logger.info("q = Xk * ( Xj * Xi ) = {}", q);
438                            logger.info("q-p = {}", p.subtract(q));
439                        }
440                        return false;
441                    }
442                }
443            }
444        }
445        return true;
446    }
447
448
449    /**
450     * Get a (constant) QLRSolvablePolynomial&lt;C&gt; element from a long
451     * value.
452     * @param a long.
453     * @return a QLRSolvablePolynomial&lt;C&gt;.
454     */
455    @Override
456    public QLRSolvablePolynomial<C, D> fromInteger(long a) {
457        return new QLRSolvablePolynomial<C, D>(this, coFac.fromInteger(a), evzero);
458    }
459
460
461    /**
462     * Get a (constant) QLRSolvablePolynomial&lt;C&gt; element from a BigInteger
463     * value.
464     * @param a BigInteger.
465     * @return a QLRSolvablePolynomial&lt;C&gt;.
466     */
467    @Override
468    public QLRSolvablePolynomial<C, D> fromInteger(BigInteger a) {
469        return new QLRSolvablePolynomial<C, D>(this, coFac.fromInteger(a), evzero);
470    }
471
472
473    /**
474     * Random solvable polynomial. Generates a random solvable polynomial with k
475     * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
476     * @param n number of terms.
477     * @return a random solvable polynomial.
478     */
479    @Override
480    public QLRSolvablePolynomial<C, D> random(int n) {
481        return random(n, random);
482    }
483
484
485    /**
486     * Random solvable polynomial. Generates a random solvable polynomial with k
487     * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3.
488     * @param n number of terms.
489     * @param rnd is a source for random bits.
490     * @return a random solvable polynomial.
491     */
492    @Override
493    public QLRSolvablePolynomial<C, D> random(int n, Random rnd) {
494        if (nvar == 1) {
495            return random(5, n, n, 0.7f, rnd);
496        }
497        return random(5, n, 3, 0.3f, rnd);
498    }
499
500
501    /**
502     * Generate a random solvable polynomial.
503     * @param k bitsize of random coefficients.
504     * @param l number of terms.
505     * @param d maximal degree in each variable.
506     * @param q density of nozero exponents.
507     * @return a random solvable polynomial.
508     */
509    @Override
510    public QLRSolvablePolynomial<C, D> random(int k, int l, int d, float q) {
511        return random(k, l, d, q, random);
512    }
513
514
515    /**
516     * Random solvable polynomial.
517     * @param k size of random coefficients.
518     * @param l number of terms.
519     * @param d maximal degree in each variable.
520     * @param q density of nozero exponents.
521     * @param rnd is a source for random bits.
522     * @return a random solvable polynomial.
523     */
524    @Override
525    @SuppressWarnings("unchecked")
526    public QLRSolvablePolynomial<C, D> random(int k, int l, int d, float q, Random rnd) {
527        QLRSolvablePolynomial<C, D> r = getZERO(); // copy( ZERO ); 
528        ExpVector e;
529        C a;
530        // add random coeffs and exponents
531        for (int i = 0; i < l; i++) {
532            e = ExpVector.random(nvar, d, q, rnd);
533            a = coFac.random(k, rnd);
534            r = (QLRSolvablePolynomial<C, D>) r.sum(a, e);
535            // somewhat inefficient but clean
536        }
537        return r;
538    }
539
540
541    /**
542     * Copy polynomial c.
543     * @param c
544     * @return a copy of c.
545     */
546    public QLRSolvablePolynomial<C, D> copy(QLRSolvablePolynomial<C, D> c) {
547        return new QLRSolvablePolynomial<C, D>(this, c.getMap());
548    }
549
550
551    /**
552     * Parse a solvable polynomial with the use of GenPolynomialTokenizer
553     * @param s String.
554     * @return QLRSolvablePolynomial from s.
555     */
556    @Override
557    public QLRSolvablePolynomial<C, D> parse(String s) {
558        return parse(new StringReader(s));
559    }
560
561
562    /**
563     * Parse a solvable polynomial with the use of GenPolynomialTokenizer
564     * @param r Reader.
565     * @return next QLRSolvablePolynomial from r.
566     */
567    @Override
568    @SuppressWarnings("unchecked")
569    public QLRSolvablePolynomial<C, D> parse(Reader r) {
570        GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r);
571        QLRSolvablePolynomial<C, D> p = null;
572        try {
573            GenSolvablePolynomial<C> s = pt.nextSolvablePolynomial();
574            p = new QLRSolvablePolynomial<C, D>(this, s);
575        } catch (IOException e) {
576            logger.error("{} parse {}", e, this);
577            p = ZERO;
578        }
579        return p;
580    }
581
582
583    /**
584     * Generate univariate solvable polynomial in a given variable.
585     * @param i the index of the variable.
586     * @return X_i as solvable univariate polynomial.
587     */
588    @Override
589    @SuppressWarnings("unchecked")
590    public QLRSolvablePolynomial<C, D> univariate(int i) {
591        return (QLRSolvablePolynomial<C, D>) super.univariate(i);
592    }
593
594
595    /**
596     * Generate univariate solvable polynomial in a given variable with given
597     * exponent.
598     * @param i the index of the variable.
599     * @param e the exponent of the variable.
600     * @return X_i^e as solvable univariate polynomial.
601     */
602    @Override
603    @SuppressWarnings("unchecked")
604    public QLRSolvablePolynomial<C, D> univariate(int i, long e) {
605        return (QLRSolvablePolynomial<C, D>) super.univariate(i, e);
606    }
607
608
609    /**
610     * Generate univariate solvable polynomial in a given variable with given
611     * exponent.
612     * @param modv number of module variables.
613     * @param i the index of the variable.
614     * @param e the exponent of the variable.
615     * @return X_i^e as solvable univariate polynomial.
616     */
617    @Override
618    @SuppressWarnings("unchecked")
619    public QLRSolvablePolynomial<C, D> univariate(int modv, int i, long e) {
620        return (QLRSolvablePolynomial<C, D>) super.univariate(modv, i, e);
621    }
622
623
624    /**
625     * Generate list of univariate polynomials in all variables.
626     * @return List(X_1,...,X_n) a list of univariate polynomials.
627     */
628    @Override
629    public List<QLRSolvablePolynomial<C, D>> univariateList() {
630        return univariateList(0, 1L);
631    }
632
633
634    /**
635     * Generate list of univariate polynomials in all variables.
636     * @param modv number of module variables.
637     * @return List(X_1,...,X_n) a list of univariate polynomials.
638     */
639    @Override
640    public List<QLRSolvablePolynomial<C, D>> univariateList(int modv) {
641        return univariateList(modv, 1L);
642    }
643
644
645    /**
646     * Generate list of univariate polynomials in all variables with given
647     * exponent.
648     * @param modv number of module variables.
649     * @param e the exponent of the variables.
650     * @return List(X_1^e,...,X_n^e) a list of univariate polynomials.
651     */
652    @Override
653    public List<QLRSolvablePolynomial<C, D>> univariateList(int modv, long e) {
654        List<QLRSolvablePolynomial<C, D>> pols = new ArrayList<QLRSolvablePolynomial<C, D>>(nvar);
655        int nm = nvar - modv;
656        for (int i = 0; i < nm; i++) {
657            QLRSolvablePolynomial<C, D> p = univariate(modv, nm - 1 - i, e);
658            pols.add(p);
659        }
660        return pols;
661    }
662
663
664    /**
665     * Extend variables. Used e.g. in module embedding. Extend number of
666     * variables by i.
667     * @param i number of variables to extend.
668     * @return extended solvable polynomial ring factory.
669     */
670    @Override
671    public QLRSolvablePolynomialRing<C, D> extend(int i) {
672        return extend(i, false);
673    }
674
675
676    /**
677     * Extend variables. Used e.g. in module embedding. Extend number of
678     * variables by i.
679     * @param i number of variables to extend.
680     * @param top true for TOP term order, false for POT term order.
681     * @return extended solvable polynomial ring factory.
682     */
683    @Override
684    public QLRSolvablePolynomialRing<C, D> extend(int i, boolean top) {
685        GenPolynomialRing<C> pfac = super.extend(i, top);
686        QLRSolvablePolynomialRing<C, D> spfac = new QLRSolvablePolynomialRing<C, D>(pfac.coFac, pfac.nvar,
687                        pfac.tord, pfac.getVars());
688        spfac.table.extend(this.table);
689        spfac.polCoeff.coeffTable.extend(this.polCoeff.coeffTable);
690        return spfac;
691    }
692
693
694    /**
695     * Extend variables. Used e.g. in module embedding. Extend number of
696     * variables by length(vn). New variables commute with the exiting
697     * variables.
698     * @param vn names for extended variables.
699     * @return extended polynomial ring factory.
700     */
701    @Override
702    public QLRSolvablePolynomialRing<C, D> extend(String[] vn) {
703        return extend(vn, false);
704    }
705
706
707    /**
708     * Extend variables. Used e.g. in module embedding. Extend number of
709     * variables by length(vn). New variables commute with the exiting
710     * variables.
711     * @param vn names for extended variables.
712     * @param top true for TOP term order, false for POT term order.
713     * @return extended polynomial ring factory.
714     */
715    @Override
716    public QLRSolvablePolynomialRing<C, D> extend(String[] vn, boolean top) {
717        GenPolynomialRing<C> pfac = super.extend(vn, top);
718        QLRSolvablePolynomialRing<C, D> spfac = new QLRSolvablePolynomialRing<C, D>(pfac.coFac, pfac.nvar,
719                        pfac.tord, pfac.vars);
720        spfac.table.extend(this.table);
721        spfac.polCoeff.coeffTable.extend(this.polCoeff.coeffTable);
722        return spfac;
723    }
724
725
726    /**
727     * Contract variables. Used e.g. in module embedding. Contract number of
728     * variables by i.
729     * @param i number of variables to remove.
730     * @return contracted solvable polynomial ring factory.
731     */
732    @Override
733    public QLRSolvablePolynomialRing<C, D> contract(int i) {
734        GenPolynomialRing<C> pfac = super.contract(i);
735        QLRSolvablePolynomialRing<C, D> spfac = new QLRSolvablePolynomialRing<C, D>(pfac.coFac, pfac.nvar,
736                        pfac.tord, pfac.getVars());
737        spfac.table.contract(this.table);
738        spfac.polCoeff.coeffTable.contract(this.polCoeff.coeffTable);
739        return spfac;
740    }
741
742
743    /**
744     * Reverse variables. Used e.g. in opposite rings.
745     * @return solvable polynomial ring factory with reversed variables.
746     */
747    @Override
748    public QLRSolvablePolynomialRing<C, D> reverse() {
749        return reverse(false);
750    }
751
752
753    /**
754     * Reverse variables. Used e.g. in opposite rings.
755     * @param partial true for partially reversed term orders.
756     * @return solvable polynomial ring factory with reversed variables.
757     */
758    @Override
759    public QLRSolvablePolynomialRing<C, D> reverse(boolean partial) {
760        GenPolynomialRing<C> pfac = super.reverse(partial);
761        QLRSolvablePolynomialRing<C, D> spfac = new QLRSolvablePolynomialRing<C, D>(pfac.coFac, pfac.nvar,
762                        pfac.tord, pfac.getVars());
763        spfac.partial = partial;
764        spfac.table.reverse(this.table);
765        spfac.polCoeff.coeffTable.reverse(this.polCoeff.coeffTable);
766        return spfac;
767    }
768
769
770    /**
771     * Rational function from integral polynomial coefficients. Represent as
772     * polynomial with type C coefficients.
773     * @param A polynomial with integral polynomial coefficients to be
774     *            converted.
775     * @return polynomial with type C coefficients.
776     */
777    public QLRSolvablePolynomial<C, D> fromPolyCoefficients(GenSolvablePolynomial<GenPolynomial<D>> A) {
778        QLRSolvablePolynomial<C, D> B = getZERO().copy();
779        if (A == null || A.isZERO()) {
780            return B;
781        }
782        for (Map.Entry<ExpVector, GenPolynomial<D>> y : A.getMap().entrySet()) {
783            ExpVector e = y.getKey();
784            GenSolvablePolynomial<D> a = (GenSolvablePolynomial<D>) y.getValue();
785            //C p = new C(qfac, a); 
786            C p = qpfac.create(a);
787            if (!p.isZERO()) {
788                B.doPutToMap(e, p);
789            }
790        }
791        return B;
792    }
793
794
795    /**
796     * Integral function from rational polynomial coefficients. Represent as
797     * polynomial with type GenSolvablePolynomial<C> coefficients.
798     * @param A polynomial with rational polynomial coefficients to be
799     *            converted.
800     * @return polynomial with type GenSolvablePolynomial<C> coefficients.
801     */
802    public RecSolvablePolynomial<D> toPolyCoefficients(QLRSolvablePolynomial<C, D> A) {
803        RecSolvablePolynomial<D> B = polCoeff.getZERO().copy();
804        if (A == null || A.isZERO()) {
805            return B;
806        }
807        for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) {
808            ExpVector e = y.getKey();
809            C a = y.getValue();
810            if (!a.denominator().isONE()) {
811                throw new IllegalArgumentException("den != 1 not supported: " + a);
812            }
813            GenPolynomial<D> p = a.numerator(); // can not be zero
814            if (!p.isZERO()) {
815                B.doPutToMap(e, p);
816            }
817        }
818        return B;
819    }
820
821
822    /**
823     * Integral function from rational polynomial coefficients. Represent as
824     * polynomial with type GenSolvablePolynomial coefficients.
825     * @param A polynomial with rational polynomial coefficients to be
826     *            converted.
827     * @return polynomial with type GenSolvablePolynomial coefficients.
828     */
829    public RecSolvablePolynomial<D> toPolyCoefficients(GenPolynomial<C> A) {
830        RecSolvablePolynomial<D> B = polCoeff.getZERO().copy();
831        if (A == null || A.isZERO()) {
832            return B;
833        }
834        for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) {
835            ExpVector e = y.getKey();
836            C a = y.getValue();
837            if (!a.denominator().isONE()) {
838                throw new IllegalArgumentException("den != 1 not supported: " + a);
839            }
840            GenPolynomial<D> p = a.numerator(); // can not be zero
841            if (!p.isZERO()) {
842                B.doPutToMap(e, p);
843            }
844        }
845        return B;
846    }
847
848}