001/*
002 * $Id: LocalSolvablePolynomial.java 5868 2018-07-20 15:44:13Z kredel $
003 */
004
005package edu.jas.application;
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.poly.ExpVector;
016import edu.jas.poly.GenSolvablePolynomial;
017import edu.jas.poly.RecSolvablePolynomial;
018import edu.jas.poly.TableRelation;
019import edu.jas.structure.GcdRingElem;
020
021
022/**
023 * LocalSolvablePolynomial generic recursive solvable polynomials implementing
024 * RingElem. n-variate ordered solvable polynomials over solvable polynomial
025 * coefficients. Objects of this class are intended to be immutable. The
026 * implementation is based on TreeMap respectively SortedMap from exponents to
027 * coefficients by extension of GenPolynomial.
028 * Will be deprecated use QLRSolvablePolynomial.
029 * @param <C> coefficient type
030 * @author Heinz Kredel
031 */
032
033public class LocalSolvablePolynomial<C extends GcdRingElem<C>> extends
034                GenSolvablePolynomial<SolvableLocal<C>> {
035
036
037    /**
038     * The factory for the recursive solvable polynomial ring. Hides super.ring.
039     */
040    public final LocalSolvablePolynomialRing<C> ring;
041
042
043    private static final Logger logger = LogManager.getLogger(LocalSolvablePolynomial.class);
044
045
046    private static final boolean debug = logger.isDebugEnabled();
047
048
049    /**
050     * Constructor for zero LocalSolvablePolynomial.
051     * @param r solvable polynomial ring factory.
052     */
053    public LocalSolvablePolynomial(LocalSolvablePolynomialRing<C> r) {
054        super(r);
055        ring = r;
056    }
057
058
059    /**
060     * Constructor for LocalSolvablePolynomial.
061     * @param r solvable polynomial ring factory.
062     * @param c coefficient polynomial.
063     * @param e exponent.
064     */
065    public LocalSolvablePolynomial(LocalSolvablePolynomialRing<C> r, SolvableLocal<C> c, ExpVector e) {
066        this(r);
067        if (c != null && !c.isZERO()) {
068            val.put(e, c);
069        }
070    }
071
072
073    /**
074     * Constructor for LocalSolvablePolynomial.
075     * @param r solvable polynomial ring factory.
076     * @param c coefficient polynomial.
077     */
078    public LocalSolvablePolynomial(LocalSolvablePolynomialRing<C> r, SolvableLocal<C> c) {
079        this(r, c, r.evzero);
080    }
081
082
083    /**
084     * Constructor for LocalSolvablePolynomial.
085     * @param r solvable polynomial ring factory.
086     * @param S solvable polynomial.
087     */
088    public LocalSolvablePolynomial(LocalSolvablePolynomialRing<C> r, GenSolvablePolynomial<SolvableLocal<C>> S) {
089        this(r, S.getMap());
090    }
091
092
093    /**
094     * Constructor for LocalSolvablePolynomial.
095     * @param r solvable polynomial ring factory.
096     * @param v the SortedMap of some other (solvable) polynomial.
097     */
098    protected LocalSolvablePolynomial(LocalSolvablePolynomialRing<C> r,
099                    SortedMap<ExpVector, SolvableLocal<C>> v) {
100        this(r);
101        val.putAll(v); // assume no zero coefficients
102    }
103
104
105    /**
106     * Get the corresponding element factory.
107     * @return factory for this Element.
108     * @see edu.jas.structure.Element#factory()
109     */
110    @Override
111    public LocalSolvablePolynomialRing<C> factory() {
112        return ring;
113    }
114
115
116    /**
117     * Clone this LocalSolvablePolynomial.
118     * @see java.lang.Object#clone()
119     */
120    @Override
121    public LocalSolvablePolynomial<C> copy() {
122        return new LocalSolvablePolynomial<C>(ring, this.val);
123    }
124
125
126    /**
127     * Comparison with any other object.
128     * @see java.lang.Object#equals(java.lang.Object)
129     */
130    @Override
131    public boolean equals(Object B) {
132        if (!(B instanceof LocalSolvablePolynomial)) {
133            return false;
134        }
135        return super.equals(B);
136    }
137
138
139    /**
140     * LocalSolvablePolynomial multiplication.
141     * @param Bp LocalSolvablePolynomial.
142     * @return this*Bp, where * denotes solvable multiplication.
143     */
144    // not @Override
145    public LocalSolvablePolynomial<C> multiply(LocalSolvablePolynomial<C> Bp) {
146        if (Bp == null || Bp.isZERO()) {
147            return ring.getZERO();
148        }
149        if (this.isZERO()) {
150            return this;
151        }
152        if (Bp.isONE()) {
153            return this;
154        }
155        if (this.isONE()) {
156            return Bp;
157        }
158        assert (ring.nvar == Bp.ring.nvar);
159        if (debug) {
160            logger.debug("ring = " + ring);
161        }
162        //System.out.println("this = " + this + ", Bp = " + Bp);
163        ExpVector Z = ring.evzero;
164        LocalSolvablePolynomial<C> Dp = ring.getZERO().copy();
165        LocalSolvablePolynomial<C> zero = ring.getZERO().copy();
166        SolvableLocal<C> one = ring.getONECoefficient();
167
168        //LocalSolvablePolynomial<C> C1 = null;
169        //LocalSolvablePolynomial<C> C2 = null;
170        Map<ExpVector, SolvableLocal<C>> A = val;
171        Map<ExpVector, SolvableLocal<C>> B = Bp.val;
172        Set<Map.Entry<ExpVector, SolvableLocal<C>>> Bk = B.entrySet();
173        for (Map.Entry<ExpVector, SolvableLocal<C>> y : A.entrySet()) {
174            SolvableLocal<C> a = y.getValue();
175            ExpVector e = y.getKey();
176            if (debug)
177                logger.info("e = " + e + ", a = " + a);
178            //int[] ep = e.dependencyOnVariables();
179            //int el1 = ring.nvar + 1;
180            //if (ep.length > 0) {
181            //    el1 = ep[0];
182            //}
183            //int el1s = ring.nvar + 1 - el1;
184            for (Map.Entry<ExpVector, SolvableLocal<C>> x : Bk) {
185                SolvableLocal<C> b = x.getValue();
186                ExpVector f = x.getKey();
187                if (debug)
188                    logger.info("f = " + f + ", b = " + b);
189                int[] fp = f.dependencyOnVariables();
190                int fl1 = 0;
191                if (fp.length > 0) {
192                    fl1 = fp[fp.length - 1];
193                }
194                int fl1s = ring.nvar + 1 - fl1;
195                // polynomial with coefficient multiplication 
196                LocalSolvablePolynomial<C> Cps = ring.getZERO().copy();
197                //LocalSolvablePolynomial<C> Cs;
198                LocalSolvablePolynomial<C> qp;
199                if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric
200                    Cps = new LocalSolvablePolynomial<C>(ring, b, e);
201                    if (debug)
202                        logger.info("symmetric coeff: b = " + b + ", e = " + e);
203                } else { // unsymmetric
204                    if (debug)
205                        logger.info("unsymmetric coeff: b = " + b + ", e = " + e);
206                    // compute e * b as ( e * 1/b.den ) * b.num
207                    if (b.den.isONE()) { // recursion base
208                        // for (Map.Entry<ExpVector, C> z : b.num.getMap().entrySet()) {
209                        //     C c = z.getValue();
210                        //     SolvableLocal<C> cc = b.ring.getONE().multiply(c);
211                        //     ExpVector g = z.getKey();
212                        //     if (debug)
213                        //         logger.info("g = " + g + ", c = " + c);
214                        //     int[] gp = g.dependencyOnVariables();
215                        //     int gl1 = 0;
216                        //     if (gp.length > 0) {
217                        //         gl1 = gp[gp.length - 1];
218                        //     }
219                        //     int gl1s = b.ring.ring.nvar + 1 - gl1;
220                        //     if (debug) {
221                        //         logger.info("gl1s = " + gl1s);
222                        //     }
223                        //     // split e = e1 * e2, g = g1 * g2
224                        //     ExpVector e1 = e;
225                        //     ExpVector e2 = Z;
226                        //     if (!e.isZERO()) {
227                        //         e1 = e.subst(el1, 0);
228                        //         e2 = Z.subst(el1, e.getVal(el1));
229                        //     }
230                        //     ExpVector e4;
231                        //     ExpVector g1 = g;
232                        //     ExpVector g2 = Zc;
233                        //     if (!g.isZERO()) {
234                        //         g1 = g.subst(gl1, 0);
235                        //         g2 = Zc.subst(gl1, g.getVal(gl1));
236                        //     }
237                        //     if (debug)
238                        //         logger.info("coeff, e1 = " + e1 + ", e2 = " + e2);
239                        //     if (debug)
240                        //         logger.info("coeff, g1 = " + g1 + ", g2 = " + g2);
241                        //     TableRelation<GenPolynomial<C>> crel = ring.coeffTable.lookup(e2, g2);
242                        //     if (debug)
243                        //         logger.info("coeff, crel = " + crel.p);
244                        //     if (debug)
245                        //         logger.info("coeff, e  = " + e + " g, = " + g + ", crel = " + crel);
246                        //     Cs = ring.fromPolyCoefficients(crel.p); //LocalSolvablePolynomial<C>(ring, crel.p);
247                        //     // rest of multiplication and update relations
248                        //     if (crel.f != null) {
249                        //         SolvableLocal<C> c2 = b.ring.getONE().multiply(crel.f);
250                        //         C2 = new LocalSolvablePolynomial<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, ring.toPolyCoefficients(Cs));
258                        //     }
259                        //     if (crel.e != null) { // process left part
260                        //         C1 = new LocalSolvablePolynomial<C>(ring, one, crel.e);
261                        //         Cs = C1.multiply(Cs);
262                        //         ring.coeffTable.update(e2, g2, ring.toPolyCoefficients(Cs));
263                        //     }
264                        //     if (!g1.isZERO()) { // process right part
265                        //         SolvableLocal<C> c2 = b.ring.getONE().multiply(g1);
266                        //         C2 = new LocalSolvablePolynomial<C>(ring, c2, Z);
267                        //         Cs = Cs.multiply(C2);
268                        //     }
269                        //     if (!e1.isZERO()) { // process left part
270                        //         C1 = new LocalSolvablePolynomial<C>(ring, one, e1);
271                        //         Cs = C1.multiply(Cs);
272                        //     }
273                        //     //System.out.println("e1*Cs*g1 = " + Cs);
274                        //     Cs = Cs.multiplyLeft(cc); // cc * Cs
275                        //     Cps = (LocalSolvablePolynomial<C>) Cps.sum(Cs);
276                        // } // end b.num loop 
277                        // recursive polynomial coefficient multiplication : e * b.num
278                        RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e);
279                        RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.num);
280                        RecSolvablePolynomial<C> rsp3 = rsp1.multiply(rsp2);
281                        LocalSolvablePolynomial<C> rsp = ring.fromPolyCoefficients(rsp3);
282                        Cps = rsp;
283                        // if (rsp.compareTo(Cps) != 0) {
284                        //     logger.info("coeff-poly: Cps = " + Cps);
285                        //     logger.info("coeff-poly: rsp = " + rsp);
286                        //     //System.out.println("rsp.compareTo(Cps) != 0");
287                        //     //} else {
288                        //     //System.out.println("rsp.compareTo(Cps) == 0");
289                        // }
290                    } else { // b.den != 1
291                        if (debug)
292                            logger.info("coeff-num: Cps = " + Cps + ", num = " + b.num + ", den = " + b.den);
293                        Cps = new LocalSolvablePolynomial<C>(ring, b.ring.getONE(), e);
294
295                        // coefficient multiplication with 1/den: 
296                        LocalSolvablePolynomial<C> qv = Cps;
297                        SolvableLocal<C> qden = new SolvableLocal<C>(b.ring, b.den); // den/1
298                        //System.out.println("qv = " + qv + ", den = " + den);
299                        // recursion with den==1:
300                        LocalSolvablePolynomial<C> v = qv.multiply(qden);
301                        LocalSolvablePolynomial<C> vl = qv.multiplyLeft(qden);
302                        //System.out.println("v = " + v + ", vl = " + vl + ", qden = " + qden);
303                        LocalSolvablePolynomial<C> vr = (LocalSolvablePolynomial<C>) v.subtract(vl);
304                        SolvableLocal<C> qdeni = new SolvableLocal<C>(b.ring, b.ring.ring.getONE(), b.den);
305                        //System.out.println("vr = " + vr + ", qdeni = " + qdeni);
306                        // recursion with smaller head term:
307                        LocalSolvablePolynomial<C> rq = vr.multiply(qdeni);
308                        qp = (LocalSolvablePolynomial<C>) qv.subtract(rq);
309                        qp = qp.multiplyLeft(qdeni);
310                        //System.out.println("qp_i = " + qp);
311                        Cps = qp;
312
313                        if (!b.num.isONE()) {
314                            SolvableLocal<C> qnum = new SolvableLocal<C>(b.ring, b.num); // num/1
315                            // recursion with den == 1:
316                            Cps = Cps.multiply(qnum);
317                        }
318                    }
319                } // end coeff
320                if (debug)
321                    logger.info("coeff-den: Cps = " + Cps);
322                // polynomial multiplication 
323                LocalSolvablePolynomial<C> Dps = ring.getZERO().copy();
324                LocalSolvablePolynomial<C> Ds = null;
325                LocalSolvablePolynomial<C> D1, D2;
326                if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric
327                    if (debug)
328                        logger.info("symmetric poly: b = " + b + ", e = " + e);
329                    ExpVector g = e.sum(f);
330                    if (Cps.isConstant()) {
331                        Ds = new LocalSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric!
332                    } else {
333                        Ds = Cps.shift(f); // symmetric
334                    }
335                } else { // eventually unsymmetric
336                    if (debug)
337                        logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f);
338                    for (Map.Entry<ExpVector, SolvableLocal<C>> z : Cps.val.entrySet()) {
339                        // split g = g1 * g2, f = f1 * f2
340                        SolvableLocal<C> c = z.getValue();
341                        ExpVector g = z.getKey();
342                        if (debug)
343                            logger.info("g = " + g + ", c = " + c);
344                        int[] gp = g.dependencyOnVariables();
345                        int gl1 = ring.nvar + 1;
346                        if (gp.length > 0) {
347                            gl1 = gp[0];
348                        }
349                        int gl1s = ring.nvar + 1 - gl1;
350                        if (gl1s <= fl1s) { // symmetric
351                            ExpVector h = g.sum(f);
352                            if (debug)
353                                logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h);
354                            Ds = (LocalSolvablePolynomial<C>) zero.sum(one, h); // symmetric!
355                        } else {
356                            ExpVector g1 = g.subst(gl1, 0);
357                            ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1
358                            ExpVector g4;
359                            ExpVector f1 = f.subst(fl1, 0);
360                            ExpVector f2 = Z.subst(fl1, f.getVal(fl1));
361                            if (debug) {
362                                logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps);
363                                logger.info("poly, g2 = " + g2 + ", f2 = " + f2);
364                            }
365                            TableRelation<SolvableLocal<C>> rel = ring.table.lookup(g2, f2);
366                            if (debug)
367                                logger.info("poly, g  = " + g + ", f  = " + f + ", rel = " + rel);
368                            Ds = new LocalSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p);
369                            if (rel.f != null) {
370                                D2 = new LocalSolvablePolynomial<C>(ring, one, rel.f);
371                                Ds = Ds.multiply(D2);
372                                if (rel.e == null) {
373                                    g4 = g2;
374                                } else {
375                                    g4 = g2.subtract(rel.e);
376                                }
377                                ring.table.update(g4, f2, Ds);
378                            }
379                            if (rel.e != null) {
380                                D1 = new LocalSolvablePolynomial<C>(ring, one, rel.e);
381                                Ds = D1.multiply(Ds);
382                                ring.table.update(g2, f2, Ds);
383                            }
384                            if (!f1.isZERO()) {
385                                D2 = new LocalSolvablePolynomial<C>(ring, one, f1);
386                                Ds = Ds.multiply(D2);
387                                //ring.table.update(?,f1,Ds)
388                            }
389                            if (!g1.isZERO()) {
390                                D1 = new LocalSolvablePolynomial<C>(ring, one, g1);
391                                Ds = D1.multiply(Ds);
392                                //ring.table.update(e1,?,Ds)
393                            }
394                        }
395                        Ds = Ds.multiplyLeft(c); // c * Ds
396                        Dps = (LocalSolvablePolynomial<C>) Dps.sum(Ds);
397                    } // end Dps loop
398                    Ds = Dps;
399                }
400                Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 
401                if (debug)
402                    logger.debug("Ds = " + Ds);
403                Dp = (LocalSolvablePolynomial<C>) Dp.sum(Ds);
404            } // end B loop
405        } // end A loop
406          //System.out.println("this * Bp = " + Dp);
407        return Dp;
408    }
409
410
411    /**
412     * LocalSolvablePolynomial left and right multiplication. Product with two
413     * polynomials.
414     * @param S LocalSolvablePolynomial.
415     * @param T LocalSolvablePolynomial.
416     * @return S*this*T.
417     */
418    // not @Override
419    public LocalSolvablePolynomial<C> multiply(LocalSolvablePolynomial<C> S, LocalSolvablePolynomial<C> T) {
420        if (S.isZERO() || T.isZERO() || this.isZERO()) {
421            return ring.getZERO();
422        }
423        if (S.isONE()) {
424            return multiply(T);
425        }
426        if (T.isONE()) {
427            return S.multiply(this);
428        }
429        return S.multiply(this).multiply(T);
430    }
431
432
433    /**
434     * LocalSolvablePolynomial multiplication. Product with coefficient ring
435     * element.
436     * @param b solvable coefficient.
437     * @return this*b, where * is coefficient multiplication.
438     */
439    @Override
440    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b) {
441        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
442        if (b == null || b.isZERO()) {
443            return Cp;
444        }
445        if (b.isONE()) {
446            return this;
447        }
448        Cp = new LocalSolvablePolynomial<C>(ring, b, ring.evzero);
449        return multiply(Cp);
450    }
451
452
453    /**
454     * LocalSolvablePolynomial left and right multiplication. Product with
455     * coefficient ring element.
456     * @param b coefficient polynomial.
457     * @param c coefficient polynomial.
458     * @return b*this*c, where * is coefficient multiplication.
459     */
460    @Override
461    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, SolvableLocal<C> c) {
462        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
463        if (b == null || b.isZERO()) {
464            return Cp;
465        }
466        if (c == null || c.isZERO()) {
467            return Cp;
468        }
469        if (b.isONE() && c.isONE()) {
470            return this;
471        }
472        Cp = new LocalSolvablePolynomial<C>(ring, b, ring.evzero);
473        LocalSolvablePolynomial<C> Dp = new LocalSolvablePolynomial<C>(ring, c, ring.evzero);
474        return multiply(Cp, Dp);
475    }
476
477
478    /**
479     * LocalSolvablePolynomial multiplication. Product with exponent vector.
480     * @param e exponent.
481     * @return this * x<sup>e</sup>, where * denotes solvable multiplication.
482     */
483    @Override
484    public LocalSolvablePolynomial<C> multiply(ExpVector e) {
485        if (e == null || e.isZERO()) {
486            return this;
487        }
488        SolvableLocal<C> b = ring.getONECoefficient();
489        return multiply(b, e);
490    }
491
492
493    /**
494     * LocalSolvablePolynomial left and right multiplication. Product with
495     * exponent vector.
496     * @param e exponent.
497     * @param f exponent.
498     * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable
499     *         multiplication.
500     */
501    @Override
502    public LocalSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {
503        if (e == null || e.isZERO()) {
504            return this;
505        }
506        if (f == null || f.isZERO()) {
507            return this;
508        }
509        SolvableLocal<C> b = ring.getONECoefficient();
510        return multiply(b, e, b, f);
511    }
512
513
514    /**
515     * LocalSolvablePolynomial multiplication. Product with ring element and
516     * exponent vector.
517     * @param b coefficient polynomial.
518     * @param e exponent.
519     * @return this * b x<sup>e</sup>, where * denotes solvable multiplication.
520     */
521    @Override
522    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, ExpVector e) {
523        if (b == null || b.isZERO()) {
524            return ring.getZERO();
525        }
526        if (b.isONE() && e.isZERO()) {
527            return this;
528        }
529        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
530        return multiply(Cp);
531    }
532
533
534    /**
535     * LocalSolvablePolynomial left and right multiplication. Product with ring
536     * element and exponent vector.
537     * @param b coefficient polynomial.
538     * @param e exponent.
539     * @param c coefficient polynomial.
540     * @param f exponent.
541     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes
542     *         solvable multiplication.
543     */
544    @Override
545    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, ExpVector e, SolvableLocal<C> c,
546                    ExpVector f) {
547        if (b == null || b.isZERO()) {
548            return ring.getZERO();
549        }
550        if (c == null || c.isZERO()) {
551            return ring.getZERO();
552        }
553        if (b.isONE() && e.isZERO() && c.isONE() && f.isZERO()) {
554            return this;
555        }
556        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
557        LocalSolvablePolynomial<C> Dp = new LocalSolvablePolynomial<C>(ring, c, f);
558        return multiply(Cp, Dp);
559    }
560
561
562    /**
563     * LocalSolvablePolynomial multiplication. Left product with ring element
564     * and exponent vector.
565     * @param b coefficient polynomial.
566     * @param e exponent.
567     * @return b x<sup>e</sup> * this, where * denotes solvable multiplication.
568     */
569    @Override
570    public LocalSolvablePolynomial<C> multiplyLeft(SolvableLocal<C> b, ExpVector e) {
571        if (b == null || b.isZERO()) {
572            return ring.getZERO();
573        }
574        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
575        return Cp.multiply(this);
576    }
577
578
579    /**
580     * LocalSolvablePolynomial multiplication. Left product with exponent
581     * vector.
582     * @param e exponent.
583     * @return x<sup>e</sup> * this, where * denotes solvable multiplication.
584     */
585    @Override
586    public LocalSolvablePolynomial<C> multiplyLeft(ExpVector e) {
587        if (e == null || e.isZERO()) {
588            return this;
589        }
590        SolvableLocal<C> b = ring.getONECoefficient();
591        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
592        return Cp.multiply(this);
593    }
594
595
596    /**
597     * LocalSolvablePolynomial multiplication. Left product with coefficient
598     * ring element.
599     * @param b coefficient polynomial.
600     * @return b*this, where * is coefficient multiplication.
601     */
602    @Override
603    public LocalSolvablePolynomial<C> multiplyLeft(SolvableLocal<C> b) {
604        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
605        if (b == null || b.isZERO()) {
606            return Cp;
607        }
608        Map<ExpVector, SolvableLocal<C>> Cm = Cp.val; //getMap();
609        Map<ExpVector, SolvableLocal<C>> Am = val;
610        SolvableLocal<C> c;
611        for (Map.Entry<ExpVector, SolvableLocal<C>> y : Am.entrySet()) {
612            ExpVector e = y.getKey();
613            SolvableLocal<C> a = y.getValue();
614            c = b.multiply(a);
615            if (!c.isZERO()) {
616                Cm.put(e, c);
617            }
618        }
619        return Cp;
620    }
621
622
623    /**
624     * LocalSolvablePolynomial multiplication. Left product with 'monomial'.
625     * @param m 'monomial'.
626     * @return m * this, where * denotes solvable multiplication.
627     */
628    @Override
629    public LocalSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableLocal<C>> m) {
630        if (m == null) {
631            return ring.getZERO();
632        }
633        return multiplyLeft(m.getValue(), m.getKey());
634    }
635
636
637    /**
638     * LocalSolvablePolynomial multiplication. Product with 'monomial'.
639     * @param m 'monomial'.
640     * @return this * m, where * denotes solvable multiplication.
641     */
642    @Override
643    public LocalSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableLocal<C>> m) {
644        if (m == null) {
645            return ring.getZERO();
646        }
647        return multiply(m.getValue(), m.getKey());
648    }
649
650
651    /**
652     * LocalSolvablePolynomial multiplication. Left product with coefficient
653     * ring element.
654     * @param f exponent vector.
655     * @return B*f, where * is commutative multiplication.
656     */
657    protected LocalSolvablePolynomial<C> shift(ExpVector f) {
658        LocalSolvablePolynomial<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, SolvableLocal<C>> Cm = C.val;
666        Map<ExpVector, SolvableLocal<C>> Bm = this.val;
667        for (Map.Entry<ExpVector, SolvableLocal<C>> y : Bm.entrySet()) {
668            ExpVector e = y.getKey();
669            SolvableLocal<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}