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