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