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