001/*
002 * $Id: GreatestCommonDivisorLR.java 5731 2017-02-11 11:38:15Z kredel $
003 */
004
005package edu.jas.fd;
006
007
008import org.apache.log4j.Logger;
009
010import edu.jas.gbufd.SolvableSyzygyAbstract;
011import edu.jas.poly.GenPolynomial;
012import edu.jas.poly.GenSolvablePolynomial;
013import edu.jas.poly.GenSolvablePolynomialRing;
014import edu.jas.structure.GcdRingElem;
015import edu.jas.structure.RingFactory;
016
017
018/**
019 * (Non-unique) factorization domain greatest common divisor common algorithms
020 * with monic polynomial remainder sequence. Fake implementation always returns
021 * 1 for any gcds.
022 * @param <C> coefficient type
023 * @author Heinz Kredel
024 */
025
026public class GreatestCommonDivisorLR<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> {
027
028
029    private static final Logger logger = Logger.getLogger(GreatestCommonDivisorLR.class);
030
031
032    private static final boolean debug = logger.isDebugEnabled();
033
034
035    /**
036     * Constructor.
037     * @param cf coefficient ring.
038     */
039    public GreatestCommonDivisorLR(RingFactory<C> cf) {
040        super(cf);
041    }
042
043
044    /**
045     * Constructor.
046     * @param cf coefficient ring.
047     * @param s algorithm for SolvableSyzygy computation.
048     */
049    public GreatestCommonDivisorLR(RingFactory<C> cf, SolvableSyzygyAbstract<C> s) {
050        super(cf, s);
051    }
052
053
054    /**
055     * Univariate GenSolvablePolynomial greatest common divisor. Uses
056     * pseudoRemainder for remainder.
057     * @param P univariate GenSolvablePolynomial.
058     * @param S univariate GenSolvablePolynomial.
059     * @return [P,S,coP,coS,left,right] with left * coP * right = P and left *
060     *         coS * right = S.
061     */
062    public GCDcoFactors<C> leftRightBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
063        if (S == null || P == null) {
064            throw new IllegalArgumentException("null polynomials not allowed");
065        }
066        GenSolvablePolynomialRing<C> ring = P.ring;
067        if (ring.nvar > 1) {
068            throw new IllegalArgumentException("no univariate polynomial");
069        }
070        GCDcoFactors<C> ret;
071        if (P.isZERO() || S.isZERO()) {
072            ret = new GCDcoFactors<C>(this, P, S, P, S, ring.getONE(), ring.getONE());
073            return ret;
074        }
075        // compute on coefficients
076        C contP = leftBaseContent(P);
077        C contS = leftBaseContent(S);
078        C contPS = contP.leftGcd(contS);
079        if (contPS.signum() < 0) {
080            contPS = contPS.negate();
081        }
082        if (debug) {
083            //System.out.println("contP = " + contP + ", contS = " + contS + ", leftGcd(contP,contS) = " + contPS);
084            C r1 = contP.leftDivide(contPS);
085            boolean t = contPS.multiply(r1).equals(contP);
086            if (!t) {
087                System.out.println("r1: " + r1 + " * " + contPS + " != " + contP + ", r1*cP="
088                                + contPS.multiply(r1));
089            }
090            C r2 = contS.leftDivide(contPS);
091            t = contPS.multiply(r2).equals(contS);
092            if (!t) {
093                System.out.println("r2: " + r2 + " * " + contPS + " != " + contS + ", r2*cS="
094                                + contPS.multiply(r2));
095            }
096            //System.out.println("leftGcd(contP,contS) = " + contPS);
097        }
098        GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) P.leftDivideCoeff(contP);
099        GenSolvablePolynomial<C> s = (GenSolvablePolynomial<C>) S.leftDivideCoeff(contS);
100        if (debug) {
101            boolean t = p.multiplyLeft(contP).equals(P);
102            if (!t) {
103                System.out.println(
104                                "p: " + p + " * " + contP + " != " + P + ", p*cP=" + p.multiplyLeft(contP));
105            }
106            t = s.multiplyLeft(contS).equals(S);
107            if (!t) {
108                System.out.println(
109                                "s: " + s + " * " + contS + " != " + S + ", s*cS=" + s.multiplyLeft(contS));
110            }
111        }
112        // compute on main variable
113        if (p.isONE()) {
114            ret = new GCDcoFactors<C>(this, P, S, p, s, ring.valueOf(contPS), ring.getONE());
115            return ret;
116        }
117        if (s.isONE()) {
118            ret = new GCDcoFactors<C>(this, P, S, p, s, ring.valueOf(contPS), ring.getONE());
119            return ret;
120        }
121        boolean field = ring.coFac.isField();
122        GenSolvablePolynomial<C> r = p;
123        GenSolvablePolynomial<C> q = s;
124        GenSolvablePolynomial<C> x;
125        //System.out.println("baseGCD: q = " + q + ", r = " + r);
126        while (!r.isZERO()) {
127            x = FDUtil.<C> leftBaseSparsePseudoRemainder(q, r);
128            q = r;
129            if (field) {
130                r = x.monic();
131                //System.out.println("baseGCD: lc(q) = " + q.leadingBaseCoefficient() + ", lc(r) = " + r.leadingBaseCoefficient());
132            } else {
133                r = x;
134            }
135            //System.out.println("baseGCD: q = " + q + ", r = " + r);
136        }
137        q = leftBasePrimitivePart(q);
138        q = (GenSolvablePolynomial<C>) q.abs();
139        // not meaningful:
140        // adjust signum of contPS
141        //C qc = leftBaseContent(q);
142        //q = (GenSolvablePolynomial<C>) q.leftDivideCoeff(qc); 
143        //contPS = qc.multiply(contPS);
144        //System.out.println("leftGcd()*qc = " + contPS);
145        //q = rightBasePrimitivePart(q);
146        //System.out.println("baseGCD: q = " + q + ", r = " + r);
147        p = (GenSolvablePolynomial<C>) P.leftDivideCoeff(contPS); // not contP here
148        s = (GenSolvablePolynomial<C>) S.leftDivideCoeff(contPS); // not contS here
149        GenSolvablePolynomial<C> p1 = FDUtil.<C> leftBasePseudoQuotient(p, q); // TODO
150        GenSolvablePolynomial<C> s1 = FDUtil.<C> leftBasePseudoQuotient(s, q); // TODO 
151        //System.out.println("p1 = " + p1 + ", s1 = " + s1);
152        if (debug) {
153            boolean t = p1.multiply(q).equals(p);
154            if (!t) {
155                GenSolvablePolynomial<C> p1q = (GenSolvablePolynomial<C>) leftBasePrimitivePart(
156                                p1.multiply(q)).abs();
157                GenSolvablePolynomial<C> pp = (GenSolvablePolynomial<C>) leftBasePrimitivePart(p).abs();
158                if (!p1q.equals(pp)) {
159                    System.out.println("p1: " + p1 + " * " + q + " != " + p);
160                    System.out.println("pp(p1*q): " + p1q + " != " + pp);
161                }
162                p1q = p1.multiply(q);
163                pp = p;
164                C c1 = p1q.leadingBaseCoefficient();
165                C c2 = pp.leadingBaseCoefficient();
166                C[] oc = leftOreCond(c1, c2);
167                p1q = p1q.multiplyLeft(oc[0]);
168                pp = pp.multiplyLeft(oc[1]);
169                if (!p1q.equals(pp)) {
170                    System.out.println("p1q: " + p1q + " != " + pp);
171                }
172            }
173            t = s1.multiply(q).equals(s);
174            if (!t) {
175                GenSolvablePolynomial<C> s1q = (GenSolvablePolynomial<C>) leftBasePrimitivePart(
176                                s1.multiply(q)).abs();
177                GenSolvablePolynomial<C> sp = (GenSolvablePolynomial<C>) leftBasePrimitivePart(s).abs();
178                if (!s1q.equals(sp)) {
179                    System.out.println("s1: " + s1 + " * " + q + " != " + s);
180                    System.out.println("pp(s1*q): " + s1q + " != " + sp);
181                }
182                s1q = s1.multiply(q);
183                sp = s;
184                C c1 = s1q.leadingBaseCoefficient();
185                C c2 = sp.leadingBaseCoefficient();
186                C[] oc = leftOreCond(c1, c2);
187                s1q = s1q.multiplyLeft(oc[0]);
188                sp = sp.multiplyLeft(oc[1]);
189                if (!s1q.equals(sp)) {
190                    System.out.println("s1q: " + s1q + " != " + sp);
191                }
192            }
193            t = p.multiplyLeft(contPS).equals(P); // contPS q p1 == P
194            if (!t) {
195                System.out.println("p1P: " + contPS + " * " + p + " != " + P);
196            }
197            t = s.multiplyLeft(contPS).equals(S);
198            if (!t) {
199                System.out.println("s1S: " + contPS + " * " + s + " != " + S);
200            }
201            //System.out.println("isField: " + field);
202        }
203        ret = new GCDcoFactors<C>(this, P, S, p1, s1, ring.valueOf(contPS), q);
204        return ret;
205    }
206
207
208    /**
209     * Univariate GenSolvablePolynomial greatest common divisor. Uses
210     * pseudoRemainder for remainder.
211     * @param P univariate GenSolvablePolynomial.
212     * @param S univariate GenSolvablePolynomial.
213     * @return [P,S,coP,coS,left,right] with left * coP * right = P and left *
214     *         coS * right = S.
215     */
216    public GCDcoFactors<C> rightLeftBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
217        if (S == null || P == null) {
218            throw new IllegalArgumentException("null polynomials not allowed");
219        }
220        GenSolvablePolynomialRing<C> ring = P.ring;
221        if (ring.nvar > 1) {
222            throw new IllegalArgumentException("no univariate polynomial");
223        }
224        GCDcoFactors<C> ret;
225        if (P.isZERO() || S.isZERO()) {
226            ret = new GCDcoFactors<C>(this, P, S, P, S, ring.getONE(), ring.getONE());
227            return ret;
228        }
229        // compute on coefficients
230        C contP = rightBaseContent(P);
231        C contS = rightBaseContent(S);
232        C contPS = contP.rightGcd(contS);
233        if (contPS.signum() < 0) {
234            contPS = contPS.negate();
235        }
236        if (debug) {
237            //System.out.println("contP = " + contP + ", contS = " + contS + ", rightGcd(contP,contS) = " + contPS);
238            C r1 = contP.rightDivide(contPS);
239            boolean t = r1.multiply(contPS).equals(contP);
240            if (!t) {
241                System.out.println("r1: " + r1 + " * " + contPS + " != " + contP + ", r1*cP="
242                                + r1.multiply(contPS));
243            }
244            C r2 = contS.rightDivide(contPS);
245            t = r2.multiply(contPS).equals(contS);
246            if (!t) {
247                System.out.println("r2: " + r2 + " * " + contPS + " != " + contS + ", r2*cS="
248                                + r2.multiply(contPS));
249            }
250            //System.out.println("rightGcd(contP,contS) = " + contPS);
251        }
252        GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) P.rightDivideCoeff(contP);
253        GenSolvablePolynomial<C> s = (GenSolvablePolynomial<C>) S.rightDivideCoeff(contS);
254        if (debug) {
255            boolean t = p.multiply(contP).equals(P);
256            if (!t) {
257                System.out.println("p: " + p + " * " + contP + " != " + P + ", p*cP=" + p.multiply(contP));
258            }
259            t = s.multiply(contS).equals(S);
260            if (!t) {
261                System.out.println("s: " + s + " * " + contS + " != " + S + ", s*cS=" + s.multiply(contS));
262            }
263        }
264        // compute on main variable
265        if (p.isONE()) {
266            ret = new GCDcoFactors<C>(this, P, S, p, s, ring.getONE(), ring.valueOf(contPS));
267            return ret;
268        }
269        if (s.isONE()) {
270            ret = new GCDcoFactors<C>(this, P, S, p, s, ring.getONE(), ring.valueOf(contPS));
271            return ret;
272        }
273        boolean field = ring.coFac.isField();
274        GenSolvablePolynomial<C> r = p;
275        GenSolvablePolynomial<C> q = s;
276        GenSolvablePolynomial<C> x;
277        //System.out.println("baseGCD: q = " + q + ", r = " + r);
278        while (!r.isZERO()) {
279            x = FDUtil.<C> rightBaseSparsePseudoRemainder(q, r);
280            q = r;
281            if (field) {
282                r = x.monic();
283                //System.out.println("baseGCD: lc(q) = " + q.leadingBaseCoefficient() + ", lc(r) = " + r.leadingBaseCoefficient());
284            } else {
285                r = x;
286            }
287            //System.out.println("baseGCD: r = " + r);
288        }
289        q = rightBasePrimitivePart(q);
290        q = (GenSolvablePolynomial<C>) q.abs();
291        //q = rightBasePrimitivePart(q);
292        //System.out.println("baseGCD: q = " + q + ", r = " + r);
293        p = (GenSolvablePolynomial<C>) P.rightDivideCoeff(contPS); // not contP here
294        s = (GenSolvablePolynomial<C>) S.rightDivideCoeff(contPS); // not contS here
295        GenSolvablePolynomial<C> p1 = FDUtil.<C> rightBasePseudoQuotient(p, q); // TODO
296        GenSolvablePolynomial<C> s1 = FDUtil.<C> rightBasePseudoQuotient(s, q); // TODO 
297        //System.out.println("p1 = " + p1 + ", s1 = " + s1);
298        if (debug) {
299            boolean t = q.multiply(p1).equals(p);
300            if (!t) {
301                GenSolvablePolynomial<C> p1q = p1.multiply(q);
302                GenSolvablePolynomial<C> pp = p;
303                C c1 = p1q.leadingBaseCoefficient();
304                C c2 = pp.leadingBaseCoefficient();
305                C[] oc = rightOreCond(c1, c2);
306                p1q = p1q.multiply(oc[0]);
307                pp = pp.multiply(oc[1]);
308                if (!p1q.equals(pp)) {
309                    System.out.println("p1q: " + p1q + " != " + pp);
310                }
311            }
312            t = q.multiply(s1).equals(s);
313            if (!t) {
314                GenSolvablePolynomial<C> s1q = q.multiply(s1);
315                GenSolvablePolynomial<C> sp = s;
316                C c1 = s1q.leadingBaseCoefficient();
317                C c2 = sp.leadingBaseCoefficient();
318                C[] oc = rightOreCond(c1, c2);
319                s1q = s1q.multiply(oc[0]);
320                sp = sp.multiply(oc[1]);
321                if (!s1q.equals(sp)) {
322                    System.out.println("s1q: " + s1q + " != " + sp);
323                }
324            }
325            t = p.multiply(contPS).equals(P); // contPS q p1 == P
326            if (!t) {
327                System.out.println("p1P: " + contPS + " * " + p + " != " + P);
328            }
329            t = s.multiply(contPS).equals(S);
330            if (!t) {
331                System.out.println("s1S: " + contPS + " * " + s + " != " + S);
332            }
333            //System.out.println("isField: " + field);
334        }
335        ret = new GCDcoFactors<C>(this, P, S, p1, s1, q, ring.valueOf(contPS));
336        return ret;
337    }
338
339
340    /**
341     * Univariate GenSolvablePolynomial greatest common divisor. Uses
342     * pseudoRemainder for remainder.
343     * @param P univariate GenSolvablePolynomial.
344     * @param S univariate GenSolvablePolynomial.
345     * @return l = gcd(P,S) with P = gcd(P,S)*P' and S = gcd(P,S)*S'.
346     */
347    @Override
348    public GenSolvablePolynomial<C> leftBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
349        if (S == null || S.isZERO()) {
350            return P;
351        }
352        if (P == null || P.isZERO()) {
353            return S;
354        }
355        GenSolvablePolynomialRing<C> ring = P.ring;
356        if (ring.nvar > 1) {
357            throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial");
358        }
359        // compute on coefficients
360        C contP = leftBaseContent(P);
361        C contS = leftBaseContent(S);
362        C contPS = contP.leftGcd(contS);
363        if (contPS.signum() < 0) {
364            contPS = contPS.negate();
365        }
366        if (debug) {
367            //System.out.println("contP = " + contP + ", contS = " + contS + ", leftGcd(contP,contS) = " + contPS);
368            C r1 = contP.leftDivide(contPS);
369            boolean t = contPS.multiply(r1).equals(contP);
370            if (!t) {
371                System.out.println("r1: " + r1 + " * " + contPS + " != " + contP + ", r1*cP="
372                                + contPS.multiply(r1));
373            }
374            C r2 = contS.leftDivide(contPS);
375            t = contPS.multiply(r2).equals(contS);
376            if (!t) {
377                System.out.println("r2: " + r2 + " * " + contPS + " != " + contS + ", r2*cS="
378                                + contPS.multiply(r2));
379            }
380            //System.out.println("contPS = " + contPS);
381        }
382        GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) P.leftDivideCoeff(contP);
383        GenSolvablePolynomial<C> s = (GenSolvablePolynomial<C>) S.leftDivideCoeff(contS);
384        if (debug) {
385            boolean t = p.multiplyLeft(contP).equals(P);
386            if (!t) {
387                System.out.println(
388                                "p: " + p + " * " + contP + " != " + P + ", p*cP=" + p.multiplyLeft(contP));
389            }
390            t = s.multiplyLeft(contS).equals(S);
391            if (!t) {
392                System.out.println(
393                                "s: " + s + " * " + contS + " != " + S + ", s*cS=" + s.multiplyLeft(contS));
394            }
395        }
396        // compute on main variable
397        if (p.isONE()) {
398            return ring.valueOf(contPS);
399        }
400        if (s.isONE()) {
401            return ring.valueOf(contPS);
402        }
403        boolean field = ring.coFac.isField();
404        GenSolvablePolynomial<C> r = p;
405        GenSolvablePolynomial<C> q = s;
406        GenSolvablePolynomial<C> x;
407        if (r.degree(0) > q.degree(0)) {
408            x = r;
409            r = q;
410            q = x;
411        }
412        //System.out.println("baseGCD: q = " + q + ", r = " + r);
413        while (!r.isZERO()) {
414            x = FDUtil.<C> rightBaseSparsePseudoRemainder(q, r);
415            q = r;
416            if (field) {
417                r = x.monic();
418            } else {
419                r = x;
420            }
421            //System.out.println("baseGCD: r = " + r);
422        }
423        q = leftBasePrimitivePart(q);
424        //q = rightBasePrimitivePart(q);
425        //q = (GenSolvablePolynomial<C>) q.abs();
426        //System.out.println("baseGCD: q = " + q + ", r = " + r);
427        GenSolvablePolynomial<C> p1 = FDUtil.<C> rightBasePseudoQuotient(p, q); // TODO
428        GenSolvablePolynomial<C> s1 = FDUtil.<C> rightBasePseudoQuotient(s, q); // TODO 
429        //System.out.println("p1 = " + p1 + ", s1 = " + s1);
430        if (debug) {
431            boolean t = q.multiply(p1).equals(p);
432            if (!t) {
433                GenSolvablePolynomial<C> p1q = q.multiply(p1);
434                GenSolvablePolynomial<C> pp = p;
435                C c1 = p1q.leadingBaseCoefficient();
436                C c2 = pp.leadingBaseCoefficient();
437                C[] oc = leftOreCond(c1, c2);
438                p1q = p1q.multiplyLeft(oc[0]);
439                pp = pp.multiplyLeft(oc[1]);
440                if (!p1q.equals(pp)) {
441                    System.out.println("Ore cond, p1q: " + p1q + " != " + pp);
442                }
443            }
444            t = q.multiply(s1).equals(s);
445            if (!t) {
446                GenSolvablePolynomial<C> s1q = q.multiply(s1);
447                GenSolvablePolynomial<C> sp = s;
448                C c1 = s1q.leadingBaseCoefficient();
449                C c2 = sp.leadingBaseCoefficient();
450                C[] oc = leftOreCond(c1, c2);
451                s1q = s1q.multiplyLeft(oc[0]);
452                sp = sp.multiplyLeft(oc[1]);
453                if (!s1q.equals(sp)) {
454                    System.out.println("Ore cond, s1q: " + s1q + " != " + sp);
455                }
456            }
457            t = p.multiplyLeft(contP).equals(P); // contPS q p1 == P
458            if (!t) {
459                System.out.println("p1P: " + contPS + " * " + p + " != " + P);
460            }
461            t = s.multiplyLeft(contS).equals(S); // PS
462            if (!t) {
463                System.out.println("s1S: " + contPS + " * " + s + " != " + S);
464            }
465            //System.out.println("isField: " + field);
466        }
467        return q.multiplyLeft(contPS);
468    }
469
470
471    /**
472     * Univariate GenSolvablePolynomial greatest common divisor. Uses
473     * pseudoRemainder for remainder.
474     * @param P univariate GenSolvablePolynomial.
475     * @param S univariate GenSolvablePolynomial.
476     * @return r = gcd(P,S) with P = P'*gcd(P,S) and S = S'*gcd(P,S).
477     */
478    @Override
479    public GenSolvablePolynomial<C> rightBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) {
480        if (S == null || S.isZERO()) {
481            return P;
482        }
483        if (P == null || P.isZERO()) {
484            return S;
485        }
486        GenSolvablePolynomialRing<C> ring = P.ring;
487        if (ring.nvar > 1) {
488            throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial");
489        }
490        // compute on coefficients
491        C contP = rightBaseContent(P);
492        C contS = rightBaseContent(S);
493        C contPS = contP.rightGcd(contS);
494        if (contPS.signum() < 0) {
495            contPS = contPS.negate();
496        }
497        if (debug) {
498            //System.out.println("contP = " + contP + ", contS = " + contS + ", rightGcd(contP,contS) = " + contPS);
499            C r1 = contP.rightDivide(contPS);
500            boolean t = r1.multiply(contPS).equals(contP);
501            if (!t) {
502                System.out.println("r1: " + r1 + " * " + contPS + " != " + contP + ", r1*cP="
503                                + r1.multiply(contPS));
504            }
505            C r2 = contS.rightDivide(contPS);
506            t = r2.multiply(contPS).equals(contS);
507            if (!t) {
508                System.out.println("r2: " + r2 + " * " + contPS + " != " + contS + ", r2*cS="
509                                + r2.multiply(contPS));
510            }
511            //System.out.println("contPS = " + contPS);
512        }
513        GenSolvablePolynomial<C> p = (GenSolvablePolynomial<C>) P.rightDivideCoeff(contP);
514        GenSolvablePolynomial<C> s = (GenSolvablePolynomial<C>) S.rightDivideCoeff(contS);
515        if (debug) {
516            boolean t = p.multiply(contP).equals(P);
517            if (!t) {
518                System.out.println("p: " + p + " * " + contP + " != " + P + ", p*cP=" + p.multiply(contP));
519            }
520            t = s.multiply(contS).equals(S);
521            if (!t) {
522                System.out.println("s: " + s + " * " + contS + " != " + S + ", s*cS=" + s.multiply(contS));
523            }
524        }
525        // compute on main variable
526        if (p.isONE()) {
527            return ring.valueOf(contPS);
528        }
529        if (s.isONE()) {
530            return ring.valueOf(contPS);
531        }
532        boolean field = ring.coFac.isField();
533        GenSolvablePolynomial<C> r = p;
534        GenSolvablePolynomial<C> q = s;
535        GenSolvablePolynomial<C> x;
536        if (r.degree(0) > q.degree(0)) {
537            x = r;
538            r = q;
539            q = x;
540        }
541        //System.out.println("baseGCD: q = " + q + ", r = " + r);
542        while (!r.isZERO()) {
543            x = FDUtil.<C> leftBaseSparsePseudoRemainder(q, r);
544            q = r;
545            if (field) {
546                r = x.monic();
547            } else {
548                r = x;
549            }
550            //System.out.println("baseGCD: r = " + r);
551        }
552        //q = leftBasePrimitivePart(q);
553        q = rightBasePrimitivePart(q);
554        //q = (GenSolvablePolynomial<C>) q.abs();
555        //System.out.println("baseGCD: q = " + q + ", r = " + r);
556        GenSolvablePolynomial<C> p1 = FDUtil.<C> leftBasePseudoQuotient(p, q); // TODO
557        GenSolvablePolynomial<C> s1 = FDUtil.<C> leftBasePseudoQuotient(s, q); // TODO 
558        //System.out.println("p1 = " + p1 + ", s1 = " + s1);
559        if (debug) {
560            boolean t = p1.multiply(q).equals(p);
561            if (!t) {
562                GenSolvablePolynomial<C> p1q = p1.multiply(q);
563                GenSolvablePolynomial<C> pp = p;
564                C c1 = p1q.leadingBaseCoefficient();
565                C c2 = pp.leadingBaseCoefficient();
566                C[] oc = rightOreCond(c1, c2);
567                p1q = p1q.multiply(oc[0]);
568                pp = pp.multiply(oc[1]);
569                if (!p1q.equals(pp)) {
570                    System.out.println("Ore cond, p1q: " + p1q + " != " + pp);
571                }
572            }
573            t = s1.multiply(q).equals(s);
574            if (!t) {
575                GenSolvablePolynomial<C> s1q = s1.multiply(q);
576                GenSolvablePolynomial<C> sp = s;
577                C c1 = s1q.leadingBaseCoefficient();
578                C c2 = sp.leadingBaseCoefficient();
579                C[] oc = rightOreCond(c1, c2);
580                s1q = s1q.multiply(oc[0]);
581                sp = sp.multiply(oc[1]);
582                if (!s1q.equals(sp)) {
583                    System.out.println("Ore cond, s1q: " + s1q + " != " + sp);
584                }
585            }
586            t = p.multiply(contP).equals(P); // contPS q p1 == P
587            if (!t) {
588                System.out.println("p1P: " + contPS + " * " + p + " != " + P);
589            }
590            t = s.multiply(contS).equals(S); // PS
591            if (!t) {
592                System.out.println("s1S: " + contPS + " * " + s + " != " + S);
593            }
594            //System.out.println("isField: " + field);
595        }
596        return q.multiply(contPS);
597    }
598
599
600    /**
601     * Univariate GenSolvablePolynomial left recursive greatest common divisor.
602     * Uses pseudoRemainder for remainder.
603     * @param P univariate recursive GenSolvablePolynomial.
604     * @param S univariate recursive GenSolvablePolynomial.
605     * @return 1 = gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where
606     *         deg_main(p) = deg_main(s) == 0.
607     */
608    @Override
609    public GenSolvablePolynomial<GenPolynomial<C>> leftRecursiveUnivariateGcd(
610                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
611        if (S == null || S.isZERO()) {
612            return P;
613        }
614        if (P == null || P.isZERO()) {
615            return S;
616        }
617        if (P.ring.nvar > 1) {
618            throw new IllegalArgumentException("no univariate polynomial");
619        }
620        return P.ring.getONE();
621    }
622
623
624    /**
625     * Univariate GenSolvablePolynomial right recursive greatest common divisor.
626     * Uses pseudoRemainder for remainder.
627     * @param P univariate recursive GenSolvablePolynomial.
628     * @param S univariate recursive GenSolvablePolynomial.
629     * @return 1 = gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where
630     *         deg_main(p) = deg_main(s) == 0.
631     */
632    @Override
633    public GenSolvablePolynomial<GenPolynomial<C>> rightRecursiveUnivariateGcd(
634                    GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) {
635        if (S == null || S.isZERO()) {
636            return P;
637        }
638        if (P == null || P.isZERO()) {
639            return S;
640        }
641        if (P.ring.nvar > 1) {
642            throw new IllegalArgumentException("no univariate polynomial");
643        }
644        return P.ring.getONE();
645    }
646
647}