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