001/*
002 * $Id$
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     * Hash code for this polynomial.
141     * @see java.lang.Object#hashCode()
142     */
143    @Override
144    public int hashCode() {
145        return super.hashCode();
146    }
147
148
149    /**
150     * LocalSolvablePolynomial multiplication.
151     * @param Bp LocalSolvablePolynomial.
152     * @return this*Bp, where * denotes solvable multiplication.
153     */
154    // not @Override
155    public LocalSolvablePolynomial<C> multiply(LocalSolvablePolynomial<C> Bp) {
156        if (Bp == null || Bp.isZERO()) {
157            return ring.getZERO();
158        }
159        if (this.isZERO()) {
160            return this;
161        }
162        if (Bp.isONE()) {
163            return this;
164        }
165        if (this.isONE()) {
166            return Bp;
167        }
168        assert (ring.nvar == Bp.ring.nvar);
169        logger.debug("ring = {}", ring);
170        //System.out.println("this = " + this + ", Bp = " + Bp);
171        ExpVector Z = ring.evzero;
172        LocalSolvablePolynomial<C> Dp = ring.getZERO().copy();
173        LocalSolvablePolynomial<C> zero = ring.getZERO().copy();
174        SolvableLocal<C> one = ring.getONECoefficient();
175
176        //LocalSolvablePolynomial<C> C1 = null;
177        //LocalSolvablePolynomial<C> C2 = null;
178        Map<ExpVector, SolvableLocal<C>> A = val;
179        Map<ExpVector, SolvableLocal<C>> B = Bp.val;
180        Set<Map.Entry<ExpVector, SolvableLocal<C>>> Bk = B.entrySet();
181        for (Map.Entry<ExpVector, SolvableLocal<C>> y : A.entrySet()) {
182            SolvableLocal<C> a = y.getValue();
183            ExpVector e = y.getKey();
184            if (debug) {
185                logger.info("e = {}, a = {}", e, a);
186            }
187            //int[] ep = e.dependencyOnVariables();
188            //int el1 = ring.nvar + 1;
189            //if (ep.length > 0) {
190            //    el1 = ep[0];
191            //}
192            //int el1s = ring.nvar + 1 - el1;
193            for (Map.Entry<ExpVector, SolvableLocal<C>> x : Bk) {
194                SolvableLocal<C> b = x.getValue();
195                ExpVector f = x.getKey();
196                if (debug)
197                    logger.info("f = {}, b = {}", f, b);
198                int[] fp = f.dependencyOnVariables();
199                int fl1 = 0;
200                if (fp.length > 0) {
201                    fl1 = fp[fp.length - 1];
202                }
203                int fl1s = ring.nvar + 1 - fl1;
204                // polynomial with coefficient multiplication 
205                LocalSolvablePolynomial<C> Cps = ring.getZERO().copy();
206                //LocalSolvablePolynomial<C> Cs;
207                LocalSolvablePolynomial<C> qp;
208                if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric
209                    Cps = new LocalSolvablePolynomial<C>(ring, b, e);
210                    if (debug)
211                        logger.info("symmetric coeff: b = {}, e = {}", b, e);
212                } else { // unsymmetric
213                    if (debug)
214                        logger.info("unsymmetric coeff: b = {}, e = {}", b, e);
215                    // compute e * b as ( e * 1/b.den ) * b.num
216                    if (b.den.isONE()) { // recursion base
217                        // for (Map.Entry<ExpVector, C> z : b.num.getMap().entrySet()) {
218                        //     C c = z.getValue();
219                        //     SolvableLocal<C> cc = b.ring.getONE().multiply(c);
220                        //     ExpVector g = z.getKey();
221                        //     if (debug)
222                        //         logger.info("g = {}, c = {}", g, c);
223                        //     int[] gp = g.dependencyOnVariables();
224                        //     int gl1 = 0;
225                        //     if (gp.length > 0) {
226                        //         gl1 = gp[gp.length - 1];
227                        //     }
228                        //     int gl1s = b.ring.ring.nvar + 1 - gl1;
229                        //     if (debug) {
230                        //         logger.info("gl1s = {}", gl1s);
231                        //     }
232                        //     // split e = e1 * e2, g = g1 * g2
233                        //     ExpVector e1 = e;
234                        //     ExpVector e2 = Z;
235                        //     if (!e.isZERO()) {
236                        //         e1 = e.subst(el1, 0);
237                        //         e2 = Z.subst(el1, e.getVal(el1));
238                        //     }
239                        //     ExpVector e4;
240                        //     ExpVector g1 = g;
241                        //     ExpVector g2 = Zc;
242                        //     if (!g.isZERO()) {
243                        //         g1 = g.subst(gl1, 0);
244                        //         g2 = Zc.subst(gl1, g.getVal(gl1));
245                        //     }
246                        //     if (debug)
247                        //         logger.info("coeff, e1 = {}, e2 = {}", e1, e2);
248                        //     if (debug)
249                        //         logger.info("coeff, g1 = {}, g2 = {}", g1, g2);
250                        //     TableRelation<GenPolynomial<C>> crel = ring.coeffTable.lookup(e2, g2);
251                        //     if (debug)
252                        //         logger.info("coeff, crel = {}", crel.p);
253                        //     if (debug)
254                        //         logger.info("coeff, e  = {}, g = {}, crel = {}", e, g, crel);
255                        //     Cs = ring.fromPolyCoefficients(crel.p); //LocalSolvablePolynomial<C>(ring, crel.p);
256                        //     // rest of multiplication and update relations
257                        //     if (crel.f != null) {
258                        //         SolvableLocal<C> c2 = b.ring.getONE().multiply(crel.f);
259                        //         C2 = new LocalSolvablePolynomial<C>(ring, c2, Z);
260                        //         Cs = Cs.multiply(C2);
261                        //         if (crel.e == null) {
262                        //             e4 = e2;
263                        //         } else {
264                        //             e4 = e2.subtract(crel.e);
265                        //         }
266                        //         ring.coeffTable.update(e4, g2, ring.toPolyCoefficients(Cs));
267                        //     }
268                        //     if (crel.e != null) { // process left part
269                        //         C1 = new LocalSolvablePolynomial<C>(ring, one, crel.e);
270                        //         Cs = C1.multiply(Cs);
271                        //         ring.coeffTable.update(e2, g2, ring.toPolyCoefficients(Cs));
272                        //     }
273                        //     if (!g1.isZERO()) { // process right part
274                        //         SolvableLocal<C> c2 = b.ring.getONE().multiply(g1);
275                        //         C2 = new LocalSolvablePolynomial<C>(ring, c2, Z);
276                        //         Cs = Cs.multiply(C2);
277                        //     }
278                        //     if (!e1.isZERO()) { // process left part
279                        //         C1 = new LocalSolvablePolynomial<C>(ring, one, e1);
280                        //         Cs = C1.multiply(Cs);
281                        //     }
282                        //     //System.out.println("e1*Cs*g1 = " + Cs);
283                        //     Cs = Cs.multiplyLeft(cc); // cc * Cs
284                        //     Cps = (LocalSolvablePolynomial<C>) Cps.sum(Cs);
285                        // } // end b.num loop 
286                        // recursive polynomial coefficient multiplication : e * b.num
287                        RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e);
288                        RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.num);
289                        RecSolvablePolynomial<C> rsp3 = rsp1.multiply(rsp2);
290                        LocalSolvablePolynomial<C> rsp = ring.fromPolyCoefficients(rsp3);
291                        Cps = rsp;
292                        // if (rsp.compareTo(Cps) != 0) {
293                        //     logger.info("coeff-poly: Cps = {}", Cps);
294                        //     logger.info("coeff-poly: rsp = {}", rsp);
295                        //     //System.out.println("rsp.compareTo(Cps) != 0");
296                        //     //} else {
297                        //     //System.out.println("rsp.compareTo(Cps) == 0");
298                        // }
299                    } else { // b.den != 1
300                        if (debug)
301                            logger.info("coeff-num: Cps = {}, num = {}, den = {}", Cps, b.num, b.den);
302                        Cps = new LocalSolvablePolynomial<C>(ring, b.ring.getONE(), e);
303
304                        // coefficient multiplication with 1/den: 
305                        LocalSolvablePolynomial<C> qv = Cps;
306                        SolvableLocal<C> qden = new SolvableLocal<C>(b.ring, b.den); // den/1
307                        //System.out.println("qv = " + qv + ", den = " + den);
308                        // recursion with den==1:
309                        LocalSolvablePolynomial<C> v = qv.multiply(qden);
310                        LocalSolvablePolynomial<C> vl = qv.multiplyLeft(qden);
311                        //System.out.println("v = " + v + ", vl = " + vl + ", qden = " + qden);
312                        LocalSolvablePolynomial<C> vr = (LocalSolvablePolynomial<C>) v.subtract(vl);
313                        SolvableLocal<C> qdeni = new SolvableLocal<C>(b.ring, b.ring.ring.getONE(), b.den);
314                        //System.out.println("vr = " + vr + ", qdeni = " + qdeni);
315                        // recursion with smaller head term:
316                        LocalSolvablePolynomial<C> rq = vr.multiply(qdeni);
317                        qp = (LocalSolvablePolynomial<C>) qv.subtract(rq);
318                        qp = qp.multiplyLeft(qdeni);
319                        //System.out.println("qp_i = " + qp);
320                        Cps = qp;
321
322                        if (!b.num.isONE()) {
323                            SolvableLocal<C> qnum = new SolvableLocal<C>(b.ring, b.num); // num/1
324                            // recursion with den == 1:
325                            Cps = Cps.multiply(qnum);
326                        }
327                    }
328                } // end coeff
329                if (debug)
330                    logger.info("coeff-den: Cps = {}", Cps);
331                // polynomial multiplication 
332                LocalSolvablePolynomial<C> Dps = ring.getZERO().copy();
333                LocalSolvablePolynomial<C> Ds = null;
334                LocalSolvablePolynomial<C> D1, D2;
335                if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric
336                    if (debug)
337                        logger.info("symmetric poly: b = {}, e = {}", b, e);
338                    ExpVector g = e.sum(f);
339                    if (Cps.isConstant()) {
340                        Ds = new LocalSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric!
341                    } else {
342                        Ds = Cps.shift(f); // symmetric
343                    }
344                } else { // eventually unsymmetric
345                    if (debug)
346                        logger.info("unsymmetric poly: Cps = {}, f = {}", Cps, f);
347                    for (Map.Entry<ExpVector, SolvableLocal<C>> z : Cps.val.entrySet()) {
348                        // split g = g1 * g2, f = f1 * f2
349                        SolvableLocal<C> c = z.getValue();
350                        ExpVector g = z.getKey();
351                        if (debug)
352                            logger.info("g = {}, c = {}", g, c);
353                        int[] gp = g.dependencyOnVariables();
354                        int gl1 = ring.nvar + 1;
355                        if (gp.length > 0) {
356                            gl1 = gp[0];
357                        }
358                        int gl1s = ring.nvar + 1 - gl1;
359                        if (gl1s <= fl1s) { // symmetric
360                            ExpVector h = g.sum(f);
361                            if (debug)
362                                logger.info("disjoint poly: g = {}, f = {}, h = {}", g, f, h);
363                            Ds = (LocalSolvablePolynomial<C>) zero.sum(one, h); // symmetric!
364                        } else {
365                            ExpVector g1 = g.subst(gl1, 0);
366                            ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1
367                            ExpVector g4;
368                            ExpVector f1 = f.subst(fl1, 0);
369                            ExpVector f2 = Z.subst(fl1, f.getVal(fl1));
370                            if (debug) {
371                                logger.info("poly, g1 = {}, f1 = {}, Dps = {}", g1, f1, Dps);
372                                logger.info("poly, g2 = {}, f2 = {}", g2, f2);
373                            }
374                            TableRelation<SolvableLocal<C>> rel = ring.table.lookup(g2, f2);
375                            if (debug)
376                                logger.info("poly, g  = {}, f  = {}, rel = {}", g, f, rel);
377                            Ds = new LocalSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p);
378                            if (rel.f != null) {
379                                D2 = new LocalSolvablePolynomial<C>(ring, one, rel.f);
380                                Ds = Ds.multiply(D2);
381                                if (rel.e == null) {
382                                    g4 = g2;
383                                } else {
384                                    g4 = g2.subtract(rel.e);
385                                }
386                                ring.table.update(g4, f2, Ds);
387                            }
388                            if (rel.e != null) {
389                                D1 = new LocalSolvablePolynomial<C>(ring, one, rel.e);
390                                Ds = D1.multiply(Ds);
391                                ring.table.update(g2, f2, Ds);
392                            }
393                            if (!f1.isZERO()) {
394                                D2 = new LocalSolvablePolynomial<C>(ring, one, f1);
395                                Ds = Ds.multiply(D2);
396                                //ring.table.update(?,f1,Ds)
397                            }
398                            if (!g1.isZERO()) {
399                                D1 = new LocalSolvablePolynomial<C>(ring, one, g1);
400                                Ds = D1.multiply(Ds);
401                                //ring.table.update(e1,?,Ds)
402                            }
403                        }
404                        Ds = Ds.multiplyLeft(c); // c * Ds
405                        Dps = (LocalSolvablePolynomial<C>) Dps.sum(Ds);
406                    } // end Dps loop
407                    Ds = Dps;
408                }
409                Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 
410                logger.debug("Ds = {}", Ds);
411                Dp = (LocalSolvablePolynomial<C>) Dp.sum(Ds);
412            } // end B loop
413        } // end A loop
414          //System.out.println("this * Bp = " + Dp);
415        return Dp;
416    }
417
418
419    /**
420     * LocalSolvablePolynomial left and right multiplication. Product with two
421     * polynomials.
422     * @param S LocalSolvablePolynomial.
423     * @param T LocalSolvablePolynomial.
424     * @return S*this*T.
425     */
426    // not @Override
427    public LocalSolvablePolynomial<C> multiply(LocalSolvablePolynomial<C> S, LocalSolvablePolynomial<C> T) {
428        if (S.isZERO() || T.isZERO() || this.isZERO()) {
429            return ring.getZERO();
430        }
431        if (S.isONE()) {
432            return multiply(T);
433        }
434        if (T.isONE()) {
435            return S.multiply(this);
436        }
437        return S.multiply(this).multiply(T);
438    }
439
440
441    /**
442     * LocalSolvablePolynomial multiplication. Product with coefficient ring
443     * element.
444     * @param b solvable coefficient.
445     * @return this*b, where * is coefficient multiplication.
446     */
447    @Override
448    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b) {
449        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
450        if (b == null || b.isZERO()) {
451            return Cp;
452        }
453        if (b.isONE()) {
454            return this;
455        }
456        Cp = new LocalSolvablePolynomial<C>(ring, b, ring.evzero);
457        return multiply(Cp);
458    }
459
460
461    /**
462     * LocalSolvablePolynomial left and right multiplication. Product with
463     * coefficient ring element.
464     * @param b coefficient polynomial.
465     * @param c coefficient polynomial.
466     * @return b*this*c, where * is coefficient multiplication.
467     */
468    @Override
469    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, SolvableLocal<C> c) {
470        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
471        if (b == null || b.isZERO()) {
472            return Cp;
473        }
474        if (c == null || c.isZERO()) {
475            return Cp;
476        }
477        if (b.isONE() && c.isONE()) {
478            return this;
479        }
480        Cp = new LocalSolvablePolynomial<C>(ring, b, ring.evzero);
481        LocalSolvablePolynomial<C> Dp = new LocalSolvablePolynomial<C>(ring, c, ring.evzero);
482        return multiply(Cp, Dp);
483    }
484
485
486    /**
487     * LocalSolvablePolynomial multiplication. Product with exponent vector.
488     * @param e exponent.
489     * @return this * x<sup>e</sup>, where * denotes solvable multiplication.
490     */
491    @Override
492    public LocalSolvablePolynomial<C> multiply(ExpVector e) {
493        if (e == null || e.isZERO()) {
494            return this;
495        }
496        SolvableLocal<C> b = ring.getONECoefficient();
497        return multiply(b, e);
498    }
499
500
501    /**
502     * LocalSolvablePolynomial left and right multiplication. Product with
503     * exponent vector.
504     * @param e exponent.
505     * @param f exponent.
506     * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable
507     *         multiplication.
508     */
509    @Override
510    public LocalSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {
511        if (e == null || e.isZERO()) {
512            return this;
513        }
514        if (f == null || f.isZERO()) {
515            return this;
516        }
517        SolvableLocal<C> b = ring.getONECoefficient();
518        return multiply(b, e, b, f);
519    }
520
521
522    /**
523     * LocalSolvablePolynomial multiplication. Product with ring element and
524     * exponent vector.
525     * @param b coefficient polynomial.
526     * @param e exponent.
527     * @return this * b x<sup>e</sup>, where * denotes solvable multiplication.
528     */
529    @Override
530    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, ExpVector e) {
531        if (b == null || b.isZERO()) {
532            return ring.getZERO();
533        }
534        if (b.isONE() && e.isZERO()) {
535            return this;
536        }
537        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
538        return multiply(Cp);
539    }
540
541
542    /**
543     * LocalSolvablePolynomial left and right multiplication. Product with ring
544     * element and exponent vector.
545     * @param b coefficient polynomial.
546     * @param e exponent.
547     * @param c coefficient polynomial.
548     * @param f exponent.
549     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes
550     *         solvable multiplication.
551     */
552    @Override
553    public LocalSolvablePolynomial<C> multiply(SolvableLocal<C> b, ExpVector e, SolvableLocal<C> c,
554                    ExpVector f) {
555        if (b == null || b.isZERO()) {
556            return ring.getZERO();
557        }
558        if (c == null || c.isZERO()) {
559            return ring.getZERO();
560        }
561        if (b.isONE() && e.isZERO() && c.isONE() && f.isZERO()) {
562            return this;
563        }
564        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
565        LocalSolvablePolynomial<C> Dp = new LocalSolvablePolynomial<C>(ring, c, f);
566        return multiply(Cp, Dp);
567    }
568
569
570    /**
571     * LocalSolvablePolynomial multiplication. Left product with ring element
572     * and exponent vector.
573     * @param b coefficient polynomial.
574     * @param e exponent.
575     * @return b x<sup>e</sup> * this, where * denotes solvable multiplication.
576     */
577    @Override
578    public LocalSolvablePolynomial<C> multiplyLeft(SolvableLocal<C> b, ExpVector e) {
579        if (b == null || b.isZERO()) {
580            return ring.getZERO();
581        }
582        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
583        return Cp.multiply(this);
584    }
585
586
587    /**
588     * LocalSolvablePolynomial multiplication. Left product with exponent
589     * vector.
590     * @param e exponent.
591     * @return x<sup>e</sup> * this, where * denotes solvable multiplication.
592     */
593    @Override
594    public LocalSolvablePolynomial<C> multiplyLeft(ExpVector e) {
595        if (e == null || e.isZERO()) {
596            return this;
597        }
598        SolvableLocal<C> b = ring.getONECoefficient();
599        LocalSolvablePolynomial<C> Cp = new LocalSolvablePolynomial<C>(ring, b, e);
600        return Cp.multiply(this);
601    }
602
603
604    /**
605     * LocalSolvablePolynomial multiplication. Left product with coefficient
606     * ring element.
607     * @param b coefficient polynomial.
608     * @return b*this, where * is coefficient multiplication.
609     */
610    @Override
611    public LocalSolvablePolynomial<C> multiplyLeft(SolvableLocal<C> b) {
612        LocalSolvablePolynomial<C> Cp = ring.getZERO().copy();
613        if (b == null || b.isZERO()) {
614            return Cp;
615        }
616        Map<ExpVector, SolvableLocal<C>> Cm = Cp.val; //getMap();
617        Map<ExpVector, SolvableLocal<C>> Am = val;
618        SolvableLocal<C> c;
619        for (Map.Entry<ExpVector, SolvableLocal<C>> y : Am.entrySet()) {
620            ExpVector e = y.getKey();
621            SolvableLocal<C> a = y.getValue();
622            c = b.multiply(a);
623            if (!c.isZERO()) {
624                Cm.put(e, c);
625            }
626        }
627        return Cp;
628    }
629
630
631    /**
632     * LocalSolvablePolynomial multiplication. Left product with 'monomial'.
633     * @param m 'monomial'.
634     * @return m * this, where * denotes solvable multiplication.
635     */
636    @Override
637    public LocalSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableLocal<C>> m) {
638        if (m == null) {
639            return ring.getZERO();
640        }
641        return multiplyLeft(m.getValue(), m.getKey());
642    }
643
644
645    /**
646     * LocalSolvablePolynomial multiplication. Product with 'monomial'.
647     * @param m 'monomial'.
648     * @return this * m, where * denotes solvable multiplication.
649     */
650    @Override
651    public LocalSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableLocal<C>> m) {
652        if (m == null) {
653            return ring.getZERO();
654        }
655        return multiply(m.getValue(), m.getKey());
656    }
657
658
659    /**
660     * LocalSolvablePolynomial multiplication. Left product with coefficient
661     * ring element.
662     * @param f exponent vector.
663     * @return B*f, where * is commutative multiplication.
664     */
665    protected LocalSolvablePolynomial<C> shift(ExpVector f) {
666        LocalSolvablePolynomial<C> C = ring.getZERO().copy();
667        if (this.isZERO()) {
668            return C;
669        }
670        if (f == null || f.isZERO()) {
671            return this;
672        }
673        Map<ExpVector, SolvableLocal<C>> Cm = C.val;
674        Map<ExpVector, SolvableLocal<C>> Bm = this.val;
675        for (Map.Entry<ExpVector, SolvableLocal<C>> y : Bm.entrySet()) {
676            ExpVector e = y.getKey();
677            SolvableLocal<C> a = y.getValue();
678            ExpVector d = e.sum(f);
679            if (!a.isZERO()) {
680                Cm.put(d, a);
681            }
682        }
683        return C;
684    }
685
686}