001/*
002 * $Id: GenSolvablePolynomial.java 5836 2018-05-20 12:37:32Z 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.NotInvertibleException;
015import edu.jas.structure.RingElem;
016
017
018/**
019 * GenSolvablePolynomial generic solvable polynomials implementing RingElem.
020 * n-variate ordered solvable polynomials over C. Objects of this class are
021 * intended to be immutable. The implementation is based on TreeMap respectively
022 * SortedMap from exponents to coefficients by extension of GenPolybomial. Only
023 * the coefficients are modeled with generic types, the exponents are fixed to
024 * ExpVector with long entries (this will eventually be changed in the future).
025 * @param <C> coefficient type
026 * @author Heinz Kredel
027 */
028
029public class GenSolvablePolynomial<C extends RingElem<C>> extends GenPolynomial<C> {
030
031
032    //not possible: implements RingElem< GenSolvablePolynomial<C> > {
033
034
035    private static final Logger logger = Logger.getLogger(GenSolvablePolynomial.class);
036
037
038    private static final boolean debug = false; //logger.isDebugEnabled();
039
040
041    /**
042     * The factory for the solvable polynomial ring. Hides super.ring.
043     */
044    public final GenSolvablePolynomialRing<C> ring;
045
046
047    /**
048     * Constructor for zero GenSolvablePolynomial.
049     * @param r solvable polynomial ring factory.
050     */
051    public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r) {
052        super(r);
053        ring = r;
054    }
055
056
057    /**
058     * Constructor for GenSolvablePolynomial.
059     * @param r solvable polynomial ring factory.
060     * @param c coefficient.
061     * @param e exponent.
062     */
063    public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, C c, ExpVector e) {
064        this(r);
065        if (c != null && !c.isZERO()) {
066            val.put(e, c);
067        }
068    }
069
070
071    /**
072     * Constructor for GenSolvablePolynomial.
073     * @param r solvable polynomial ring factory.
074     * @param c coefficient.
075     */
076    public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, C c) {
077        this(r, c, r.evzero);
078    }
079
080
081    /**
082     * Constructor for GenSolvablePolynomial.
083     * @param r solvable polynomial ring factory.
084     * @param v the SortedMap of some other (solvable) polynomial.
085     */
086    protected GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, SortedMap<ExpVector, C> v) {
087        this(r);
088        if (v.size() > 0) {
089            GenPolynomialRing.creations++;
090            val.putAll(v); // assume val is empty and no zero coefficients in v
091        }
092    }
093
094
095    /**
096     * Get the corresponding element factory.
097     * @return factory for this Element.
098     * @see edu.jas.structure.Element#factory()
099     */
100    @Override
101    public GenSolvablePolynomialRing<C> factory() {
102        return ring;
103    }
104
105
106    /**
107     * Clone this GenSolvablePolynomial.
108     * @see java.lang.Object#clone()
109     */
110    @Override
111    public GenSolvablePolynomial<C> copy() {
112        return new GenSolvablePolynomial<C>(ring, this.val);
113    }
114
115
116    /**
117     * Comparison with any other object.
118     * @see java.lang.Object#equals(java.lang.Object)
119     */
120    @Override
121    public boolean equals(Object B) {
122        if (!(B instanceof GenSolvablePolynomial)) {
123            return false;
124        }
125        return super.equals(B);
126    }
127
128
129    /**
130     * GenSolvablePolynomial multiplication.
131     * @param Bp GenSolvablePolynomial.
132     * @return this*Bp, where * denotes solvable multiplication.
133     */
134    // cannot @Override
135    @SuppressWarnings({ "cast", "unchecked" })
136    public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> Bp) {
137        if (Bp == null || Bp.isZERO()) {
138            return ring.getZERO();
139        }
140        if (this.isZERO()) {
141            return this;
142        }
143        assert (ring.nvar == Bp.ring.nvar);
144        if (debug) {
145            logger.debug("ring = " + ring);
146        }
147        if (this instanceof RecSolvablePolynomial && Bp instanceof RecSolvablePolynomial) {
148            //throw new RuntimeException("wrong method dispatch in JRE ");
149            logger.info("warn: wrong method dispatch in JRE Rec.multiply(Rec Bp) - trying to fix");
150            RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C>
151            RecSolvablePolynomial Sp = (RecSolvablePolynomial) Bp;
152            return T.multiply(Sp);
153        }
154        if (this instanceof QLRSolvablePolynomial && Bp instanceof QLRSolvablePolynomial) {
155            //throw new RuntimeException("wrong method dispatch in JRE ");
156            logger.info("warn: wrong method dispatch in JRE QLR.multiply(QLR Bp) - trying to fix");
157            QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C>
158            QLRSolvablePolynomial Sp = (QLRSolvablePolynomial) Bp;
159            return T.multiply(Sp);
160        }
161        final boolean commute = ring.table.isEmpty();
162        GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); // needed for doPutToMap and doAddTo
163        ExpVector Z = ring.evzero;
164
165        GenSolvablePolynomial<C> C1 = null;
166        GenSolvablePolynomial<C> C2 = null;
167        Map<ExpVector, C> A = val;
168        Map<ExpVector, C> B = Bp.val;
169        Set<Map.Entry<ExpVector, C>> Bk = B.entrySet();
170        for (Map.Entry<ExpVector, C> y : A.entrySet()) {
171            C a = y.getValue();
172            ExpVector e = y.getKey();
173            if (debug)
174                logger.debug("e = " + e);
175            int[] ep = e.dependencyOnVariables();
176            int el1 = ring.nvar + 1;
177            if (ep.length > 0) {
178                el1 = ep[0];
179            }
180            int el1s = ring.nvar + 1 - el1;
181            for (Map.Entry<ExpVector, C> x : Bk) {
182                C b = x.getValue();
183                ExpVector f = x.getKey();
184                if (debug)
185                    logger.debug("f = " + f);
186                int[] fp = f.dependencyOnVariables();
187                int fl1 = 0;
188                if (fp.length > 0) {
189                    fl1 = fp[fp.length - 1];
190                }
191                int fl1s = ring.nvar + 1 - fl1;
192                if (debug) {
193                    logger.debug("el1s = " + el1s + " fl1s = " + fl1s);
194                }
195                GenSolvablePolynomial<C> Cs = null;
196                if (commute || el1s <= fl1s) { // symmetric
197                    ExpVector g = e.sum(f);
198                    Cs = ring.valueOf(g); // symmetric! 
199                    //no: Cs = new GenSolvablePolynomial<C>(ring, one, g); 
200                    //System.out.println("Cs(sym) = " + Cs + ", g = " + g);
201                } else { // unsymmetric
202                    // split e = e1 * e2, f = f1 * f2
203                    ExpVector e1 = e.subst(el1, 0);
204                    ExpVector e2 = Z.subst(el1, e.getVal(el1));
205                    ExpVector e4;
206                    ExpVector f1 = f.subst(fl1, 0);
207                    ExpVector f2 = Z.subst(fl1, f.getVal(fl1));
208                    TableRelation<C> rel = ring.table.lookup(e2, f2);
209                    //logger.info("relation = " + rel);
210                    Cs = rel.p; // do not clone() 
211                    if (rel.f != null) {
212                        C2 = ring.valueOf(rel.f); 
213                        Cs = Cs.multiply(C2);
214                        if (rel.e == null) {
215                            e4 = e2;
216                        } else {
217                            e4 = e2.subtract(rel.e);
218                        }
219                        ring.table.update(e4, f2, Cs);
220                    }
221                    if (rel.e != null) {
222                        C1 = ring.valueOf(rel.e); 
223                        Cs = C1.multiply(Cs);
224                        ring.table.update(e2, f2, Cs);
225                    }
226                    if (!f1.isZERO()) {
227                        C2 = ring.valueOf(f1); 
228                        Cs = Cs.multiply(C2);
229                        //ring.table.update(?,f1,Cs)
230                    }
231                    if (!e1.isZERO()) {
232                        C1 = ring.valueOf(e1); 
233                        Cs = C1.multiply(Cs);
234                        //ring.table.update(e1,?,Cs)
235                    }
236                }
237                //System.out.println("Cs = " + Cs + ", a = " + a + ", b = " + b);
238                Cs = Cs.multiply(a, b); // now non-symmetric // Cs.multiply(c); is symmetric!
239                Cp.doAddTo(Cs);
240            }
241        }
242        return Cp;
243    }
244
245
246    /**
247     * GenSolvablePolynomial left and right multiplication. Product with two
248     * polynomials.
249     * @param S GenSolvablePolynomial.
250     * @param T GenSolvablePolynomial.
251     * @return S*this*T.
252     */
253    // new method, @NoOverride
254    public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> S, GenSolvablePolynomial<C> T) {
255        if (S.isZERO() || T.isZERO() || this.isZERO()) {
256            return ring.getZERO();
257        }
258        if (S.isONE()) {
259            return multiply(T);
260        }
261        if (T.isONE()) {
262            return S.multiply(this);
263        }
264        return S.multiply(this).multiply(T);
265    }
266
267
268    /**
269     * GenSolvablePolynomial multiplication. Product with coefficient ring
270     * element.
271     * @param b coefficient.
272     * @return this*b, where * is coefficient multiplication.
273     */
274    @Override
275    @SuppressWarnings({ "cast", "unchecked" })
276    public GenSolvablePolynomial<C> multiply(C b) {
277        GenSolvablePolynomial<C> Cp = ring.getZERO();
278        if (b == null || b.isZERO()) {
279            return Cp;
280        }
281        if (this instanceof RecSolvablePolynomial && b instanceof GenSolvablePolynomial) {
282            //throw new RuntimeException("wrong method dispatch in JRE ");
283            logger.info("warn: wrong method dispatch in JRE Rec.multiply(b) - trying to fix");
284            RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C>
285            GenSolvablePolynomial Sp = (GenSolvablePolynomial) b;
286            return (GenSolvablePolynomial<C>) T.recMultiply(Sp);
287        }
288        if (this instanceof QLRSolvablePolynomial && b instanceof GenSolvablePolynomial) {
289            //throw new RuntimeException("wrong method dispatch in JRE ");
290            logger.info("warn: wrong method dispatch in JRE QLR.multiply(Bp) - trying to fix");
291            QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C>
292            GenSolvablePolynomial Sp = (GenSolvablePolynomial) b;
293            return (GenSolvablePolynomial<C>) T.multiply(Sp);
294        }
295        Cp = Cp.copy();
296        Map<ExpVector, C> Cm = Cp.val;
297        Map<ExpVector, C> Am = val;
298        for (Map.Entry<ExpVector, C> y : Am.entrySet()) {
299            ExpVector e = y.getKey();
300            C a = y.getValue();
301            C c = a.multiply(b);
302            if (!c.isZERO()) {
303                Cm.put(e, c);
304            }
305        }
306        return Cp;
307    }
308
309
310    /**
311     * GenSolvablePolynomial left and right multiplication. Product with
312     * coefficient ring element.
313     * @param b coefficient.
314     * @param c coefficient.
315     * @return b*this*c, where * is coefficient multiplication.
316     */
317    // new method, @NoOverride
318    @SuppressWarnings({ "cast", "unchecked" })
319    public GenSolvablePolynomial<C> multiply(C b, C c) {
320        GenSolvablePolynomial<C> Cp = ring.getZERO();
321        if (b == null || b.isZERO()) {
322            return Cp;
323        }
324        if (c == null || c.isZERO()) {
325            return Cp;
326        }
327        if (this instanceof RecSolvablePolynomial && b instanceof GenSolvablePolynomial
328                        && c instanceof GenSolvablePolynomial) {
329            //throw new RuntimeException("wrong method dispatch in JRE ");
330            logger.info("warn: wrong method dispatch in JRE Rec.multiply(b,c) - trying to fix");
331            RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C>
332            GenSolvablePolynomial Bp = (GenSolvablePolynomial) b;
333            GenSolvablePolynomial Dp = (GenSolvablePolynomial) c;
334            return (GenSolvablePolynomial<C>) T.multiply(Bp, Dp);
335        }
336        if (this instanceof QLRSolvablePolynomial && b instanceof GenSolvablePolynomial
337                        && c instanceof GenSolvablePolynomial) {
338            //throw new RuntimeException("wrong method dispatch in JRE ");
339            logger.info("warn: wrong method dispatch in JRE QLR.multiply(b,c) - trying to fix");
340            QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C>
341            GenSolvablePolynomial Bp = (GenSolvablePolynomial) b;
342            GenSolvablePolynomial Dp = (GenSolvablePolynomial) c;
343            return (GenSolvablePolynomial<C>) T.multiply(Bp, Dp);
344        }
345        Cp = Cp.copy();
346        Map<ExpVector, C> Cm = Cp.val;
347        Map<ExpVector, C> Am = val;
348        for (Map.Entry<ExpVector, C> y : Am.entrySet()) {
349            ExpVector e = y.getKey();
350            C a = y.getValue();
351            C d = b.multiply(a).multiply(c);
352            if (!d.isZERO()) {
353                Cm.put(e, d);
354            }
355        }
356        return Cp;
357    }
358
359
360    /**
361     * GenSolvablePolynomial multiplication. Product with exponent vector.
362     * @param e exponent.
363     * @return this * x<sup>e</sup>, where * denotes solvable multiplication.
364     */
365    @Override
366    public GenSolvablePolynomial<C> multiply(ExpVector e) {
367        if (e == null || e.isZERO()) {
368            return this;
369        }
370        C b = ring.getONECoefficient();
371        return multiply(b, e);
372    }
373
374
375    /**
376     * GenSolvablePolynomial left and right multiplication. Product with
377     * exponent vector.
378     * @param e exponent.
379     * @param f exponent.
380     * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable
381     *         multiplication.
382     */
383    // new method, @NoOverride
384    public GenSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) {
385        if (e == null || e.isZERO()) {
386            return this;
387        }
388        if (f == null || f.isZERO()) {
389            return this;
390        }
391        C b = ring.getONECoefficient();
392        return multiply(b, e, b, f);
393    }
394
395
396    /**
397     * GenSolvablePolynomial multiplication. Product with ring element and
398     * exponent vector.
399     * @param b coefficient.
400     * @param e exponent.
401     * @return this * b x<sup>e</sup>, where * denotes solvable multiplication.
402     */
403    @Override
404    public GenSolvablePolynomial<C> multiply(C b, ExpVector e) {
405        if (b == null || b.isZERO()) {
406            return ring.getZERO();
407        }
408        GenSolvablePolynomial<C> Cp = ring.valueOf(b, e); //new GenSolvablePolynomial<C>(ring, b, e);
409        return multiply(Cp);
410    }
411
412
413    /**
414     * GenSolvablePolynomial left and right multiplication. Product with ring
415     * element and exponent vector.
416     * @param b coefficient.
417     * @param e exponent.
418     * @param c coefficient.
419     * @param f exponent.
420     * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes
421     *         solvable multiplication.
422     */
423    // new method, @NoOverride
424    public GenSolvablePolynomial<C> multiply(C b, ExpVector e, C c, ExpVector f) {
425        if (b == null || b.isZERO()) {
426            return ring.getZERO();
427        }
428        if (c == null || c.isZERO()) {
429            return ring.getZERO();
430        }
431        GenSolvablePolynomial<C> Cp = ring.valueOf(b, e); //new GenSolvablePolynomial<C>(ring, b, e);
432        GenSolvablePolynomial<C> Dp = ring.valueOf(c, f); //new GenSolvablePolynomial<C>(ring, c, f);
433        return multiply(Cp, Dp);
434    }
435
436
437    /**
438     * GenSolvablePolynomial multiplication. Left product with ring element and
439     * exponent vector.
440     * @param b coefficient.
441     * @param e exponent.
442     * @return b x<sup>e</sup> * this, where * denotes solvable multiplication.
443     */
444    public GenSolvablePolynomial<C> multiplyLeft(C b, ExpVector e) {
445        if (b == null || b.isZERO()) {
446            return ring.getZERO();
447        }
448        GenSolvablePolynomial<C> Cp = ring.valueOf(b, e);
449        return Cp.multiply(this);
450    }
451
452
453    /**
454     * GenSolvablePolynomial multiplication. Left product with exponent vector.
455     * @param e exponent.
456     * @return x<sup>e</sup> * this, where * denotes solvable multiplication.
457     */
458    public GenSolvablePolynomial<C> multiplyLeft(ExpVector e) {
459        if (e == null || e.isZERO()) {
460            return this;
461        }
462        C b = ring.getONECoefficient();
463        return multiplyLeft(b, e);
464    }
465
466
467    /**
468     * GenSolvablePolynomial multiplication. Left product with coefficient ring
469     * element.
470     * @param b coefficient.
471     * @return b*this, where * is coefficient multiplication.
472     */
473    @Override
474    public GenSolvablePolynomial<C> multiplyLeft(C b) {
475        GenSolvablePolynomial<C> Cp = ring.getZERO();
476        if (b == null || b.isZERO()) {
477            return Cp;
478        }
479        Cp = Cp.copy();
480        Map<ExpVector, C> Cm = Cp.val; //getMap();
481        Map<ExpVector, C> Am = val;
482        for (Map.Entry<ExpVector, C> y : Am.entrySet()) {
483            ExpVector e = y.getKey();
484            C a = y.getValue();
485            C c = b.multiply(a);
486            if (!c.isZERO()) {
487                Cm.put(e, c);
488            }
489        }
490        return Cp;
491    }
492
493
494    /**
495     * GenSolvablePolynomial multiplication. Left product with 'monomial'.
496     * @param m 'monomial'.
497     * @return m * this, where * denotes solvable multiplication.
498     */
499    // new method, @NoOverride
500    public GenSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, C> m) {
501        if (m == null) {
502            return ring.getZERO();
503        }
504        return multiplyLeft(m.getValue(), m.getKey());
505    }
506
507
508    /**
509     * GenSolvablePolynomial multiplication. Product with 'monomial'.
510     * @param m 'monomial'.
511     * @return this * m, where * denotes solvable multiplication.
512     */
513    @Override
514    public GenSolvablePolynomial<C> multiply(Map.Entry<ExpVector, C> m) {
515        if (m == null) {
516            return ring.getZERO();
517        }
518        return multiply(m.getValue(), m.getKey());
519    }
520
521
522    /**
523     * GenSolvablePolynomial subtract a multiple.
524     * @param a coefficient.
525     * @param S GenSolvablePolynomial.
526     * @return this - a * S.
527     */
528    public GenSolvablePolynomial<C> subtractMultiple(C a, GenSolvablePolynomial<C> S) {
529        if (a == null || a.isZERO()) {
530            return this;
531        }
532        if (S == null || S.isZERO()) {
533            return this;
534        }
535        if (this.isZERO()) {
536            return S.multiplyLeft(a.negate());
537        }
538        assert (ring.nvar == S.ring.nvar);
539        GenSolvablePolynomial<C> n = this.copy();
540        SortedMap<ExpVector, C> nv = n.val;
541        SortedMap<ExpVector, C> sv = S.val;
542        for (Map.Entry<ExpVector, C> me : sv.entrySet()) {
543            ExpVector f = me.getKey();
544            C y = me.getValue(); // assert y != null
545            y = a.multiply(y);
546            C x = nv.get(f);
547            if (x != null) {
548                x = x.subtract(y);
549                if (!x.isZERO()) {
550                    nv.put(f, x);
551                } else {
552                    nv.remove(f);
553                }
554            } else if (!y.isZERO()) {
555                nv.put(f, y.negate());
556            }
557        }
558        return n;
559    }
560
561
562    /**
563     * GenSolvablePolynomial subtract a multiple.
564     * @param a coefficient.
565     * @param e exponent.
566     * @param S GenSolvablePolynomial.
567     * @return this - a * x<sup>e</sup> * S.
568     */
569    public GenSolvablePolynomial<C> subtractMultiple(C a, ExpVector e, GenSolvablePolynomial<C> S) {
570        if (a == null || a.isZERO()) {
571            return this;
572        }
573        if (S == null || S.isZERO()) {
574            return this;
575        }
576        if (this.isZERO()) {
577            return S.multiplyLeft(a.negate(), e);
578        }
579        assert (ring.nvar == S.ring.nvar);
580        GenSolvablePolynomial<C> n = this.copy();
581        SortedMap<ExpVector, C> nv = n.val;
582        GenSolvablePolynomial<C> s = S.multiplyLeft(e);
583        SortedMap<ExpVector, C> sv = s.val;
584        for (Map.Entry<ExpVector, C> me : sv.entrySet()) {
585            ExpVector f = me.getKey();
586            //f = e.sum(f);
587            C y = me.getValue(); // assert y != null
588            y = a.multiply(y);
589            C x = nv.get(f);
590            if (x != null) {
591                x = x.subtract(y);
592                if (!x.isZERO()) {
593                    nv.put(f, x);
594                } else {
595                    nv.remove(f);
596                }
597            } else if (!y.isZERO()) {
598                nv.put(f, y.negate());
599            }
600        }
601        return n;
602    }
603
604
605    /**
606     * GenSolvablePolynomial scale and subtract a multiple.
607     * @param b scale factor.
608     * @param a coefficient.
609     * @param S GenSolvablePolynomial.
610     * @return b * this - a * S.
611     */
612    public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, C a, GenSolvablePolynomial<C> S) {
613        if (a == null || S == null) {
614            return this.multiplyLeft(b);
615        }
616        if (a.isZERO() || S.isZERO()) {
617            return this.multiplyLeft(b);
618        }
619        if (this.isZERO() || b == null || b.isZERO()) {
620            return S.multiplyLeft(a.negate());
621        }
622        if (b.isONE()) {
623            return subtractMultiple(a, S);
624        }
625        assert (ring.nvar == S.ring.nvar);
626        GenSolvablePolynomial<C> n = this.multiplyLeft(b);
627        SortedMap<ExpVector, C> nv = n.val;
628        SortedMap<ExpVector, C> sv = S.val;
629        for (Map.Entry<ExpVector, C> me : sv.entrySet()) {
630            ExpVector f = me.getKey();
631            //f = e.sum(f);
632            C y = me.getValue(); // assert y != null
633            y = a.multiply(y); // now y can be zero
634            C x = nv.get(f);
635            if (x != null) {
636                x = x.subtract(y);
637                if (!x.isZERO()) {
638                    nv.put(f, x);
639                } else {
640                    nv.remove(f);
641                }
642            } else if (!y.isZERO()) {
643                nv.put(f, y.negate());
644            }
645        }
646        return n;
647    }
648
649
650    /**
651     * GenSolvablePolynomial scale and subtract a multiple.
652     * @param b scale factor.
653     * @param a coefficient.
654     * @param e exponent.
655     * @param S GenSolvablePolynomial.
656     * @return b * this - a * x<sup>e</sup> * S.
657     */
658    public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, C a, ExpVector e, GenSolvablePolynomial<C> S) {
659        if (a == null || S == null) {
660            return this.multiplyLeft(b);
661        }
662        if (a.isZERO() || S.isZERO()) {
663            return this.multiplyLeft(b);
664        }
665        if (this.isZERO() || b == null || b.isZERO()) {
666            return S.multiplyLeft(a.negate(), e);
667        }
668        if (b.isONE()) {
669            return subtractMultiple(a, e, S);
670        }
671        assert (ring.nvar == S.ring.nvar);
672        GenSolvablePolynomial<C> n = this.multiplyLeft(b);
673        SortedMap<ExpVector, C> nv = n.val;
674        GenSolvablePolynomial<C> s = S.multiplyLeft(e);
675        SortedMap<ExpVector, C> sv = s.val;
676        for (Map.Entry<ExpVector, C> me : sv.entrySet()) {
677            ExpVector f = me.getKey();
678            //f = e.sum(f);
679            C y = me.getValue(); // assert y != null
680            y = a.multiply(y); // now y can be zero
681            C x = nv.get(f);
682            if (x != null) {
683                x = x.subtract(y);
684                if (!x.isZERO()) {
685                    nv.put(f, x);
686                } else {
687                    nv.remove(f);
688                }
689            } else if (!y.isZERO()) {
690                nv.put(f, y.negate());
691            }
692        }
693        return n;
694    }
695
696
697    /**
698     * GenSolvablePolynomial scale and subtract a multiple.
699     * @param b scale factor.
700     * @param g scale exponent.
701     * @param a coefficient.
702     * @param e exponent.
703     * @param S GenSolvablePolynomial.
704     * @return a * x<sup>g</sup> * this - a * x<sup>e</sup> * S.
705     */
706    public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, ExpVector g, C a, ExpVector e,
707                    GenSolvablePolynomial<C> S) {
708        if (a == null || S == null) {
709            return this.multiplyLeft(b, g);
710        }
711        if (a.isZERO() || S.isZERO()) {
712            return this.multiplyLeft(b, g);
713        }
714        if (this.isZERO() || b == null || b.isZERO()) {
715            return S.multiplyLeft(a.negate(), e);
716        }
717        if (b.isONE() && g.isZERO()) {
718            return subtractMultiple(a, e, S);
719        }
720        assert (ring.nvar == S.ring.nvar);
721        GenSolvablePolynomial<C> n = this.multiplyLeft(b, g);
722        SortedMap<ExpVector, C> nv = n.val;
723        GenSolvablePolynomial<C> s = S.multiplyLeft(e);
724        SortedMap<ExpVector, C> sv = s.val;
725        for (Map.Entry<ExpVector, C> me : sv.entrySet()) {
726            ExpVector f = me.getKey();
727            //f = e.sum(f);
728            C y = me.getValue(); // assert y != null
729            y = a.multiply(y); // y can be zero now
730            C x = nv.get(f);
731            if (x != null) {
732                x = x.subtract(y);
733                if (!x.isZERO()) {
734                    nv.put(f, x);
735                } else {
736                    nv.remove(f);
737                }
738            } else if (!y.isZERO()) {
739                nv.put(f, y.negate());
740            }
741        }
742        return n;
743    }
744
745
746    /**
747     * GenSolvablePolynomial left monic, i.e. leadingCoefficient == 1. If
748     * leadingCoefficient is not invertible returns this abs value.
749     * @return monic(this).
750     */
751    @Override
752    public GenSolvablePolynomial<C> monic() {
753        if (this.isZERO()) {
754            return this;
755        }
756        C lc = leadingBaseCoefficient();
757        if (!lc.isUnit()) {
758            return (GenSolvablePolynomial<C>)this.abs();
759        }
760        try {
761            C lm = lc.inverse();
762            //System.out.println("lm = "+lm);
763            return (GenSolvablePolynomial<C>)multiplyLeft(lm).abs();
764        } catch (NotInvertibleException e) {
765            logger.info("monic not invertible " + lc);
766            //e.printStackTrace();
767        }
768        return this;
769    }
770
771
772    /**
773     * GenSolvablePolynomial left division. Fails, if exact
774     * division by leading base coefficient is not possible. Meaningful only for
775     * univariate polynomials over fields, but works in any case.
776     * @param S nonzero GenSolvablePolynomial with invertible leading
777     *            coefficient.
778     * @return quotient with this = quotient * S + remainder and
779     *         deg(remainder) &lt; deg(S) or remiander = 0.
780     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
781     */
782    // cannot @Override
783    @SuppressWarnings({ "unchecked" })
784    public GenSolvablePolynomial<C> divide(GenSolvablePolynomial<C> S) {
785        return quotientRemainder(S)[0];
786    }
787
788
789    /**
790     * GenSolvablePolynomial remainder by left division. Fails, if exact
791     * division by leading base coefficient is not possible. Meaningful only for
792     * univariate polynomials over fields, but works in any case.
793     * @param S nonzero GenSolvablePolynomial with invertible leading
794     *            coefficient.
795     * @return remainder with this = quotient * S + remainder and
796     *         deg(remainder) &lt; deg(S) or remiander = 0.
797     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
798     */
799    // cannot @Override
800    @SuppressWarnings({ "unchecked" })
801    public GenSolvablePolynomial<C> remainder(GenSolvablePolynomial<C> S) {
802        return quotientRemainder(S)[1];
803    }
804
805
806    /**
807     * GenSolvablePolynomial left division with remainder. Fails, if exact
808     * division by leading base coefficient is not possible. Meaningful only for
809     * univariate polynomials over fields, but works in any case.
810     * @param S nonzero GenSolvablePolynomial with invertible leading
811     *            coefficient.
812     * @return [ quotient , remainder ] with this = quotient * S + remainder and
813     *         deg(remainder) &lt; deg(S) or remiander = 0.
814     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
815     */
816    // cannot @Override
817    @SuppressWarnings({ "unchecked" })
818    public GenSolvablePolynomial<C>[] quotientRemainder(GenSolvablePolynomial<C> S) {
819        if (S == null || S.isZERO()) {
820            throw new ArithmeticException("division by zero");
821        }
822        C c = S.leadingBaseCoefficient();
823        if (!c.isUnit()) {
824            throw new ArithmeticException("lbcf not invertible " + c);
825        }
826        C ci = c.inverse();
827        assert (ring.nvar == S.ring.nvar);
828        ExpVector e = S.leadingExpVector();
829        GenSolvablePolynomial<C> h;
830        GenSolvablePolynomial<C> q = ring.getZERO().copy();
831        GenSolvablePolynomial<C> r = this.copy();
832        while (!r.isZERO()) {
833            ExpVector f = r.leadingExpVector();
834            if (f.multipleOf(e)) {
835                C a = r.leadingBaseCoefficient();
836                //System.out.println("FDQR: f = " + f + ", a = " + a);
837                f = f.subtract(e);
838                //a = ci.multiply(a); // multiplyLeft
839                a = a.multiply(ci); // this is correct!
840                q = (GenSolvablePolynomial<C>) q.sum(a, f);
841                h = S.multiplyLeft(a, f);
842                if (!h.leadingBaseCoefficient().equals(r.leadingBaseCoefficient())) {
843                    throw new RuntimeException("something is wrong: r = " + r + ", h = " + h);
844                }
845                r = (GenSolvablePolynomial<C>) r.subtract(h);
846            } else {
847                break;
848            }
849        }
850        GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2];
851        ret[0] = q;
852        ret[1] = r;
853        return ret;
854    }
855
856
857    /**
858     * GenSolvablePolynomial right division. Fails, if exact
859     * division by leading base coefficient is not possible. Meaningful only for
860     * univariate polynomials over fields, but works in any case.
861     * @param S nonzero GenSolvablePolynomial with invertible leading
862     *            coefficient.
863     * @return quotient with this = S * quotient + remainder and
864     *         deg(remainder) &lt; deg(S) or remiander = 0.
865     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
866     */
867    @SuppressWarnings({ "unchecked" })
868    public GenSolvablePolynomial<C> rightDivide(GenSolvablePolynomial<C> S) {
869        return rightQuotientRemainder(S)[0];
870    }
871
872
873    /**
874     * GenSolvablePolynomial remainder by right division. Fails, if exact
875     * division by leading base coefficient is not possible. Meaningful only for
876     * univariate polynomials over fields, but works in any case.
877     * @param S nonzero GenSolvablePolynomial with invertible leading
878     *            coefficient.
879     * @return remainder with this = S * quotient + remainder and
880     *         deg(remainder) &lt; deg(S) or remiander = 0.
881     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
882     */
883    @SuppressWarnings({ "unchecked" })
884    public GenSolvablePolynomial<C> rightRemainder(GenSolvablePolynomial<C> S) {
885        return rightQuotientRemainder(S)[1];
886    }
887
888
889    /**
890     * GenSolvablePolynomial right division with remainder. Fails, if exact
891     * division by leading base coefficient is not possible. Meaningful only for
892     * univariate polynomials over fields, but works in any case.
893     * @param S nonzero GenSolvablePolynomial with invertible leading
894     *            coefficient.
895     * @return [ quotient , remainder ] with this = S * quotient + remainder and
896     *         deg(remainder) &lt; deg(S) or remainder = 0.
897     * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
898     */
899    @SuppressWarnings({ "unchecked" })
900    public GenSolvablePolynomial<C>[] rightQuotientRemainder(GenSolvablePolynomial<C> S) {
901        if (S == null || S.isZERO()) {
902            throw new ArithmeticException("division by zero");
903        }
904        C c = S.leadingBaseCoefficient();
905        if (!c.isUnit()) {
906            throw new ArithmeticException("lbcf not invertible " + c);
907        }
908        C ci = c.inverse();
909        assert (ring.nvar == S.ring.nvar);
910        ExpVector e = S.leadingExpVector();
911        GenSolvablePolynomial<C> h;
912        GenSolvablePolynomial<C> q = ring.getZERO().copy();
913        GenSolvablePolynomial<C> r = this.copy();
914        while (!r.isZERO()) {
915            ExpVector f = r.leadingExpVector();
916            if (f.multipleOf(e)) {
917                C a = r.leadingBaseCoefficient();
918                //System.out.println("FDQR: f = " + f + ", a = " + a);
919                f = f.subtract(e);
920                //a = a.multiplyLeft(ci); // not existing
921                a = ci.multiply(a); // this is correct!
922                q = (GenSolvablePolynomial<C>) q.sum(a, f);
923                h = S.multiply(a, f);
924                if (!h.leadingBaseCoefficient().equals(r.leadingBaseCoefficient())) {
925                    throw new RuntimeException("something is wrong: r = " + r + ", h = " + h);
926                }
927                r = (GenSolvablePolynomial<C>) r.subtract(h);
928            } else {
929                break;
930            }
931        }
932        GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2];
933        ret[0] = q;
934        ret[1] = r;
935        return ret;
936    }
937
938
939    /**
940     * RecSolvablePolynomial right coefficients from left coefficients.
941     * <b>Note:</b> R is represented as a polynomial with left coefficients, the
942     * implementation can at the moment not distinguish between left and right
943     * coefficients.
944     * @return R = sum( X<sup>i</sup> b<sub>i</sub> ), with P =
945     *         sum(a<sub>i</sub> X<sup>i</sup> ) and eval(sum(X<sup>i</sup>
946     *         b<sub>i</sub>)) == sum(a<sub>i</sub> X<sup>i</sup>)
947     */
948    @SuppressWarnings({ "unchecked" })
949    public GenSolvablePolynomial<C> rightRecursivePolynomial() {
950        if (this.isONE() || this.isZERO()) {
951            return this;
952        }
953        if (!(this instanceof RecSolvablePolynomial)) {
954            return this;
955        }
956        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
957        if (rfac.coeffTable.isEmpty()) {
958            return this;
959        }
960        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this;
961        RecSolvablePolynomial<C> R = (RecSolvablePolynomial<C>) p.rightRecursivePolynomial();
962        return (GenSolvablePolynomial<C>) R;
963    }
964
965
966    /**
967     * Evaluate RecSolvablePolynomial as right coefficients polynomial.
968     * <b>Note:</b> R is represented as a polynomial with left coefficients, the
969     * implementation can at the moment not distinguish between left and right
970     * coefficients.
971     * @return this as evaluated polynomial R. R = sum( X<sup>i</sup>
972     *         b<sub>i</sub> ), this = sum(a<sub>i</sub> X<sup>i</sup> ) =
973     *         eval(sum(X<sup>i</sup> b<sub>i</sub>))
974     */
975    @SuppressWarnings({ "unchecked" })
976    public GenSolvablePolynomial<C> evalAsRightRecursivePolynomial() {
977        if (this.isONE() || this.isZERO()) {
978            return this;
979        }
980        if (!(this instanceof RecSolvablePolynomial)) {
981            return this;
982        }
983        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
984        if (rfac.coeffTable.isEmpty()) {
985            return this;
986        }
987        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this;
988        RecSolvablePolynomial<C> R = (RecSolvablePolynomial<C>) p.evalAsRightRecursivePolynomial();
989        return (GenSolvablePolynomial<C>) R;
990    }
991
992
993    /**
994     * Test RecSolvablePolynomial right coefficients polynomial. <b>Note:</b> R
995     * is represented as a polynomial with left coefficients, the implementation
996     * can at the moment not distinguish between left and right coefficients.
997     * @param R GenSolvablePolynomial with right coefficients.
998     * @return true, if R is polynomial with right coefficients of this. R =
999     *         sum( X<sup>i</sup> b<sub>i</sub> ), with this = sum(a<sub>i</sub>
1000     *         X<sup>i</sup> ) and eval(sum(X<sup>i</sup> b<sub>i</sub>)) ==
1001     *         sum(a<sub>i</sub> X<sup>i</sup>)
1002     */
1003    @SuppressWarnings({ "unchecked" })
1004    public boolean isRightRecursivePolynomial(GenSolvablePolynomial<C> R) {
1005        if (this.isZERO()) {
1006            return R.isZERO();
1007        }
1008        if (this.isONE()) {
1009            return R.isONE();
1010        }
1011        if (!(this instanceof RecSolvablePolynomial)) {
1012            return !(R instanceof RecSolvablePolynomial);
1013        }
1014        if (!(R instanceof RecSolvablePolynomial)) {
1015            return false;
1016        }
1017        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring;
1018        if (rfac.coeffTable.isEmpty()) {
1019            RecSolvablePolynomialRing<C> rf = (RecSolvablePolynomialRing<C>) R.ring;
1020            return rf.coeffTable.isEmpty();
1021        }
1022        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this;
1023        RecSolvablePolynomial<C> q = (RecSolvablePolynomial<C>) R;
1024        return p.isRightRecursivePolynomial(q);
1025    }
1026
1027}