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