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