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