001/*
002 * $Id$
003 */
004
005package edu.jas.fd;
006
007
008import java.util.ArrayList;
009import java.util.Collection;
010import java.util.List;
011import java.util.Map;
012
013import org.apache.logging.log4j.Logger;
014import org.apache.logging.log4j.LogManager; 
015
016import edu.jas.poly.ExpVector;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019import edu.jas.poly.GenSolvablePolynomial;
020import edu.jas.poly.GenSolvablePolynomialRing;
021import edu.jas.poly.RecSolvablePolynomial;
022import edu.jas.poly.RecSolvablePolynomialRing;
023import edu.jas.structure.GcdRingElem;
024import edu.jas.structure.RingFactory;
025
026
027/**
028 * Solvable polynomials factorization domain utilities, for example recursive
029 * pseudo remainder.
030 * @author Heinz Kredel
031 */
032
033public class FDUtil {
034
035
036    private static final Logger logger = LogManager.getLogger(FDUtil.class);
037
038
039    private static final boolean debug = true; //logger.isDebugEnabled();
040
041
042    private static final boolean info = logger.isInfoEnabled();
043
044
045    /**
046     * GenSolvablePolynomial sparse pseudo remainder for univariate polynomials.
047     * @param <C> coefficient type.
048     * @param P GenSolvablePolynomial.
049     * @param S nonzero GenSolvablePolynomial.
050     * @return remainder with ore(ldcf(S)<sup>m'</sup>) P = quotient * S +
051     *         remainder. m' &le; deg(P)-deg(S)
052     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
053     */
054    @SuppressWarnings("unchecked")
055    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> leftBaseSparsePseudoRemainder(
056                    GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
057        return leftBasePseudoQuotientRemainder(P, S)[1];
058    }
059
060
061    /**
062     * GenSolvablePolynomial sparse right pseudo remainder for univariate
063     * polynomials.
064     * @param <C> coefficient type.
065     * @param P GenSolvablePolynomial.
066     * @param S nonzero GenSolvablePolynomial.
067     * @return remainder with P ore(ldcf(S)<sup>m'</sup>) = S * quotient +
068     *         remainder. m' &le; deg(P)-deg(S)
069     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
070     */
071    @SuppressWarnings("unchecked")
072    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> rightBaseSparsePseudoRemainder(
073                    GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
074        return rightBasePseudoQuotientRemainder(P, S)[1];
075    }
076
077
078    /**
079     * GenSolvablePolynomial sparse pseudo quotient for univariate polynomials
080     * or exact division.
081     * @param <C> coefficient type.
082     * @param P GenSolvablePolynomial.
083     * @param S nonzero GenSolvablePolynomial.
084     * @return quotient with ore(ldcf(S)<sup>m'</sup>) P = quotient * S +
085     *         remainder. m' &le; deg(P)-deg(S)
086     * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial).
087     */
088    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> leftBasePseudoQuotient(
089                    GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
090        return leftBasePseudoQuotientRemainder(P, S)[0];
091    }
092
093
094    /**
095     * GenSolvablePolynomial right sparse pseudo quotient for univariate
096     * polynomials or exact division.
097     * @param <C> coefficient type.
098     * @param P GenSolvablePolynomial.
099     * @param S nonzero GenSolvablePolynomial.
100     * @return quotient with P ore(ldcf(S)<sup>m'</sup>) = S * quotient +
101     *         remainder. m' &le; deg(P)-deg(S)
102     * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial).
103     */
104    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> rightBasePseudoQuotient(
105                    GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
106        return rightBasePseudoQuotientRemainder(P, S)[0];
107    }
108
109
110    /**
111     * GenSolvablePolynomial sparse pseudo quotient and remainder for univariate
112     * polynomials or exact division.
113     * @param <C> coefficient type.
114     * @param P GenSolvablePolynomial.
115     * @param S nonzero GenSolvablePolynomial.
116     * @return [ quotient, remainder ] with ore(ldcf(S)<sup>m'</sup>) P =
117     *         quotient * S + remainder. m' &le; deg(P)-deg(S)
118     * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial).
119     */
120    @SuppressWarnings("unchecked")
121    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C>[] leftBasePseudoQuotientRemainder(
122                    final GenSolvablePolynomial<C> P, final GenSolvablePolynomial<C> S) {
123        if (S == null || S.isZERO()) {
124            throw new ArithmeticException(P.toString() + " division by zero " + S);
125        }
126        //if (S.ring.nvar != 1) { // ok if exact division
127        //    throw new RuntimeException("univariate polynomials only");
128        //}
129        GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2];
130        ret[0] = null;
131        ret[1] = null;
132        if (P.isZERO() || S.isONE()) {
133            ret[0] = P;
134            ret[1] = S.ring.getZERO();
135            return ret;
136        }
137        if (P instanceof RecSolvablePolynomial) {
138            RecSolvablePolynomial<C> Pr = (RecSolvablePolynomial) P;
139            if (!Pr.ring.coeffTable.isEmpty()) {
140                throw new UnsupportedOperationException(
141                                "RecSolvablePolynomial with twisted coeffs not supported");
142            }
143        }
144        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorFake<C>(P.ring.coFac);
145        final ExpVector e = S.leadingExpVector();
146        GenSolvablePolynomial<C> h;
147        GenSolvablePolynomial<C> r = P;
148        GenSolvablePolynomial<C> q = S.ring.getZERO().copy();
149        while (!r.isZERO()) {
150            ExpVector f = r.leadingExpVector();
151            if (f.multipleOf(e)) {
152                C a = r.leadingBaseCoefficient();
153                f = f.subtract(e);
154                h = S.multiplyLeft(f); // coeff a
155                C c = h.leadingBaseCoefficient();
156                // need ga, gc: ga a = gc c
157                C[] oc = fd.leftOreCond(a, c);
158                C ga = oc[0];
159                C gc = oc[1];
160                //logger.debug("left ga, gc   = " + ga + ", " + gc);
161                r = r.multiplyLeft(ga); // coeff ga a, exp f
162                h = h.multiplyLeft(gc); // coeff gc c, exp f
163                q = q.multiplyLeft(ga); // c
164                q = (GenSolvablePolynomial<C>) q.sum(gc, f); // a
165                r = (GenSolvablePolynomial<C>) r.subtract(h);
166            } else {
167                break;
168            }
169            //System.out.println("left q, r   = " + q + ", " + r);
170        }
171        int sp = P.signum();
172        int ss = S.signum();
173        int sq = q.signum();
174        // sp = ss * sq
175        if (sp != ss * sq) {
176            q = (GenSolvablePolynomial<C>) q.negate();
177            r = (GenSolvablePolynomial<C>) r.negate();
178        }
179        ret[0] = q;
180        ret[1] = r;
181        return ret;
182    }
183
184
185    /**
186     * GenSolvablePolynomial right sparse pseudo quotient and remainder
187     * for univariate polynomials or exact division.
188     * @param <C> coefficient type.
189     * @param P GenSolvablePolynomial.
190     * @param S nonzero GenSolvablePolynomial.
191     * @return [ quotient, remainder ] with P ore(ldcf(S)<sup>m'</sup>) = S *
192     *         quotient + remainder. m' &le; deg(P)-deg(S)
193     * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial).
194     */
195    @SuppressWarnings("unchecked")
196    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C>[] rightBasePseudoQuotientRemainder(
197                    GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
198        if (S == null || S.isZERO()) {
199            throw new ArithmeticException(P.toString() + " division by zero " + S);
200        }
201        //if (S.ring.nvar != 1) { // ok if exact division
202        //    throw new RuntimeException("univariate polynomials only");
203        //}
204        GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2];
205        ret[0] = null;
206        ret[1] = null;
207        if (P.isZERO() || S.isONE()) {
208            ret[0] = P;
209            ret[1] = S.ring.getZERO();
210            return ret;
211        }
212        if (P instanceof RecSolvablePolynomial) {
213            RecSolvablePolynomial<C> Pr = (RecSolvablePolynomial) P;
214            if (!Pr.ring.coeffTable.isEmpty()) {
215                throw new UnsupportedOperationException(
216                                "RecSolvablePolynomial with twisted coeffs not supported");
217            }
218        }
219        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorFake<C>(P.ring.coFac);
220        ExpVector e = S.leadingExpVector();
221        GenSolvablePolynomial<C> h;
222        GenSolvablePolynomial<C> r = P;
223        GenSolvablePolynomial<C> q = S.ring.getZERO().copy();
224        while (!r.isZERO()) {
225            ExpVector f = r.leadingExpVector();
226            if (f.multipleOf(e)) {
227                C a = r.leadingBaseCoefficient();
228                f = f.subtract(e);
229                h = S.multiply(f); // coeff a
230                C c = h.leadingBaseCoefficient();
231                // need ga, gc: a ga = c gc
232                C[] oc = fd.rightOreCond(a, c);
233                C ga = oc[0];
234                C gc = oc[1];
235                r = r.multiply(ga); // coeff a ga, exp f
236                h = h.multiply(gc); // coeff c gc, exp f wanted but is exp f * coeff c gc, okay for base
237                q = q.multiply(ga); // c
238                q = (GenSolvablePolynomial<C>) q.sum(gc, f); // a
239                r = (GenSolvablePolynomial<C>) r.subtract(h);
240            } else {
241                break;
242            }
243        }
244        int sp = P.signum();
245        int ss = S.signum();
246        int sq = q.signum();
247        // sp = ss * sq
248        if (sp != ss * sq) {
249            q = (GenSolvablePolynomial<C>) q.negate();
250            r = (GenSolvablePolynomial<C>) r.negate();
251        }
252        ret[0] = q;
253        ret[1] = r;
254        return ret;
255    }
256
257
258    /**
259     * Is GenSolvablePolynomial left base pseudo quotient and
260     * remainder. For univariate polynomials. todo: Ore condition
261     * @param <C> coefficient type.
262     * @param P base GenSolvablePolynomial.
263     * @param S nonzero base GenSolvablePolynomial.
264     * @return true, if P = q * S + r, else false.
265     * @see edu.jas.poly.GenSolvablePolynomial#remainder(edu.jas.poly.GenPolynomial).
266     *      <b>Note:</b> not always meaningful and working
267     */
268    public static <C extends GcdRingElem<C>> boolean isLeftBasePseudoQuotientRemainder(GenPolynomial<C> P,
269                    GenPolynomial<C> S, GenPolynomial<C> q, GenPolynomial<C> r) {
270        GenPolynomial<C> rhs = q.multiply(S).sum(r);
271        //System.out.println("rhs,1 = " + rhs);
272        GenPolynomial<C> lhs = P;
273        C ldcf = S.leadingBaseCoefficient();
274        long d = P.degree(0) - S.degree(0) + 1;
275        d = (d > 0 ? d : -d + 2);
276        for (long i = 0; i <= d; i++) {
277            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
278            if (lhs.equals(rhs) || lhs.negate().equals(rhs)) {
279                //System.out.println("lhs,1 = " + lhs);
280                return true;
281            }
282            lhs = lhs.multiply(ldcf);
283        }
284        GenPolynomial<C> Pp = P;
285        rhs = q.multiply(S);
286        //System.out.println("rhs,2 = " + rhs);
287        for (long i = 0; i <= d; i++) {
288            lhs = Pp.subtract(r);
289            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
290            if (lhs.equals(rhs) || lhs.negate().equals(rhs)) {
291                //System.out.println("lhs,2 = " + lhs);
292                return true;
293            }
294            Pp = Pp.multiply(ldcf);
295        }
296        C a = P.leadingBaseCoefficient();
297        rhs = q.multiply(S).sum(r);
298        C b = rhs.leadingBaseCoefficient();
299        C gcd = a.gcd(b);
300        C p = a.multiply(b);
301        C lcm = p.divide(gcd);
302        C ap = lcm.divide(a);
303        C bp = lcm.divide(b);
304        if (P.multiply(ap).equals(rhs.multiply(bp))) {
305            return true;
306        }
307        return false;
308    }
309
310
311    /**
312     * Is GenSolvablePolynomial right base pseudo quotient and
313     * remainder. For univariate polynomials. todo: Ore condition
314     * @param <C> coefficient type.
315     * @param P base GenSolvablePolynomial.
316     * @param S nonzero base GenSolvablePolynomial.
317     * @return true, if P = S * q + r, else false.
318     * @see edu.jas.poly.GenSolvablePolynomial#remainder(edu.jas.poly.GenPolynomial).
319     *      <b>Note:</b> not always meaningful and working
320     */
321    public static <C extends GcdRingElem<C>> boolean isRightBasePseudoQuotientRemainder(GenPolynomial<C> P,
322                    GenPolynomial<C> S, GenPolynomial<C> q, GenPolynomial<C> r) {
323        GenPolynomial<C> rhs = S.multiply(q).sum(r);
324        //System.out.println("rhs,1 = " + rhs);
325        GenPolynomial<C> lhs = P;
326        C ldcf = S.leadingBaseCoefficient();
327        long d = P.degree(0) - S.degree(0) + 1;
328        d = (d > 0 ? d : -d + 2);
329        for (long i = 0; i <= d; i++) {
330            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
331            if (lhs.equals(rhs) || lhs.negate().equals(rhs)) {
332                //System.out.println("lhs,1 = " + lhs);
333                return true;
334            }
335            lhs = lhs.multiply(ldcf);
336        }
337        GenPolynomial<C> Pp = P;
338        rhs = S.multiply(q);
339        //System.out.println("rhs,2 = " + rhs);
340        for (long i = 0; i <= d; i++) {
341            lhs = Pp.subtract(r);
342            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
343            if (lhs.equals(rhs) || lhs.negate().equals(rhs)) {
344                //System.out.println("lhs,2 = " + lhs);
345                return true;
346            }
347            Pp = Pp.multiply(ldcf);
348        }
349        C a = P.leadingBaseCoefficient();
350        rhs = S.multiply(q).sum(r);
351        C b = rhs.leadingBaseCoefficient();
352        C gcd = a.gcd(b);
353        C p = a.multiply(b);
354        C lcm = p.divide(gcd);
355        C ap = lcm.divide(a);
356        C bp = lcm.divide(b);
357        if (P.multiply(ap).equals(rhs.multiply(bp))) {
358            return true;
359        }
360        return false;
361    }
362
363
364    /**
365     * Is recursive GenSolvablePolynomial pseudo quotient and remainder. For
366     * recursive polynomials.
367     * @param <C> coefficient type.
368     * @param P recursive GenSolvablePolynomial.
369     * @param S nonzero recursive GenSolvablePolynomial.
370     * @return true, if P ~= q * S + r, else false.
371     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
372     *      <b>Note:</b> not always meaningful and working
373     */
374    @SuppressWarnings("unchecked")
375    public static <C extends GcdRingElem<C>> boolean isRecursivePseudoQuotientRemainder(
376                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S,
377                    GenSolvablePolynomial<GenPolynomial<C>> q, GenSolvablePolynomial<GenPolynomial<C>> r) {
378        GenSolvablePolynomial<GenPolynomial<C>> rhs, lhs;
379        rhs = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiply(S).sum(r);
380        lhs = P;
381        GenPolynomial<C> ldcf = S.leadingBaseCoefficient();
382        long d = P.degree(0) - S.degree(0) + 1;
383        d = (d > 0 ? d : -d + 2);
384        for (long i = 0; i <= d; i++) {
385            //System.out.println("lhs = " + lhs);
386            //System.out.println("rhs = " + rhs);
387            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
388            if (lhs.equals(rhs)) {
389                return true;
390            }
391            lhs = lhs.multiply(ldcf);
392        }
393        GenSolvablePolynomial<GenPolynomial<C>> Pp = P;
394        rhs = q.multiply(S);
395        //System.out.println("rhs,2 = " + rhs);
396        for (long i = 0; i <= d; i++) {
397            lhs = (GenSolvablePolynomial<GenPolynomial<C>>) Pp.subtract(r);
398            //System.out.println("lhs = " + lhs);
399            //System.out.println("rhs = " + rhs);
400            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
401            if (lhs.equals(rhs)) {
402                //System.out.println("lhs,2 = " + lhs);
403                return true;
404            }
405            Pp = Pp.multiply(ldcf);
406        }
407        GenPolynomialRing<C> cofac = (GenPolynomialRing) P.ring.coFac;
408        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorSimple<C>(cofac.coFac);
409        GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) P.leadingBaseCoefficient();
410        rhs = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiply(S).sum(r);
411        GenSolvablePolynomial<C> b = (GenSolvablePolynomial<C>) rhs.leadingBaseCoefficient();
412        GenSolvablePolynomial<C>[] oc = fd.leftOreCond(a, b);
413        GenPolynomial<C> ga = oc[0];
414        GenPolynomial<C> gb = oc[1];
415        //System.out.println("FDQR: OreCond:  a = " +  a + ",  b = " +  b);
416        //System.out.println("FDQR: OreCond: ga = " + ga + ", gb = " + gb);
417        // ga a = gd d
418        GenSolvablePolynomial<GenPolynomial<C>> Pa = P.multiplyLeft(ga); // coeff ga a
419        GenSolvablePolynomial<GenPolynomial<C>> Rb = rhs.multiplyLeft(gb); // coeff gb b  
420        GenSolvablePolynomial<GenPolynomial<C>> D = (GenSolvablePolynomial<GenPolynomial<C>>) Pa.subtract(Rb);
421        if (D.isZERO()) {
422            return true;
423        }
424        if (debug) {
425            logger.info("not QR: D = {}", D);
426        }
427        //System.out.println("FDQR: Pa = " + Pa);
428        //System.out.println("FDQR: Rb = " + Rb);
429        //System.out.println("FDQR: Pa-Rb = " + D);
430        return false;
431    }
432
433
434    /**
435     * GenSolvablePolynomial sparse pseudo remainder for recursive solvable
436     * polynomials.
437     * @param <C> coefficient type.
438     * @param P recursive GenSolvablePolynomial.
439     * @param S nonzero recursive GenSolvablePolynomial.
440     * @return remainder with ore(ldcf(S)<sup>m'</sup>) P = quotient * S +
441     *         remainder.
442     * @see edu.jas.poly.PolyUtil#recursiveSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
443     *      .
444     */
445    @SuppressWarnings("unchecked")
446    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveSparsePseudoRemainder(
447                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
448        return recursivePseudoQuotientRemainder(P, S)[1];
449    }
450
451
452    /**
453     * GenSolvablePolynomial recursive pseudo quotient for recursive
454     * polynomials.
455     * @param <C> coefficient type.
456     * @param P recursive GenSolvablePolynomial.
457     * @param S nonzero recursive GenSolvablePolynomial.
458     * @return quotient with ore(ldcf(S)<sup>m'</sup>) P = quotient * S +
459     *         remainder.
460     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
461     */
462    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursivePseudoQuotient(
463                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
464        return recursivePseudoQuotientRemainder(P, S)[0];
465    }
466
467
468    /**
469     * GenSolvablePolynomial recursive pseudo quotient and remainder for
470     * recursive polynomials.
471     * @param <C> coefficient type.
472     * @param P recursive GenSolvablePolynomial.
473     * @param S nonzero recursive GenSolvablePolynomial.
474     * @return [ quotient, remainder ] with ore(ldcf(S)<sup>m'</sup>) P =
475     *         quotient * S + remainder.
476     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
477     */
478    @SuppressWarnings("unchecked")
479    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>>[] recursivePseudoQuotientRemainder(
480                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
481        if (S == null || S.isZERO()) {
482            throw new ArithmeticException(P + " division by zero " + S);
483        }
484        //if (S.ring.nvar != 1) { // ok if exact division
485        //    throw new RuntimeException("univariate polynomials only");
486        //}
487        GenSolvablePolynomial<GenPolynomial<C>>[] ret = new GenSolvablePolynomial[2];
488        if (P == null || P.isZERO()) {
489            ret[0] = S.ring.getZERO();
490            ret[1] = S.ring.getZERO();
491            return ret;
492        }
493        if (S.isONE()) {
494            ret[0] = P;
495            ret[1] = S.ring.getZERO();
496            return ret;
497        }
498        GenPolynomialRing<C> cofac = (GenPolynomialRing) P.ring.coFac;
499        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorSimple<C>(cofac.coFac);
500
501        ExpVector e = S.leadingExpVector();
502        GenSolvablePolynomial<GenPolynomial<C>> h;
503        GenSolvablePolynomial<GenPolynomial<C>> r = P;
504        GenSolvablePolynomial<GenPolynomial<C>> q = S.ring.getZERO().copy();
505        while (!r.isZERO()) {
506            ExpVector g = r.leadingExpVector();
507            ExpVector f = g;
508            if (f.multipleOf(e)) {
509                f = f.subtract(e);
510                h = S.multiplyLeft(f); // coeff c, exp (f/e) e
511                GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) r.leadingBaseCoefficient();
512                GenSolvablePolynomial<C> d = (GenSolvablePolynomial<C>) h.leadingBaseCoefficient();
513                GenSolvablePolynomial<C>[] oc = fd.leftOreCond(a, d);
514                GenSolvablePolynomial<C> ga = (GenSolvablePolynomial<C>) oc[0]; // a
515                GenSolvablePolynomial<C> gd = (GenSolvablePolynomial<C>) oc[1]; // d
516                // ga * a = gd * d
517                r = r.multiplyLeft(ga); // coeff ga a, exp g
518                h = h.multiplyLeft(gd); // coeff gd d, exp f1
519                q = q.multiplyLeft(ga); // d
520                q = (GenSolvablePolynomial<GenPolynomial<C>>) q.sum(gd, f); // a
521                r = (GenSolvablePolynomial<GenPolynomial<C>>) r.subtract(h);
522                if (!r.isZERO() && g.equals(r.leadingExpVector())) {
523                    System.out.println("lt(r) = g = " + g + ", leftOre: " + fd.isLeftOreCond(a, d, ga, gd));
524                    //System.out.println("gd*d-ga*a = " + gd.multiply(d).subtract(ga.multiply(a)));
525                    throw new RuntimeException("degree not descending: r = " + r);
526                }
527                //System.out.println("r = " + r);
528            } else {
529                break;
530            }
531        }
532        int sp = P.signum();
533        int ss = S.signum();
534        int sq = q.signum();
535        // sp = ss * sq
536        if (sp != ss * sq) {
537            q = (GenSolvablePolynomial<GenPolynomial<C>>) q.negate();
538            r = (GenSolvablePolynomial<GenPolynomial<C>>) r.negate();
539        }
540        ret[0] = q;
541        ret[1] = r;
542        return ret;
543    }
544
545
546    /**
547     * Is recursive GenSolvablePolynomial right pseudo quotient and remainder.
548     * For recursive polynomials.
549     * @param <C> coefficient type.
550     * @param P recursive GenSolvablePolynomial.
551     * @param S nonzero recursive GenSolvablePolynomial.
552     * @return true, if P ~= S * q + r, else false.
553     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
554     *      <b>Note:</b> not always meaningful and working
555     */
556    @SuppressWarnings("unchecked")
557    public static <C extends GcdRingElem<C>> boolean isRecursiveRightPseudoQuotientRemainder(
558                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S,
559                    GenSolvablePolynomial<GenPolynomial<C>> q, GenSolvablePolynomial<GenPolynomial<C>> r) {
560        GenSolvablePolynomial<GenPolynomial<C>> rhs, lhs;
561        rhs = (GenSolvablePolynomial<GenPolynomial<C>>) S.multiply(q).sum(r);
562        lhs = P;
563        GenPolynomial<C> ldcf = S.leadingBaseCoefficient();
564        long d = P.degree(0) - S.degree(0) + 1;
565        d = (d > 0 ? d : -d + 2);
566        for (long i = 0; i <= d; i++) {
567            //System.out.println("lhs = " + lhs);
568            //System.out.println("rhs = " + rhs);
569            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
570            if (lhs.equals(rhs)) {
571                return true;
572            }
573            lhs = lhs.multiplyLeft(ldcf); // side?
574        }
575        GenSolvablePolynomial<GenPolynomial<C>> Pp = P;
576        rhs = S.multiply(q);
577        //System.out.println("rhs,2 = " + rhs);
578        for (long i = 0; i <= d; i++) {
579            lhs = (GenSolvablePolynomial<GenPolynomial<C>>) Pp.subtract(r);
580            //System.out.println("lhs = " + lhs);
581            //System.out.println("rhs = " + rhs);
582            //System.out.println("lhs-rhs = " + lhs.subtract(rhs));
583            if (lhs.equals(rhs)) {
584                //System.out.println("lhs,2 = " + lhs);
585                return true;
586            }
587            Pp = Pp.multiplyLeft(ldcf); // side?
588        }
589        GenPolynomialRing<C> cofac = (GenPolynomialRing) P.ring.coFac;
590        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorSimple<C>(cofac.coFac);
591
592        //GenSolvablePolynomial<GenPolynomial<C>> pr = P.rightRecursivePolynomial();
593        RecSolvablePolynomial<C> pr = (RecSolvablePolynomial<C>) P.rightRecursivePolynomial();
594        GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) pr.leadingBaseCoefficient();
595
596        rhs = (GenSolvablePolynomial<GenPolynomial<C>>) S.multiply(q).sum(r);
597        //GenSolvablePolynomial<GenPolynomial<C>> rr = rhs.rightRecursivePolynomial();
598        RecSolvablePolynomial<C> rr = (RecSolvablePolynomial<C>) rhs.rightRecursivePolynomial();
599        GenSolvablePolynomial<C> b = (GenSolvablePolynomial<C>) rr.leadingBaseCoefficient();
600
601        GenSolvablePolynomial<C>[] oc = fd.rightOreCond(a, b);
602        GenPolynomial<C> ga = oc[0];
603        GenPolynomial<C> gb = oc[1];
604        //System.out.println("FDQR: OreCond:  a = " +  a + ",  b = " +  b);
605        //System.out.println("FDQR: OreCond: ga = " + ga + ", gb = " + gb);
606        // a ga = d gd
607        GenSolvablePolynomial<GenPolynomial<C>> Pa = pr.multiplyRightComm(ga); // coeff a ga
608        GenSolvablePolynomial<GenPolynomial<C>> Rb = rr.multiplyRightComm(gb); // coeff b gb
609        //System.out.println("right(P)  = " +  pr + ",  P   = " +  P);
610        //System.out.println("right(rhs)= " +  rr + ",  rhs = " +  rhs);
611        //System.out.println("Pa        = " +  Pa + ",  ga  = " +  ga);
612        //System.out.println("Rb        = " +  Rb + ",  gb  = " +  gb);
613        GenSolvablePolynomial<GenPolynomial<C>> D = (GenSolvablePolynomial<GenPolynomial<C>>) Pa.subtract(Rb);
614        if (D.isZERO()) {
615            return true;
616        }
617        if (true) {
618            System.out.println("Pa = " + Pa);
619            System.out.println("Rb = " + Rb);
620            logger.info("not right QR: Pa-Rb = {}", D);
621        }
622        return false;
623    }
624
625
626    /**
627     * GenSolvablePolynomial right sparse pseudo remainder for recursive
628     * solvable polynomials. <b>Note:</b> uses right multiplication of P by
629     * ldcf(S), not always applicable.
630     * @param <C> coefficient type.
631     * @param P recursive GenSolvablePolynomial.
632     * @param S nonzero recursive GenSolvablePolynomial.
633     * @return remainder with P ore(ldcf(S)<sup>m'</sup>) = quotient * S +
634     *         remainder.
635     * @see edu.jas.poly.PolyUtil#recursiveSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
636     *      .
637     */
638    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveRightSparsePseudoRemainder(
639                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
640        return recursiveRightPseudoQuotientRemainder(P, S)[1];
641    }
642
643
644    /**
645     * GenSolvablePolynomial recursive right pseudo quotient for recursive
646     * polynomials.
647     * @param <C> coefficient type.
648     * @param P recursive GenSolvablePolynomial.
649     * @param S nonzero recursive GenSolvablePolynomial.
650     * @return quotient with P ore(ldcf(S)<sup>m'</sup>) = S * quotient +
651     *         remainder.
652     * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial).
653     */
654    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveRightPseudoQuotient(
655                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
656        return recursiveRightPseudoQuotientRemainder(P, S)[0];
657    }
658
659
660    /**
661     * GenSolvablePolynomial right sparse pseudo quotient and remainder for
662     * recursive solvable polynomials. <b>Note:</b> uses right multiplication of
663     * P by ldcf(S), not always applicable.
664     * @param <C> coefficient type.
665     * @param P recursive GenSolvablePolynomial.
666     * @param S nonzero recursive GenSolvablePolynomial.
667     * @return remainder with P ore(ldcf(S)<sup>m'</sup>) = S * quotient +
668     *         remainder.
669     * @see edu.jas.poly.PolyUtil#recursiveSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)
670     *      .
671     */
672    @SuppressWarnings("unchecked")
673    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>>[] recursiveRightPseudoQuotientRemainder(
674                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
675        if (S == null || S.isZERO()) {
676            throw new ArithmeticException(P + " division by zero " + S);
677        }
678        GenSolvablePolynomial<GenPolynomial<C>>[] ret = new GenSolvablePolynomial[2];
679        if (P == null || P.isZERO()) {
680            ret[0] = S.ring.getZERO();
681            ret[1] = S.ring.getZERO();
682            return ret;
683        }
684        if (S.isONE()) {
685            ret[0] = P;
686            ret[1] = S.ring.getZERO();
687            return ret;
688        }
689        //if (S.isConstant()) {
690        //    ret[0] = P.ring.getZERO();
691        //    ret[1] = S.ring.getZERO();
692        //    return ret;
693        //}
694        GenPolynomialRing<C> cofac = (GenPolynomialRing) P.ring.coFac;
695        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorSimple<C>(cofac.coFac);
696
697        ExpVector e = S.leadingExpVector();
698        GenSolvablePolynomial<GenPolynomial<C>> h, q, r;
699        RecSolvablePolynomial<C> hr, rr, qr;
700        r = P;
701        //System.out.println("zero = " + S.ring.getZERO().copy());
702        qr = (RecSolvablePolynomial<C>) S.ring.getZERO().copy();
703        while (!r.isZERO()) {
704            ExpVector g = r.leadingExpVector();
705            ExpVector f = g;
706            if (f.multipleOf(e)) {
707                f = f.subtract(e);
708                //System.out.println("f = " + f);
709                h = S.multiply(f); // coeff c, exp e (f/e)
710                hr = (RecSolvablePolynomial<C>) h.rightRecursivePolynomial();
711                rr = (RecSolvablePolynomial<C>) r.rightRecursivePolynomial();
712                GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) rr.leadingBaseCoefficient();
713                GenSolvablePolynomial<C> d = (GenSolvablePolynomial<C>) hr.leadingBaseCoefficient();
714                GenSolvablePolynomial<C>[] oc = fd.rightOreCond(a, d);
715                GenPolynomial<C> ga = oc[0]; // a
716                GenPolynomial<C> gd = oc[1]; // d
717                //System.out.println("OreCond:  a = " +  a + ",  d = " +  d);
718                //System.out.println("OreCond: ga = " + ga + ", gd = " + gd);
719                // a ga = d gd
720                //rr = rr.multiply(ga);   // exp f, coeff a ga 
721                //hr = hr.multiply(gd,f); // exp f, coeff d gd
722                rr = rr.multiplyRightComm(ga); // exp f, coeff a ga 
723                hr = hr.multiplyRightComm(gd); // exp f, coeff d gd  ///.shift(f)
724                h = hr.evalAsRightRecursivePolynomial();
725                r = rr.evalAsRightRecursivePolynomial();
726                r = (GenSolvablePolynomial<GenPolynomial<C>>) r.subtract(h);
727                qr = qr.multiplyRightComm(ga); // d
728                qr = (RecSolvablePolynomial<C>) qr.sum(gd, f); // a // same for right coefficients
729                //System.out.println("q = " + qr); //.leadingMonomial());
730                if (!r.isZERO() && g.equals(r.leadingExpVector())) {
731                    throw new RuntimeException("something is wrong: g == lc(r), terms not descending " + r);
732                }
733                //System.out.println("r = " +  r + ", qr = " +  qr);
734            } else {
735                break;
736            }
737        }
738        q = qr.evalAsRightRecursivePolynomial();
739        int sp = P.signum();
740        int ss = S.signum();
741        int sq = q.signum();
742        // sp = ss * sq
743        if (sp != ss * sq) {
744            q = (GenSolvablePolynomial<GenPolynomial<C>>) q.negate();
745            r = (GenSolvablePolynomial<GenPolynomial<C>>) r.negate();
746        }
747        ret[0] = q;
748        ret[1] = r;
749        return ret;
750    }
751
752
753    // ----------------------------------------------------------------------
754
755
756    /**
757     * GenSolvablePolynomial recursive quotient for recursive polynomials and
758     * exact division by coefficient ring element.
759     * @param <C> coefficient type.
760     * @param P recursive GenSolvablePolynomial.
761     * @param s GenSolvablePolynomial.
762     * @return P/s.
763     */
764    @SuppressWarnings("unchecked")
765    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveDivideRightEval(
766                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<C> s) {
767        if (s.isONE()) {
768            return P;
769        }
770        GenSolvablePolynomial<GenPolynomial<C>> Pr = P.rightRecursivePolynomial();
771        GenSolvablePolynomial<GenPolynomial<C>> Qr = FDUtil.<C> recursiveLeftDivide(Pr, s); // Left/Right
772        GenSolvablePolynomial<GenPolynomial<C>> Q = Qr.evalAsRightRecursivePolynomial();
773        if (debug) {
774            if (!Qr.multiplyLeft(s).equals(Pr)) {
775                System.out.println("rDivREval: Pr   = " + Pr + ", P = " + P);
776                System.out.println("rDivREval: Qr   = " + Qr + ", Q = " + Q);
777                System.out.println("rDivREval: s*Qr = " + Qr.multiplyLeft(s) + ", s = " + s);
778                System.out.println("rDivREval: Qr*s = " + Qr.multiply(s));
779                //System.out.println("rDivREval: P.ring == Q.ring: " + P.ring.equals(Q.ring) );
780                throw new RuntimeException("rDivREval: s*Qr != Pr");
781            }
782            if (!Q.multiply(s).equals(P)) {
783                System.out.println("rDivREval: P   = " + P + ", right(P) = " + Pr);
784                System.out.println("rDivREval: Q   = " + Q + ", right(Q) = " + Qr);
785                System.out.println("rDivREval: Q*s = " + Q.multiply(s) + ", s = " + s);
786                System.out.println("rDivREval: s*Q = " + Q.multiplyLeft(s));
787                //System.out.println("rDivREval: P.ring == Q.ring: " + P.ring.equals(Q.ring) );
788                throw new RuntimeException("rDivREval: Q*s != P");
789            }
790        }
791        return Q;
792    }
793
794
795    /**
796     * GenSolvablePolynomial left recursive quotient for recursive polynomials
797     * and exact division by coefficient ring element.
798     * @param <C> coefficient type.
799     * @param P recursive GenSolvablePolynomial.
800     * @param s GenSolvablePolynomial.
801     * @return this/s.
802     */
803    @SuppressWarnings({ "unchecked", "cast" })
804    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveDivide(
805                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<C> s) {
806        if (s == null || s.isZERO()) {
807            throw new ArithmeticException("division by zero " + P + ", " + s);
808        }
809        if (P.isZERO()) {
810            return P;
811        }
812        if (s.isONE()) {
813            return P;
814        }
815        GenSolvablePolynomialRing<GenPolynomial<C>> rfac = (GenSolvablePolynomialRing<GenPolynomial<C>>) P.ring;
816        GenSolvablePolynomial<GenPolynomial<C>> onep = rfac.getONE();
817        ExpVector zero = rfac.evzero;
818        GenSolvablePolynomial<GenPolynomial<C>> q = rfac.getZERO();
819        GenSolvablePolynomial<GenPolynomial<C>> r;
820        GenSolvablePolynomial<GenPolynomial<C>> p = P; //.ring.getZERO().copy();
821        while (!p.isZERO()) {
822            // for (Map.Entry<ExpVector, GenPolynomial<C>> m1 : P.getMap().entrySet()) {
823            Map.Entry<ExpVector, GenPolynomial<C>> m1 = p.leadingMonomial();
824            GenSolvablePolynomial<C> c1 = (GenSolvablePolynomial<C>) m1.getValue();
825            ExpVector e1 = m1.getKey();
826            GenSolvablePolynomial<C> c = c1.divide(s);
827            if (c.isZERO()) {
828                throw new RuntimeException("something is wrong: c is zero, c1 = " + c1 + ", s = " + s);
829            }
830            //r = onep.multiplyLeft(c.multiply(s), e1); // right: (c e1) * 1 * (s zero)
831            r = onep.multiply(c, e1, s, zero); // right: (c e1) * 1 * (s zero)
832            if (!c1.equals(r.leadingBaseCoefficient())) {
833                System.out.println("recRightDivide: lc(r) = " + r.leadingBaseCoefficient() + ", c1 = " + c1);
834                System.out.println("recRightDivide: lc(r) = " + c.multiply(s) + ", c = " + c + ", s = " + s);
835                throw new RuntimeException("something is wrong: lc(r) != c*s");
836            }
837            p = (RecSolvablePolynomial<C>) p.subtract(r);
838            if (!p.isZERO() && e1.compareTo(p.leadingExpVector()) == 0) {
839                System.out.println("recRightDivide: c     = " + c);
840                System.out.println("recRightDivide: lt(p) = " + p.leadingExpVector() + ", e1 = " + e1);
841                System.out.println("recRightDivide: c1/s  = " + c1.divide(s));
842                System.out.println("recRightDivide: s*c   = " + s.multiply(c));
843                System.out.println("recRightDivide: c*s   = " + c.multiply(s));
844                throw new RuntimeException("something is wrong: degree not descending");
845            }
846            q = (RecSolvablePolynomial<C>) q.sum(c, e1);
847        }
848        return q;
849    }
850
851
852    /*
853     * GenSolvablePolynomial recursive right quotient for recursive polynomials
854     * and partial right exact division by coefficient ring element.
855     * @param <C> coefficient type.
856     * @param P recursive GenSolvablePolynomial.
857     * @param s GenSolvablePolynomial.
858     * @return this/s.
859     @SuppressWarnings("unchecked")
860     public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveRightDivide(
861     GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<C> s) {
862     if (s == null || s.isZERO()) {
863     throw new ArithmeticException("division by zero " + P + ", " + s);
864     }
865     if (P.isZERO()) {
866     return P;
867     }
868     if (s.isONE()) {
869     return P;
870     }
871     GenSolvablePolynomial<GenPolynomial<C>> p = P.ring.getZERO().copy();
872     GenSolvablePolynomial<GenPolynomial<C>> Pr = P.rightRecursivePolynomial();
873     logger.info("P = {}, right(P) = {}, left(s) = {}", P, Pr, s);
874     for (Map.Entry<ExpVector, GenPolynomial<C>> m1 : Pr.getMap().entrySet()) {
875     GenSolvablePolynomial<C> c1 = (GenSolvablePolynomial<C>) m1.getValue();
876     ExpVector e1 = m1.getKey();
877     //GenSolvablePolynomial<C> c = FDUtil.<C> basePseudoQuotient(c1, s);
878     GenSolvablePolynomial<C> c = FDUtil.<C> divideRightPolynomial(c1, s);
879     //GenSolvablePolynomial<C>[] QR = FDUtil.<C> basePseudoQuotientRemainder(c1, s);
880     if (!c.isZERO()) {
881     //pv.put(e1, c); 
882     p.doPutToMap(e1, c);
883     }
884     }
885     GenSolvablePolynomial<GenPolynomial<C>> pl = p.evalAsRightRecursivePolynomial();
886     logger.info("pl = {}, p = {}", pl, p);
887     return pl;
888     }
889    */
890
891
892    /*
893     * GenSolvablePolynomial right quotient for polynomials and partial right
894     * exact division by coefficient ring element.
895     * @param <C> coefficient type.
896     * @param P GenSolvablePolynomial.
897     * @param s GenSolvablePolynomial, constant wrt. the main variable.
898     * @return P/s.
899     @SuppressWarnings("unchecked")
900     public static <C extends GcdRingElem<C>> GenSolvablePolynomial<C> divideRightPolynomial(
901     GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> s) {
902     if (s == null || s.isZERO()) {
903     throw new ArithmeticException("division by zero " + P + ", " + s);
904     }
905     if (P.isZERO()) {
906     return P;
907     }
908     if (s.isONE()) {
909     return P;
910     }
911     GenSolvablePolynomialRing<C> pfac = P.ring;
912     GenSolvablePolynomial<C> q;
913     if (pfac.nvar <= 1) {
914     GenSolvablePolynomial<C>[] QR1;
915     QR1 = FDUtil.<C> leftBasePseudoQuotientRemainder(P, s);
916     q = QR1[0];
917     if (debug) {
918     if (!QR1[1].isZERO()) {
919     System.out.println("rDivPol, P = " + P);
920     System.out.println("rDivPol, s = " + s);
921     throw new RuntimeException("non zero remainder, q = " + q + ", r = " + QR1[1]);
922     }
923     }
924     return q;
925     }
926     GenSolvablePolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1);
927     GenSolvablePolynomial<GenPolynomial<C>> pr, sr, qr, rr;
928     GenSolvablePolynomial<GenPolynomial<C>>[] QR;
929     pr = (GenSolvablePolynomial<GenPolynomial<C>>) PolyUtil.<C> recursive(rfac, P);
930     sr = (GenSolvablePolynomial<GenPolynomial<C>>) PolyUtil.<C> recursive(rfac, s);
931     //qr = FDUtil.<C> recursiveDivideRightPolynomial(pr,sc);
932     QR = FDUtil.<C> recursiveRightPseudoQuotientRemainder(pr, sr);
933     //QR = FDUtil.<C> recursivePseudoQuotientRemainder(pr,sr);
934     qr = QR[0];
935     rr = QR[1];
936     if (debug) {
937     if (!rr.isZERO()) {
938     System.out.println("rDivPol, pr = " + pr);
939     System.out.println("rDivPol, sr = " + sr);
940     throw new RuntimeException("non zero remainder, q = " + qr + ", r = " + rr);
941     }
942     }
943     q = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(pfac, qr);
944     return q;
945     }
946    */
947
948
949    /**
950     * GenSolvablePolynomial recursive quotient for recursive polynomials and
951     * partial right exact division by coefficient ring element.
952     * @param <C> coefficient type.
953     * @param P recursive GenSolvablePolynomial.
954     * @param s GenSolvablePolynomial.
955     * @return Q with s * Q = P.
956     */
957    @SuppressWarnings({ "unchecked", "cast" })
958    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveRightDivide(
959                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<C> s) {
960        if (s == null || s.isZERO()) {
961            throw new ArithmeticException("division by zero " + P + ", " + s);
962        }
963        if (P.isZERO()) {
964            return P;
965        }
966        if (s.isONE()) {
967            return P;
968        }
969        if (!(P instanceof RecSolvablePolynomial)) {
970            //return FDUtil.<C> recursiveDivide(P,s);
971        }
972        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) P.ring;
973        if (rfac.coeffTable.isEmpty()) {
974            //return FDUtil.<C> recursiveDivide(P,s);
975        }
976        RecSolvablePolynomial<C> onep = rfac.getONE();
977        //ExpVector zero = rfac.evzero;
978        RecSolvablePolynomial<C> q = rfac.getZERO();
979        RecSolvablePolynomial<C> r;
980        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) P;
981        //System.out.println("recRightDivide: p=P = " + p + ", s = " + s);
982        while (!p.isZERO()) {
983            Map.Entry<ExpVector, GenPolynomial<C>> m1 = p.leadingMonomial();
984            GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) m1.getValue();
985            ExpVector f = m1.getKey();
986            GenSolvablePolynomial<C> c = (GenSolvablePolynomial<C>) a.rightDivide(s); // s * c = a
987            //System.out.println("recRightDivide: s \\ a = c: " + s + " \\ " + a + " = " + c);
988            if (c.isZERO()) {
989                //logger.info("something is wrong: c is zero, a = {}, s = {}", a, s);
990                throw new RuntimeException("something is wrong: c is zero, a = " + a + ", s = " + s);
991            }
992            r = onep.multiply(s.multiply(c), f); // left 1 * s * c * (1 f)
993            if (!a.equals(r.leadingBaseCoefficient())) {
994                System.out.println("recRightDivide: a   = " + a + ", lc(r) = " + r.leadingBaseCoefficient());
995                System.out.println("recRightDivide: c*s = " + c.multiply(s) + ", s = " + s + ", c = " + c);
996                System.out.println(
997                                "recRightDivide: s*c = " + s.multiply(c) + ", a%s = " + a.rightRemainder(s));
998                throw new RuntimeException("something is wrong: c*s != a: " + rfac.toScript());
999            }
1000            p = (RecSolvablePolynomial<C>) p.subtract(r);
1001            if (!p.isZERO() && f.compareTo(p.leadingExpVector()) == 0) {
1002                System.out.println("recRightDivide: c     = " + c);
1003                System.out.println("recRightDivide: lt(p) = " + p.leadingExpVector() + ", f = " + f);
1004                System.out.println("recRightDivide: a/s   = " + a.divide(s));
1005                System.out.println("recRightDivide: s*c   = " + s.multiply(c));
1006                System.out.println("recRightDivide: c*s   = " + c.multiply(s));
1007                throw new RuntimeException("something is wrong: degree not descending");
1008            }
1009            q = (RecSolvablePolynomial<C>) q.sum(c, f);
1010        }
1011        //System.out.println("recRightDivide: q        = " + q);
1012        return q;
1013    }
1014
1015
1016    /**
1017     * GenSolvablePolynomial recursive quotient for recursive polynomials and
1018     * partial left exact division by coefficient ring element.
1019     * @param <C> coefficient type.
1020     * @param P recursive GenSolvablePolynomial.
1021     * @param s GenSolvablePolynomial.
1022     * @return Q with Q * s = P.
1023     */
1024    @SuppressWarnings({ "unchecked", "cast" })
1025    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> recursiveLeftDivide(
1026                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<C> s) {
1027        if (s == null || s.isZERO()) {
1028            throw new ArithmeticException("division by zero " + P + ", " + s);
1029        }
1030        if (P.isZERO()) {
1031            return P;
1032        }
1033        if (s.isONE()) {
1034            return P;
1035        }
1036        if (!(P instanceof RecSolvablePolynomial)) {
1037            //return FDUtil.<C> recursiveDivide(P,s);
1038            System.out.println("not RecSolvablePolynomial");
1039        }
1040        RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) P.ring;
1041        if (rfac.coeffTable.isEmpty()) {
1042            //return FDUtil.<C> recursiveDivide(P,s);
1043        }
1044        RecSolvablePolynomial<C> onep = rfac.getONE();
1045        //ExpVector zero = rfac.evzero;
1046        RecSolvablePolynomial<C> q = rfac.getZERO();
1047        RecSolvablePolynomial<C> r, Pp;
1048        //RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) P;
1049        RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) P.rightRecursivePolynomial();
1050        //System.out.println("recLeftDivide: P        = " + P + ", s = " + s);
1051        //System.out.println("recLeftDivide: right(P) = " + p);
1052        Pp = p;
1053        while (!p.isZERO()) {
1054            ExpVector f = p.leadingExpVector();
1055            GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) p.leadingBaseCoefficient();
1056            GenSolvablePolynomial<C> c = (GenSolvablePolynomial<C>) a.divide(s); // c * s = a
1057            ///GenSolvablePolynomial<C> c = (GenSolvablePolynomial<C>) a.rightDivide(s);
1058            if (c.isZERO()) {
1059                throw new RuntimeException("something is wrong: c is zero, a = " + a + ", s = " + s);
1060            }
1061            //System.out.println("recLeftDivide: a / s = c: " + a + " / " + s + " = " + c);
1062            //r = onep.multiply(c, f, s, zero); // right: (c f) * 1 * (s zero)
1063            r = onep.multiplyLeft(c.multiply(s), f); // right: (c*s f) * one
1064            ///r = onep.multiplyLeft(s.multiply(c), f); // left: (s*c f) * one
1065            if (!a.equals(r.leadingBaseCoefficient())) {
1066                System.out.println("recLeftDivide: a        = " + a);
1067                System.out.println("recLeftDivide: lc(r)    = " + r.leadingBaseCoefficient());
1068                System.out.println("recLeftDivide: c        = " + c);
1069                System.out.println("recLeftDivide: s        = " + s);
1070                C ac = a.leadingBaseCoefficient();
1071                C rc = r.leadingBaseCoefficient().leadingBaseCoefficient();
1072                C cc = rc.inverse().multiply(ac);
1073                System.out.println("recLeftDivide: cc       = " + cc);
1074                //c = c.multiply(cc);
1075                r = onep.multiplyLeft(c.multiply(s), f); // right: (1 f) * c * s
1076                System.out.println("recLeftDivide: lc(r)    = " + r.leadingBaseCoefficient());
1077                System.out.println("recLeftDivide: deg(r)   = " + r.degree());
1078                throw new RuntimeException("something is wrong: a != lc(r): " + rfac.toScript());
1079            }
1080            p = (RecSolvablePolynomial<C>) p.subtract(r);
1081            if (!p.isZERO() && f.compareTo(p.leadingExpVector()) == 0) {
1082                System.out.println("recLeftDivide: P        = " + P + ", s = " + s);
1083                System.out.println("recLeftDivide: right(P) = " + Pp);
1084                System.out.println("recLeftDivide: c        = " + c);
1085                System.out.println("recLeftDivide: lt(p)    = " + p.leadingExpVector() + ", f = " + f);
1086                System.out.println("recLeftDivide: a/s      = " + a.divide(s));
1087                System.out.println("recLeftDivide: a\\s      = " + a.rightDivide(s));
1088                System.out.println("recLeftDivide: s*c      = " + s.multiply(c));
1089                System.out.println("recLeftDivide: c*s      = " + c.multiply(s));
1090                throw new RuntimeException("something is wrong: degree not descending");
1091            }
1092            q = (RecSolvablePolynomial<C>) q.sum(c, f);
1093        }
1094        //System.out.println("recLeftDivide: q        = " + q);
1095        q = (RecSolvablePolynomial<C>) q.evalAsRightRecursivePolynomial();
1096        //System.out.println("recLeftDivide: eval(q)  = " + q);
1097        return q;
1098    }
1099
1100
1101    /**
1102     * Integral solvable polynomial from solvable rational function
1103     * coefficients. Represent as polynomial with integral solvable polynomial
1104     * coefficients by multiplication with the lcm(??) of the numerators of the
1105     * rational function coefficients.
1106     * @param fac result polynomial factory.
1107     * @param A polynomial with solvable rational function coefficients to be
1108     *            converted.
1109     * @return polynomial with integral solvable polynomial coefficients.
1110     */
1111    @SuppressWarnings({ "unchecked", "cast" })
1112    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<GenPolynomial<C>> integralFromQuotientCoefficients(
1113                    GenSolvablePolynomialRing<GenPolynomial<C>> fac,
1114                    GenSolvablePolynomial<SolvableQuotient<C>> A) {
1115        GenSolvablePolynomial<GenPolynomial<C>> B = fac.getZERO().copy();
1116        if (A == null || A.isZERO()) {
1117            return B;
1118        }
1119        GenSolvablePolynomial<C> c = null;
1120        GenSolvablePolynomial<C> d;
1121        GenSolvablePolynomial<C> x;
1122        GenSolvablePolynomial<C> z;
1123        GenPolynomialRing<C> cofac = (GenPolynomialRing) fac.coFac;
1124        GreatestCommonDivisorAbstract<C> fd = new GreatestCommonDivisorPrimitive<C>(cofac.coFac);
1125        int s = 0;
1126        // lcm/ore of denominators ??
1127        Map<ExpVector, SolvableQuotient<C>> Am = A.getMap();
1128        for (SolvableQuotient<C> y : Am.values()) {
1129            x = y.den;
1130            // c = lcm(c,x)
1131            if (c == null) {
1132                c = x;
1133                s = x.signum();
1134            } else {
1135                d = fd.leftGcd(c, x);
1136                z = (GenSolvablePolynomial<C>) x.divide(d); // ??
1137                c = z.multiply(c); // ?? multiplyLeft
1138            }
1139        }
1140        if (s < 0) {
1141            c = (GenSolvablePolynomial<C>) c.negate();
1142        }
1143        for (Map.Entry<ExpVector, SolvableQuotient<C>> y : Am.entrySet()) {
1144            ExpVector e = y.getKey();
1145            SolvableQuotient<C> a = y.getValue();
1146            // p = n*(c/d)
1147            GenPolynomial<C> b = c.divide(a.den);
1148            GenPolynomial<C> p = a.num.multiply(b);
1149            //B = B.sum( p, e ); // inefficient
1150            B.doPutToMap(e, p);
1151        }
1152        return B;
1153    }
1154
1155
1156    /**
1157     * Integral solvable polynomial from solvable rational function
1158     * coefficients. Represent as polynomial with integral solvable polynomial
1159     * coefficients by multiplication with the lcm(??) of the numerators of the
1160     * solvable rational function coefficients.
1161     * @param fac result polynomial factory.
1162     * @param L list of polynomials with solvable rational function coefficients
1163     *            to be converted.
1164     * @return list of polynomials with integral solvable polynomial
1165     *         coefficients.
1166     */
1167    @SuppressWarnings("unchecked")
1168    public static <C extends GcdRingElem<C>> List<GenSolvablePolynomial<GenPolynomial<C>>> integralFromQuotientCoefficients(
1169                    GenSolvablePolynomialRing<GenPolynomial<C>> fac,
1170                    Collection<GenSolvablePolynomial<SolvableQuotient<C>>> L) {
1171        if (L == null) {
1172            return null;
1173        }
1174        List<GenSolvablePolynomial<GenPolynomial<C>>> list = new ArrayList<GenSolvablePolynomial<GenPolynomial<C>>>(
1175                        L.size());
1176        for (GenSolvablePolynomial<SolvableQuotient<C>> p : L) {
1177            list.add(integralFromQuotientCoefficients(fac, p));
1178        }
1179        return list;
1180    }
1181
1182
1183    /**
1184     * Solvable rational function from integral solvable polynomial
1185     * coefficients. Represent as polynomial with type SolvableQuotient
1186     * <C> coefficients.
1187     * @param fac result polynomial factory.
1188     * @param A polynomial with integral solvable polynomial coefficients to be
1189     *            converted.
1190     * @return polynomial with type SolvableQuotient<C> coefficients.
1191     */
1192    @SuppressWarnings("unchecked")
1193    public static <C extends GcdRingElem<C>> GenSolvablePolynomial<SolvableQuotient<C>> quotientFromIntegralCoefficients(
1194                    GenSolvablePolynomialRing<SolvableQuotient<C>> fac,
1195                    GenSolvablePolynomial<GenPolynomial<C>> A) {
1196        GenSolvablePolynomial<SolvableQuotient<C>> B = fac.getZERO().copy();
1197        if (A == null || A.isZERO()) {
1198            return B;
1199        }
1200        RingFactory<SolvableQuotient<C>> cfac = fac.coFac;
1201        SolvableQuotientRing<C> qfac = (SolvableQuotientRing<C>) cfac;
1202        for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.getMap().entrySet()) {
1203            ExpVector e = y.getKey();
1204            GenSolvablePolynomial<C> a = (GenSolvablePolynomial<C>) y.getValue();
1205            SolvableQuotient<C> p = new SolvableQuotient<C>(qfac, a); // can not be zero
1206            if (!p.isZERO()) {
1207                //B = B.sum( p, e ); // inefficient
1208                B.doPutToMap(e, p);
1209            }
1210        }
1211        return B;
1212    }
1213
1214
1215    /**
1216     * Solvable rational function from integral solvable polynomial
1217     * coefficients. Represent as polynomial with type SolvableQuotient
1218     * <C> coefficients.
1219     * @param fac result polynomial factory.
1220     * @param L list of polynomials with integral solvable polynomial
1221     *            coefficients to be converted.
1222     * @return list of polynomials with type SolvableQuotient<C> coefficients.
1223     */
1224    public static <C extends GcdRingElem<C>> List<GenSolvablePolynomial<SolvableQuotient<C>>> quotientFromIntegralCoefficients(
1225                    GenSolvablePolynomialRing<SolvableQuotient<C>> fac,
1226                    Collection<GenSolvablePolynomial<GenPolynomial<C>>> L) {
1227        if (L == null) {
1228            return null;
1229        }
1230        List<GenSolvablePolynomial<SolvableQuotient<C>>> list = new ArrayList<GenSolvablePolynomial<SolvableQuotient<C>>>(
1231                        L.size());
1232        for (GenSolvablePolynomial<GenPolynomial<C>> p : L) {
1233            list.add(quotientFromIntegralCoefficients(fac, p));
1234        }
1235        return list;
1236    }
1237
1238}