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