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