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