001/*
002 * $Id$
003 */
004
005package edu.jas.poly;
006
007
008import java.util.Map;
009import java.util.Set;
010import java.util.SortedMap;
011
012import org.apache.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.structure.RingElem;
016
017
018/**
019 * RecSolvablePolynomial generic recursive solvable polynomials implementing
020 * RingElem. n-variate ordered solvable polynomials over solvable polynomial
021 * coefficients. Objects of this class are intended to be immutable. The
022 * implementation is based on TreeMap respectively SortedMap from exponents to
023 * coefficients by extension of GenPolynomial.
024 * @param <C> coefficient type
025 * @author Heinz Kredel
026 */
027
028public class RecSolvablePolynomial<C extends RingElem<C>> extends GenSolvablePolynomial<GenPolynomial<C>> {
029
030
031    /**
032     * The factory for the recursive solvable polynomial ring. Hides super.ring.
033     */
034    public final RecSolvablePolynomialRing<C> ring;
035
036
037    private static final Logger logger = LogManager.getLogger(RecSolvablePolynomial.class);
038
039
040    private static final boolean debug = logger.isDebugEnabled();
041
042
043    /**
044     * Constructor for zero RecSolvablePolynomial.
045     * @param r solvable polynomial ring factory.
046     */
047    public RecSolvablePolynomial(RecSolvablePolynomialRing<C> r) {
048        super(r);
049        ring = r;
050    }
051
052
053    /**
054     * Constructor for RecSolvablePolynomial.
055     * @param r solvable polynomial ring factory.
056     * @param e exponent.
057     */
058    public RecSolvablePolynomial(RecSolvablePolynomialRing<C> r, ExpVector e) {
059        this(r);
060        val.put(e, ring.getONECoefficient());
061    }
062
063
064    /**
065     * Constructor for RecSolvablePolynomial.
066     * @param r solvable polynomial ring factory.
067     * @param c coefficient polynomial.
068     * @param e exponent.
069     */
070    public RecSolvablePolynomial(RecSolvablePolynomialRing<C> r, GenPolynomial<C> c, ExpVector e) {
071        this(r);
072        if (c != null && !c.isZERO()) {
073            val.put(e, c);
074        }
075    }
076
077
078    /**
079     * Constructor for RecSolvablePolynomial.
080     * @param r solvable polynomial ring factory.
081     * @param c coefficient polynomial.
082     */
083    public RecSolvablePolynomial(RecSolvablePolynomialRing<C> r, GenPolynomial<C> c) {
084        this(r, c, r.evzero);
085    }
086
087
088    /**
089     * Constructor for RecSolvablePolynomial.
090     * @param r solvable polynomial ring factory.
091     * @param S solvable polynomial.
092     */
093    public RecSolvablePolynomial(RecSolvablePolynomialRing<C> r, GenSolvablePolynomial<GenPolynomial<C>> S) {
094        this(r, S.val);
095    }
096
097
098    /**
099     * Constructor for RecSolvablePolynomial.
100     * @param r solvable polynomial ring factory.
101     * @param v the SortedMap of some other (solvable) polynomial.
102     */
103    protected RecSolvablePolynomial(RecSolvablePolynomialRing<C> r, SortedMap<ExpVector, GenPolynomial<C>> v) {
104        this(r);
105        val.putAll(v); // assume no zero coefficients
106    }
107
108
109    /**
110     * Get the corresponding element factory.
111     * @return factory for this Element.
112     * @see edu.jas.structure.Element#factory()
113     */
114    @Override
115    public RecSolvablePolynomialRing<C> factory() {
116        return ring;
117    }
118
119
120    /**
121     * Clone this RecSolvablePolynomial.
122     * @see java.lang.Object#clone()
123     */
124    @Override
125    public RecSolvablePolynomial<C> copy() {
126        return new RecSolvablePolynomial<C>(ring, this.val);
127    }
128
129
130    /**
131     * Comparison with any other object.
132     * @see java.lang.Object#equals(java.lang.Object)
133     */
134    @Override
135    public boolean equals(Object B) {
136        if (!(B instanceof RecSolvablePolynomial)) {
137            return false;
138        }
139        // compare also coeffTable?
140        return super.equals(B);
141    }
142
143
144    /**
145     * Hash code for this polynomial.
146     * @see java.lang.Object#hashCode()
147     */
148    @Override
149    public int hashCode() {
150        return super.hashCode();
151    }
152
153
154    /**
155     * RecSolvablePolynomial multiplication.
156     * @param Bp RecSolvablePolynomial.
157     * @return this*Bp, where * denotes solvable multiplication.
158     */
159    // cannot @Override, @NoOverride
160    public RecSolvablePolynomial<C> multiply(RecSolvablePolynomial<C> Bp) {
161        if (Bp == null || Bp.isZERO()) {
162            return ring.getZERO();
163        }
164        if (this.isZERO()) {
165            return this;
166        }
167        assert (ring.nvar == Bp.ring.nvar);
168        if (debug) {
169            logger.info("ring = " + ring.toScript());
170        }
171        final boolean commute = ring.table.isEmpty();
172        final boolean commuteCoeff = ring.coeffTable.isEmpty();
173        GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) ring.coFac;
174        RecSolvablePolynomial<C> Dp = ring.getZERO().copy();
175        ExpVector Z = ring.evzero;
176        ExpVector Zc = cfac.evzero;
177        GenPolynomial<C> one = ring.getONECoefficient();
178
179        RecSolvablePolynomial<C> C1 = null;
180        RecSolvablePolynomial<C> C2 = null;
181        Map<ExpVector, GenPolynomial<C>> A = val;
182        Map<ExpVector, GenPolynomial<C>> B = Bp.val;
183        Set<Map.Entry<ExpVector, GenPolynomial<C>>> Bk = B.entrySet();
184        if (debug)
185            logger.info("input A = " + this);
186        for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.entrySet()) {
187            GenPolynomial<C> a = y.getValue();
188            ExpVector e = y.getKey();
189            if (debug)
190                logger.info("e = " + e + ", a = " + a);
191            int[] ep = e.dependencyOnVariables();
192            int el1 = ring.nvar + 1;
193            if (ep.length > 0) {
194                el1 = ep[0];
195            }
196            //int el1s = ring.nvar + 1 - el1;
197            if (debug)
198                logger.info("input B = " + Bp);
199            for (Map.Entry<ExpVector, GenPolynomial<C>> x : Bk) {
200                GenPolynomial<C> b = x.getValue();
201                ExpVector f = x.getKey();
202                if (debug)
203                    logger.info("f = " + f + ", b = " + b);
204                int[] fp = f.dependencyOnVariables();
205                int fl1 = 0;
206                if (fp.length > 0) {
207                    fl1 = fp[fp.length - 1];
208                }
209                int fl1s = ring.nvar + 1 - fl1;
210                // polynomial coefficient multiplication e*b = P_eb, for a*((e*b)*f)
211                RecSolvablePolynomial<C> Cps = ring.getZERO().copy();
212                RecSolvablePolynomial<C> Cs = null;
213                if (commuteCoeff || b.isConstant() || e.isZERO()) { // symmetric
214                    Cps.doAddTo(b, e);
215                    if (debug)
216                        logger.info("symmetric coeff, e*b: b = " + b + ", e = " + e);
217                } else { // unsymmetric
218                    if (debug)
219                        logger.info("unsymmetric coeff, e*b: b = " + b + ", e = " + e);
220                    for (Map.Entry<ExpVector, C> z : b.val.entrySet()) {
221                        C c = z.getValue();
222                        GenPolynomial<C> cc = b.ring.valueOf(c); 
223                        ExpVector g = z.getKey();
224                        if (debug)
225                            logger.info("g = " + g + ", c = " + c);
226                        int[] gp = g.dependencyOnVariables();
227                        int gl1 = 0;
228                        if (gp.length > 0) {
229                            gl1 = gp[gp.length - 1];
230                        }
231                        int gl1s = b.ring.nvar + 1 - gl1;
232                        if (debug) {
233                            logger.info("gl1s = " + gl1s);
234                        }
235                        // split e = e1 * e2, g = g2 * g1 (= g1 * g2)
236                        ExpVector e1 = e;
237                        ExpVector e2 = Z;
238                        if (!e.isZERO()) {
239                            e1 = e.subst(el1, 0);
240                            e2 = Z.subst(el1, e.getVal(el1));
241                        }
242                        ExpVector e4;
243                        ExpVector g1 = g;
244                        ExpVector g2 = Zc;
245                        if (!g.isZERO()) {
246                            g1 = g.subst(gl1, 0);
247                            g2 = Zc.subst(gl1, g.getVal(gl1));
248                        }
249                        if (debug) {
250                            logger.info("coeff, e1 = " + e1 + ", e2 = " + e2 + ", Cps = " + Cps);
251                            logger.info("coeff, g1 = " + g1 + ", g2 = " + g2);
252                        }
253                        TableRelation<GenPolynomial<C>> crel = ring.coeffTable.lookup(e2, g2);
254                        if (debug)
255                            logger.info("coeff, crel = " + crel.p);
256                        //logger.info("coeff, e  = " + e + " g, = " + g + ", crel = " + crel);
257                        Cs = new RecSolvablePolynomial<C>(ring, crel.p);
258                        // rest of multiplication and update relations
259                        if (crel.f != null) { // process remaining right power
260                            GenPolynomial<C> c2 = b.ring.valueOf(crel.f); 
261                            C2 = new RecSolvablePolynomial<C>(ring, c2, Z);
262                            Cs = Cs.multiply(C2);
263                            if (crel.e == null) {
264                                e4 = e2;
265                            } else {
266                                e4 = e2.subtract(crel.e);
267                            }
268                            ring.coeffTable.update(e4, g2, Cs);
269                        }
270                        if (crel.e != null) { // process remaining left power
271                            C1 = new RecSolvablePolynomial<C>(ring, one, crel.e);
272                            Cs = C1.multiply(Cs);
273                            ring.coeffTable.update(e2, g2, Cs);
274                        }
275                        if (!g1.isZERO()) { // process remaining right part
276                            GenPolynomial<C> c2 = b.ring.valueOf(g1); 
277                            C2 = new RecSolvablePolynomial<C>(ring, c2, Z);
278                            Cs = Cs.multiply(C2);
279                        }
280                        if (!e1.isZERO()) { // process remaining left part
281                            C1 = new RecSolvablePolynomial<C>(ring, one, e1);
282                            Cs = C1.multiply(Cs);
283                        }
284                        //System.out.println("e1*Cs*g1 = " + Cs);
285                        Cs = Cs.multiplyLeft(cc); // assume c, coeff(cc) commutes with Cs
286                        //Cps = (RecSolvablePolynomial<C>) Cps.sum(Cs);
287                        Cps.doAddTo(Cs);
288                    } // end b loop 
289                    if (debug)
290                        logger.info("coeff, Cs = " + Cs + ", Cps = " + Cps);
291                }
292                if (debug)
293                    logger.info("coeff-poly: Cps = " + Cps);
294                // polynomial multiplication P_eb*f, for a*(P_eb*f)
295                RecSolvablePolynomial<C> Dps = ring.getZERO().copy();
296                RecSolvablePolynomial<C> Ds = null;
297                RecSolvablePolynomial<C> D1, D2;
298                if (commute || Cps.isConstant() || f.isZERO()) { // symmetric
299                    if (debug)
300                        logger.info("symmetric poly, P_eb*f: Cps = " + Cps + ", f = " + f);
301                    ExpVector g = e.sum(f);
302                    if (Cps.isConstant()) {
303                        Ds = new RecSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric!
304                    } else {
305                        Ds = Cps.shift(f); // symmetric
306                    }
307                } else { // eventually unsymmetric
308                    if (debug)
309                        logger.info("unsymmetric poly, P_eb*f: Cps = " + Cps + ", f = " + f);
310                    for (Map.Entry<ExpVector, GenPolynomial<C>> z : Cps.val.entrySet()) {
311                        // split g = g1 * g2, f = f1 * f2
312                        GenPolynomial<C> c = z.getValue();
313                        ExpVector g = z.getKey();
314                        if (debug)
315                            logger.info("g = " + g + ", c = " + c);
316                        int[] gp = g.dependencyOnVariables();
317                        int gl1 = ring.nvar + 1;
318                        if (gp.length > 0) {
319                            gl1 = gp[0];
320                        }
321                        int gl1s = ring.nvar + 1 - gl1;
322                        if (gl1s <= fl1s) { // symmetric
323                            ExpVector h = g.sum(f);
324                            if (debug)
325                                logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h);
326                            Ds = ring.valueOf(h); // symmetric! 
327                        } else {
328                            ExpVector g1 = g.subst(gl1, 0);
329                            ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1
330                            ExpVector g4;
331                            ExpVector f1 = f.subst(fl1, 0);
332                            ExpVector f2 = Z.subst(fl1, f.getVal(fl1));
333                            if (debug) {
334                                logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps);
335                                logger.info("poly, g2 = " + g2 + ", f2 = " + f2);
336                            }
337                            TableRelation<GenPolynomial<C>> rel = ring.table.lookup(g2, f2);
338                            if (debug)
339                                logger.info("poly, g  = " + g + ", f  = " + f + ", rel = " + rel);
340                            Ds = new RecSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p);
341                            if (rel.f != null) {
342                                D2 = ring.valueOf(rel.f); 
343                                Ds = Ds.multiply(D2);
344                                if (rel.e == null) {
345                                    g4 = g2;
346                                } else {
347                                    g4 = g2.subtract(rel.e);
348                                }
349                                ring.table.update(g4, f2, Ds);
350                            }
351                            if (rel.e != null) {
352                                D1 = ring.valueOf(rel.e); 
353                                Ds = D1.multiply(Ds);
354                                ring.table.update(g2, f2, Ds);
355                            }
356                            if (!f1.isZERO()) {
357                                D2 = ring.valueOf(f1); 
358                                Ds = Ds.multiply(D2);
359                                //ring.table.update(?,f1,Ds)
360                            }
361                            if (!g1.isZERO()) {
362                                D1 = ring.valueOf(g1); 
363                                Ds = D1.multiply(Ds);
364                                //ring.table.update(e1,?,Ds)
365                            }
366                        }
367                        Ds = Ds.multiplyLeft(c); // assume c commutes with Cs
368                        Dps.doAddTo(Ds);
369                    } // end Dps loop
370                    Ds = Dps;
371                }
372                if (debug) {
373                    logger.info("recursion+: Ds = " + Ds + ", a = " + a);
374                }
375                // polynomial coefficient multiplication a*(P_eb*f) = a*Ds
376                Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 
377                if (debug)
378                    logger.info("recursion-: Ds = " + Ds);
379                Dp.doAddTo(Ds);
380                if (debug)
381                    logger.info("end B loop: Dp = " + Dp);
382            } // end B loop
383            if (debug)
384                logger.info("end A loop: Dp = " + Dp);
385        } // end A loop
386        return Dp;
387    }
388
389
390    /**
391     * RecSolvablePolynomial left and right multiplication. Product with two
392     * polynomials.
393     * @param S RecSolvablePolynomial.
394     * @param T RecSolvablePolynomial.
395     * @return S*this*T.
396     */
397    // cannot @Override, @NoOverride
398    public RecSolvablePolynomial<C> multiply(RecSolvablePolynomial<C> S, RecSolvablePolynomial<C> T) {
399        if (S.isZERO() || T.isZERO() || this.isZERO()) {
400            return ring.getZERO();
401        }
402        if (S.isONE()) {
403            return multiply(T);
404        }
405        if (T.isONE()) {
406            return S.multiply(this);
407        }
408        return S.multiply(this).multiply(T);
409    }
410
411
412    /**
413     * RecSolvablePolynomial multiplication. Product with coefficient ring
414     * element.
415     * @param b coefficient polynomial.
416     * @return this*b, where * is coefficient multiplication.
417     */
418    // cannot @Override
419    //public RecSolvablePolynomial<C> multiply(GenPolynomial<C> b) {
420    //public GenSolvablePolynomial<GenPolynomial<C>> multiply(GenPolynomial<C> b) {
421    public RecSolvablePolynomial<C> recMultiply(GenPolynomial<C> b) {
422        RecSolvablePolynomial<C> Cp = ring.getZERO().copy();
423        if (b == null || b.isZERO()) {
424            return Cp;
425        }
426        Cp = new RecSolvablePolynomial<C>(ring, b, ring.evzero);
427        return multiply(Cp);
428        // wrong:
429        // Map<ExpVector, GenPolynomial<C>> Cm = Cp.val; //getMap();
430        // Map<ExpVector, GenPolynomial<C>> Am = val;
431        // for (Map.Entry<ExpVector, GenPolynomial<C>> y : Am.entrySet()) {
432        //     ExpVector e = y.getKey();
433        //     GenPolynomial<C> a = y.getValue();
434        //     GenPolynomial<C> c = a.multiply(b);
435        //     if (!c.isZERO()) {
436        //         Cm.put(e, c);
437        //     }
438        // }
439        // return Cp;
440    }
441
442
443    /**
444     * RecSolvablePolynomial left and right multiplication. Product with
445     * coefficient ring element.
446     * @param b coefficient polynomial.
447     * @param c coefficient polynomial.
448     * @return b*this*c, where * is coefficient multiplication.
449     */
450    @Override
451    public RecSolvablePolynomial<C> multiply(GenPolynomial<C> b, GenPolynomial<C> c) {
452        RecSolvablePolynomial<C> Cp = ring.getZERO().copy();
453        if (b == null || b.isZERO()) {
454            return Cp;
455        }
456        if (c == null || c.isZERO()) {
457            return Cp;
458        }
459        RecSolvablePolynomial<C> Cb = ring.valueOf(b); 
460        RecSolvablePolynomial<C> Cc = ring.valueOf(c); 
461        return Cb.multiply(this).multiply(Cc);
462        // wrong:
463        // Map<ExpVector, GenPolynomial<C>> Cm = Cp.val; //getMap();
464        // Map<ExpVector, GenPolynomial<C>> Am = val;
465        // for (Map.Entry<ExpVector, GenPolynomial<C>> y : Am.entrySet()) {
466        //     ExpVector e = y.getKey();
467        //     GenPolynomial<C> a = y.getValue();
468        //     GenPolynomial<C> d = b.multiply(a).multiply(c);
469        //     if (!d.isZERO()) {
470        //         Cm.put(e, d);
471        //     }
472        // }
473        // return Cp;
474    }
475
476
477    /*
478     * RecSolvablePolynomial multiplication. Product with coefficient ring
479     * element.
480     * @param b coefficient of coefficient.
481     * @return this*b, where * is coefficient multiplication.
482     */
483    //@Override not possible, @NoOverride
484    //public RecSolvablePolynomial<C> multiply(C b) { ... }
485
486
487    /**
488     * RecSolvablePolynomial multiplication. Product with exponent vector.
489     * @param e exponent.
490     * @return this * x<sup>e</sup>, where * denotes solvable multiplication.
491     */
492    @Override
493    public RecSolvablePolynomial<C> multiply(ExpVector e) {
494        if (e == null || e.isZERO()) {
495            return this;
496        }
497        GenPolynomial<C> b = ring.getONECoefficient();
498        return multiply(b, e);
499    }
500
501
502    /**
503     * RecSolvablePolynomial left and right multiplication. Product with
504     * exponent vector.
505     * @param e exponent.
506     * @param f exponent.
507     * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable
508     *         multiplication.
509     */
510    @Override
511    public RecSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {
512        if (e == null || e.isZERO()) {
513            return this;
514        }
515        if (f == null || f.isZERO()) {
516            return this;
517        }
518        GenPolynomial<C> b = ring.getONECoefficient();
519        return multiply(b, e, b, f);
520    }
521
522
523    /**
524     * RecSolvablePolynomial multiplication. Product with ring element and
525     * exponent vector.
526     * @param b coefficient polynomial.
527     * @param e exponent.
528     * @return this * b x<sup>e</sup>, where * denotes solvable multiplication.
529     */
530    @Override
531    public RecSolvablePolynomial<C> multiply(GenPolynomial<C> b, ExpVector e) {
532        if (b == null || b.isZERO()) {
533            return ring.getZERO();
534        }
535        RecSolvablePolynomial<C> Cp = ring.valueOf(b, e); 
536        return multiply(Cp);
537    }
538
539
540    /**
541     * RecSolvablePolynomial left and right multiplication. Product with ring
542     * element and exponent vector.
543     * @param b coefficient polynomial.
544     * @param e exponent.
545     * @param c coefficient polynomial.
546     * @param f exponent.
547     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes
548     *         solvable multiplication.
549     */
550    @Override
551    public RecSolvablePolynomial<C> multiply(GenPolynomial<C> b, ExpVector e, GenPolynomial<C> c, ExpVector f) {
552        if (b == null || b.isZERO()) {
553            return ring.getZERO();
554        }
555        if (c == null || c.isZERO()) {
556            return ring.getZERO();
557        }
558        RecSolvablePolynomial<C> Cp = ring.valueOf(b, e); 
559        RecSolvablePolynomial<C> Dp = ring.valueOf(c, f); 
560        return multiply(Cp, Dp);
561    }
562
563
564    /**
565     * RecSolvablePolynomial multiplication. Left product with ring element and
566     * exponent vector.
567     * @param b coefficient polynomial.
568     * @param e exponent.
569     * @return b x<sup>e</sup> * this, where * denotes solvable multiplication.
570     */
571    @Override
572    public RecSolvablePolynomial<C> multiplyLeft(GenPolynomial<C> b, ExpVector e) {
573        if (b == null || b.isZERO()) {
574            return ring.getZERO();
575        }
576        RecSolvablePolynomial<C> Cp = ring.valueOf(b, e); 
577        return Cp.multiply(this);
578    }
579
580
581    /**
582     * RecSolvablePolynomial multiplication. Left product with exponent vector.
583     * @param e exponent.
584     * @return x<sup>e</sup> * this, where * denotes solvable multiplication.
585     */
586    @Override
587    public RecSolvablePolynomial<C> multiplyLeft(ExpVector e) {
588        if (e == null || e.isZERO()) {
589            return this;
590        }
591        RecSolvablePolynomial<C> Cp = ring.valueOf(e); 
592        return Cp.multiply(this);
593    }
594
595
596    /**
597     * RecSolvablePolynomial multiplication. Left product with coefficient ring
598     * element.
599     * @param b coefficient polynomial.
600     * @return b*this, where * is coefficient multiplication.
601     */
602    @Override
603    public RecSolvablePolynomial<C> multiplyLeft(GenPolynomial<C> b) {
604        RecSolvablePolynomial<C> Cp = ring.getZERO().copy();
605        if (b == null || b.isZERO()) {
606            return Cp;
607        }
608        GenSolvablePolynomial<C> bb = null;
609        if (b instanceof GenSolvablePolynomial) {
610            //throw new RuntimeException("wrong method dispatch in JRE ");
611            logger.debug("warn: wrong method dispatch in JRE multiply(b) - trying to fix");
612            bb = (GenSolvablePolynomial<C>) b;
613        }
614        Map<ExpVector, GenPolynomial<C>> Cm = Cp.val; //getMap();
615        Map<ExpVector, GenPolynomial<C>> Am = val;
616        GenPolynomial<C> c;
617        for (Map.Entry<ExpVector, GenPolynomial<C>> y : Am.entrySet()) {
618            ExpVector e = y.getKey();
619            GenPolynomial<C> a = y.getValue();
620            if (bb != null) {
621                GenSolvablePolynomial<C> aa = (GenSolvablePolynomial<C>) a;
622                c = bb.multiply(aa);
623            } else {
624                c = b.multiply(a);
625            }
626            if (!c.isZERO()) {
627                Cm.put(e, c);
628            }
629        }
630        return Cp;
631    }
632
633
634    /**
635     * RecSolvablePolynomial multiplication. Left product with 'monomial'.
636     * @param m 'monomial'.
637     * @return m * this, where * denotes solvable multiplication.
638     */
639    @Override
640    public RecSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, GenPolynomial<C>> m) {
641        if (m == null) {
642            return ring.getZERO();
643        }
644        return multiplyLeft(m.getValue(), m.getKey());
645    }
646
647
648    /**
649     * RecSolvablePolynomial multiplication. Product with 'monomial'.
650     * @param m 'monomial'.
651     * @return this * m, where * denotes solvable multiplication.
652     */
653    @Override
654    public RecSolvablePolynomial<C> multiply(Map.Entry<ExpVector, GenPolynomial<C>> m) {
655        if (m == null) {
656            return ring.getZERO();
657        }
658        return multiply(m.getValue(), m.getKey());
659    }
660
661
662    /**
663     * RecSolvablePolynomial multiplication. Commutative product with exponent
664     * vector.
665     * @param f exponent vector.
666     * @return B*f, where * is commutative multiplication.
667     */
668    public RecSolvablePolynomial<C> shift(ExpVector f) {
669        RecSolvablePolynomial<C> C = ring.getZERO().copy();
670        if (this.isZERO()) {
671            return C;
672        }
673        if (f == null || f.isZERO()) {
674            return this;
675        }
676        Map<ExpVector, GenPolynomial<C>> Cm = C.val;
677        Map<ExpVector, GenPolynomial<C>> Bm = this.val;
678        for (Map.Entry<ExpVector, GenPolynomial<C>> y : Bm.entrySet()) {
679            ExpVector e = y.getKey();
680            GenPolynomial<C> a = y.getValue();
681            ExpVector d = e.sum(f);
682            if (!a.isZERO()) {
683                Cm.put(d, a);
684            }
685        }
686        return C;
687    }
688
689
690    /**
691     * RecSolvablePolynomial multiplication. Commutative product with 
692     * coefficient.
693     * @param b coefficient.
694     * @return B*b, where * is commutative multiplication with respect to main variables.
695     */
696     public RecSolvablePolynomial<C> multiplyRightComm(GenPolynomial<C> b) {
697        RecSolvablePolynomial<C> C = ring.getZERO().copy();
698        if (this.isZERO()) {
699            return C;
700        }
701        if (b == null || b.isZERO()) {
702            return this;
703        }
704        Map<ExpVector, GenPolynomial<C>> Cm = C.val;
705        Map<ExpVector, GenPolynomial<C>> Bm = this.val;
706        for (Map.Entry<ExpVector, GenPolynomial<C>> y : Bm.entrySet()) {
707            ExpVector e = y.getKey();
708            GenPolynomial<C> a = y.getValue();
709            a = a.multiply(b);
710            if (!a.isZERO()) {
711                Cm.put(e, a);
712            }
713        }
714        return C;
715    }
716
717
718    /**
719     * RecSolvablePolynomial right coefficients from left coefficients.
720     * <b>Note:</b> R is represented as a polynomial with left coefficients, the
721     * implementation can at the moment not distinguish between left and right
722     * coefficients.
723     * @return R = sum( X<sup>i</sup> b<sub>i</sub> ), with this =
724     *         sum(a<sub>i</sub> X<sup>i</sup> ) and eval(sum(X<sup>i</sup>
725     *         b<sub>i</sub>)) == sum(a<sub>i</sub> X<sup>i</sup>)
726     */
727    @SuppressWarnings("cast")
728    @Override
729    public GenSolvablePolynomial<GenPolynomial<C>> rightRecursivePolynomial() {
730        if (this.isZERO()) {
731            return this;
732        }
733        if (!(this instanceof RecSolvablePolynomial)) {
734            return this;
735        }
736        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
737        if (rfac.coeffTable.isEmpty()) {
738            return this;
739        }
740        RecSolvablePolynomial<C> R = rfac.getZERO().copy();
741        RecSolvablePolynomial<C> p = this;
742        RecSolvablePolynomial<C> r;
743        while (!p.isZERO()) {
744            ExpVector f = p.leadingExpVector();
745            GenPolynomial<C> a = p.leadingBaseCoefficient();
746            //r = h.multiply(a); // wrong method dispatch // right: f*a
747            //okay: r = onep.multiply(one, f, a, zero); // right: (1 f) * 1 * (a zero)
748            r = rfac.valueOf(f).multiply(rfac.valueOf(a)); // right: (1 f) * 1 * (a zero)
749            //System.out.println("a,f = " + a + ", " + f); // + ", h.ring = " + h.ring.toScript());
750            //System.out.println("f*a = " + r); // + ", r.ring = " + r.ring.toScript());
751            p = (RecSolvablePolynomial<C>) p.subtract(r);
752            R = (RecSolvablePolynomial<C>) R.sum(a, f);
753            //R.doPutToMap(f, a);
754        }
755        return R;
756    }
757
758
759    /**
760     * Evaluate RecSolvablePolynomial as right coefficients polynomial.
761     * <b>Note:</b> R is represented as a polynomial with left coefficients, the
762     * implementation can at the moment not distinguish between left and right
763     * coefficients.
764     * @return this as evaluated polynomial R. R = sum( X<sup>i</sup>
765     *         b<sub>i</sub> ), this = sum(a<sub>i</sub> X<sup>i</sup> ) =
766     *         eval(sum(X<sup>i</sup> b<sub>i</sub>))
767     */
768    @SuppressWarnings("cast")
769    @Override
770    public GenSolvablePolynomial<GenPolynomial<C>> evalAsRightRecursivePolynomial() {
771        if (this.isONE() || this.isZERO()) {
772            return this;
773        }
774        if (!(this instanceof RecSolvablePolynomial)) {
775            return this;
776        }
777        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
778        if (rfac.coeffTable.isEmpty()) {
779            return this;
780        }
781        RecSolvablePolynomial<C> q = rfac.getZERO();
782        RecSolvablePolynomial<C> s;
783        RecSolvablePolynomial<C> r = (RecSolvablePolynomial<C>) this;
784        for (Map.Entry<ExpVector, GenPolynomial<C>> y : r.getMap().entrySet()) {
785            ExpVector f = y.getKey();
786            GenPolynomial<C> a = y.getValue();
787            // f.multiply(a); // wrong method dispatch // right: f*a
788            // onep.multiply(f).multiply(a) // should do now
789            //okay: s = onep.multiply(one, f, a, zero); // right: (1 f) * 1 * (a zero)
790            s = rfac.valueOf(f).multiply(rfac.valueOf(a)); // right: (1 f) * 1 * (a zero)
791            q = (RecSolvablePolynomial<C>) q.sum(s);
792        }
793        return q;
794    }
795
796
797    /**
798     * Test RecSolvablePolynomial right coefficients polynomial. <b>Note:</b> R
799     * is represented as a polynomial with left coefficients, the implementation
800     * can at the moment not distinguish between left and right coefficients.
801     * @param R GenSolvablePolynomial with right coefficients.
802     * @return true, if R is polynomial with right coefficients of this. R =
803     *         sum( X<sup>i</sup> b<sub>i</sub> ), with this = sum(a<sub>i</sub>
804     *         X<sup>i</sup> ) and eval(sum(X<sup>i</sup> b<sub>i</sub>)) ==
805     *         sum(a<sub>i</sub> X<sup>i</sup>)
806     */
807    @SuppressWarnings("cast")
808    @Override
809    public boolean isRightRecursivePolynomial(GenSolvablePolynomial<GenPolynomial<C>> R) {
810        if (this.isZERO()) {
811            return R.isZERO();
812        }
813        if (this.isONE()) {
814            return R.isONE();
815        }
816        if (!(this instanceof RecSolvablePolynomial)) {
817            return !(R instanceof RecSolvablePolynomial);
818        }
819        if (!(R instanceof RecSolvablePolynomial)) {
820            return false;
821        }
822        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
823        if (rfac.coeffTable.isEmpty()) {
824            RecSolvablePolynomialRing<C> rf = (RecSolvablePolynomialRing<C>) R.ring;
825            return rf.coeffTable.isEmpty();
826        }
827        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this;
828        RecSolvablePolynomial<C> q = (RecSolvablePolynomial<C>) R.evalAsRightRecursivePolynomial();
829        p = (RecSolvablePolynomial<C>) PolyUtil.<C> monic(p);
830        q = (RecSolvablePolynomial<C>) PolyUtil.<C> monic(q);
831        return p.equals(q);
832    }
833
834}