001/*
002 * $Id: GreatestCommonDivisorAbstract.java 4148 2012-08-31 19:49:27Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.poly.GenPolynomial;
014import edu.jas.poly.GenPolynomialRing;
015import edu.jas.poly.PolyUtil;
016import edu.jas.structure.GcdRingElem;
017import edu.jas.structure.RingFactory;
018
019
020/**
021 * Greatest common divisor algorithms.
022 * @author Heinz Kredel
023 */
024
025public abstract class GreatestCommonDivisorAbstract<C extends GcdRingElem<C>> implements
026                GreatestCommonDivisor<C> {
027
028
029    private static final Logger logger = Logger.getLogger(GreatestCommonDivisorAbstract.class);
030
031
032    private final boolean debug = logger.isDebugEnabled();
033
034
035    /**
036     * Get the String representation.
037     * @see java.lang.Object#toString()
038     */
039    @Override
040    public String toString() {
041        return getClass().getName();
042    }
043
044
045    /**
046     * GenPolynomial base coefficient content.
047     * @param P GenPolynomial.
048     * @return cont(P).
049     */
050    public C baseContent(GenPolynomial<C> P) {
051        if (P == null) {
052            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
053        }
054        if (P.isZERO()) {
055            return P.ring.getZEROCoefficient();
056        }
057        C d = null;
058        for (C c : P.getMap().values()) {
059            if (d == null) {
060                d = c;
061            } else {
062                d = d.gcd(c);
063            }
064            if (d.isONE()) {
065                return d;
066            }
067        }
068        if (d.signum() < 0) {
069            d = d.negate();
070        }
071        return d;
072    }
073
074
075    /**
076     * GenPolynomial base coefficient primitive part.
077     * @param P GenPolynomial.
078     * @return pp(P).
079     */
080    public GenPolynomial<C> basePrimitivePart(GenPolynomial<C> P) {
081        if (P == null) {
082            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
083        }
084        if (P.isZERO()) {
085            return P;
086        }
087        C d = baseContent(P);
088        if (d.isONE()) {
089            return P;
090        }
091        GenPolynomial<C> pp = P.divide(d);
092        if (debug) {
093            GenPolynomial<C> p = pp.multiply(d);
094            if (!p.equals(P)) {
095                throw new ArithmeticException("pp(p)*cont(p) != p: ");
096            }
097        }
098        return pp;
099    }
100
101
102    /**
103     * Univariate GenPolynomial greatest common divisor. Uses sparse
104     * pseudoRemainder for remainder.
105     * @param P univariate GenPolynomial.
106     * @param S univariate GenPolynomial.
107     * @return gcd(P,S).
108     */
109    public abstract GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S);
110
111
112    /**
113     * GenPolynomial recursive content.
114     * @param P recursive GenPolynomial.
115     * @return cont(P).
116     */
117    public GenPolynomial<C> recursiveContent(GenPolynomial<GenPolynomial<C>> P) {
118        if (P == null) {
119            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
120        }
121        if (P.isZERO()) {
122            return P.ring.getZEROCoefficient();
123        }
124        GenPolynomial<C> d = null;
125        for (GenPolynomial<C> c : P.getMap().values()) {
126            if (d == null) {
127                d = c;
128            } else {
129                d = gcd(d, c); // go to recursion
130            }
131            if (d.isONE()) {
132                return d;
133            }
134        }
135        return d.abs();
136    }
137
138
139    /**
140     * GenPolynomial recursive primitive part.
141     * @param P recursive GenPolynomial.
142     * @return pp(P).
143     */
144    public GenPolynomial<GenPolynomial<C>> recursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
145        if (P == null) {
146            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
147        }
148        if (P.isZERO()) {
149            return P;
150        }
151        GenPolynomial<C> d = recursiveContent(P);
152        if (d.isONE()) {
153            return P;
154        }
155        GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> recursiveDivide(P, d);
156        return pp;
157    }
158
159
160    /**
161     * GenPolynomial base recursive content.
162     * @param P recursive GenPolynomial.
163     * @return baseCont(P).
164     */
165    public C baseRecursiveContent(GenPolynomial<GenPolynomial<C>> P) {
166        if (P == null) {
167            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
168        }
169        if (P.isZERO()) {
170            GenPolynomialRing<C> cf = (GenPolynomialRing<C>) P.ring.coFac;
171            return cf.coFac.getZERO();
172        }
173        C d = null;
174        for (GenPolynomial<C> c : P.getMap().values()) {
175            C cc = baseContent(c);
176            if (d == null) {
177                d = cc;
178            } else {
179                d = gcd(d, cc);
180            }
181            if (d.isONE()) {
182                return d;
183            }
184        }
185        if (d.signum() < 0) {
186            d = d.negate();
187        }
188        return d;
189    }
190
191
192    /**
193     * GenPolynomial base recursive primitive part.
194     * @param P recursive GenPolynomial.
195     * @return basePP(P).
196     */
197    public GenPolynomial<GenPolynomial<C>> baseRecursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
198        if (P == null) {
199            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
200        }
201        if (P.isZERO()) {
202            return P;
203        }
204        C d = baseRecursiveContent(P);
205        if (d.isONE()) {
206            return P;
207        }
208        GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> baseRecursiveDivide(P, d);
209        return pp;
210    }
211
212
213    /**
214     * GenPolynomial recursive greatest common divisor. Uses pseudoRemainder for
215     * remainder.
216     * @param P recursive GenPolynomial.
217     * @param S recursive GenPolynomial.
218     * @return gcd(P,S).
219     */
220    public GenPolynomial<GenPolynomial<C>> recursiveGcd(GenPolynomial<GenPolynomial<C>> P,
221                    GenPolynomial<GenPolynomial<C>> S) {
222        if (S == null || S.isZERO()) {
223            return P;
224        }
225        if (P == null || P.isZERO()) {
226            return S;
227        }
228        if (P.ring.nvar <= 1) {
229            return recursiveUnivariateGcd(P, S);
230        }
231        // distributed polynomials gcd
232        GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
233        RingFactory<GenPolynomial<C>> rrfac = rfac.coFac;
234        GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rrfac;
235        GenPolynomialRing<C> dfac = cfac.extend(rfac.nvar);
236        GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac, P);
237        GenPolynomial<C> Sd = PolyUtil.<C> distribute(dfac, S);
238        GenPolynomial<C> Dd = gcd(Pd, Sd);
239        // convert to recursive
240        GenPolynomial<GenPolynomial<C>> C = PolyUtil.<C> recursive(rfac, Dd);
241        return C;
242    }
243
244
245    /**
246     * Univariate GenPolynomial recursive greatest common divisor. Uses
247     * pseudoRemainder for remainder.
248     * @param P univariate recursive GenPolynomial.
249     * @param S univariate recursive GenPolynomial.
250     * @return gcd(P,S).
251     */
252    public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P,
253                    GenPolynomial<GenPolynomial<C>> S);
254
255
256    /**
257     * GenPolynomial content.
258     * @param P GenPolynomial.
259     * @return cont(P).
260     */
261    public GenPolynomial<C> content(GenPolynomial<C> P) {
262        if (P == null) {
263            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
264        }
265        GenPolynomialRing<C> pfac = P.ring;
266        if (pfac.nvar <= 1) {
267            // baseContent not possible by return type
268            throw new IllegalArgumentException(this.getClass().getName()
269                            + " use baseContent for univariate polynomials");
270
271        }
272        GenPolynomialRing<C> cfac = pfac.contract(1);
273        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
274
275        GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
276        GenPolynomial<C> D = recursiveContent(Pr);
277        return D;
278    }
279
280
281    /**
282     * GenPolynomial primitive part.
283     * @param P GenPolynomial.
284     * @return pp(P).
285     */
286    public GenPolynomial<C> primitivePart(GenPolynomial<C> P) {
287        if (P == null) {
288            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
289        }
290        if (P.isZERO()) {
291            return P;
292        }
293        GenPolynomialRing<C> pfac = P.ring;
294        if (pfac.nvar <= 1) {
295            return basePrimitivePart(P);
296        }
297        GenPolynomialRing<C> cfac = pfac.contract(1);
298        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
299
300        GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
301        GenPolynomial<GenPolynomial<C>> PP = recursivePrimitivePart(Pr);
302
303        GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PP);
304        return D;
305    }
306
307
308    /**
309     * GenPolynomial division. Indirection to GenPolynomial method.
310     * @param a GenPolynomial.
311     * @param b coefficient.
312     * @return a/b.
313     */
314    public GenPolynomial<C> divide(GenPolynomial<C> a, C b) {
315        if (b == null || b.isZERO()) {
316            throw new IllegalArgumentException("division by zero");
317
318        }
319        if (a == null || a.isZERO()) {
320            return a;
321        }
322        return a.divide(b);
323    }
324
325
326    /**
327     * Coefficient greatest common divisor. Indirection to coefficient method.
328     * @param a coefficient.
329     * @param b coefficient.
330     * @return gcd(a,b).
331     */
332    public C gcd(C a, C b) {
333        if (b == null || b.isZERO()) {
334            return a;
335        }
336        if (a == null || a.isZERO()) {
337            return b;
338        }
339        return a.gcd(b);
340    }
341
342
343    /**
344     * GenPolynomial greatest common divisor.
345     * @param P GenPolynomial.
346     * @param S GenPolynomial.
347     * @return gcd(P,S).
348     */
349    public GenPolynomial<C> gcd(GenPolynomial<C> P, GenPolynomial<C> S) {
350        if (S == null || S.isZERO()) {
351            return P;
352        }
353        if (P == null || P.isZERO()) {
354            return S;
355        }
356        GenPolynomialRing<C> pfac = P.ring;
357        if (pfac.nvar <= 1) {
358            GenPolynomial<C> T = baseGcd(P, S);
359            return T;
360        }
361        GenPolynomialRing<C> cfac = pfac.contract(1);
362        GenPolynomialRing<GenPolynomial<C>> rfac;
363        if (pfac.getVars() != null && pfac.getVars().length > 0) {
364            String[] v = new String[] { pfac.getVars()[pfac.nvar - 1] };
365            rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1, v);
366        } else {
367            rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
368        }
369        GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
370        GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
371        GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateGcd(Pr, Sr);
372        GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
373        return D;
374    }
375
376
377    /**
378     * GenPolynomial least common multiple.
379     * @param P GenPolynomial.
380     * @param S GenPolynomial.
381     * @return lcm(P,S).
382     */
383    public GenPolynomial<C> lcm(GenPolynomial<C> P, GenPolynomial<C> S) {
384        if (S == null || S.isZERO()) {
385            return S;
386        }
387        if (P == null || P.isZERO()) {
388            return P;
389        }
390        GenPolynomial<C> C = gcd(P, S);
391        GenPolynomial<C> A = P.multiply(S);
392        return PolyUtil.<C> basePseudoDivide(A, C);
393    }
394
395
396    /**
397     * List of GenPolynomials greatest common divisor.
398     * @param A non empty list of GenPolynomials.
399     * @return gcd(A_i).
400     */
401    public GenPolynomial<C> gcd(List<GenPolynomial<C>> A) {
402        if (A == null || A.isEmpty()) {
403            throw new IllegalArgumentException("A may not be empty");
404        }
405        GenPolynomial<C> g = A.get(0);
406        for (int i = 1; i < A.size(); i++) {
407            GenPolynomial<C> f = A.get(i);
408            g = gcd(g, f);
409        }
410        return g;
411    }
412
413
414    /**
415     * Univariate GenPolynomial resultant.
416     * @param P univariate GenPolynomial.
417     * @param S univariate GenPolynomial.
418     * @return res(P,S).
419     * @throws UnsupportedOperationException if there is no implementation in
420     *             the sub-class.
421     */
422    @SuppressWarnings("unused")
423    public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) {
424        // can not be abstract
425        throw new UnsupportedOperationException("not implmented");
426    }
427
428
429    /**
430     * Univariate GenPolynomial recursive resultant.
431     * @param P univariate recursive GenPolynomial.
432     * @param S univariate recursive GenPolynomial.
433     * @return res(P,S).
434     * @throws UnsupportedOperationException if there is no implementation in
435     *             the sub-class.
436     */
437    @SuppressWarnings("unused")
438    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P,
439                    GenPolynomial<GenPolynomial<C>> S) {
440        // can not be abstract
441        throw new UnsupportedOperationException("not implmented");
442    }
443
444
445    /**
446     * GenPolynomial recursive resultant.
447     * @param P univariate recursive GenPolynomial.
448     * @param S univariate recursive GenPolynomial.
449     * @return res(P,S).
450     * @throws UnsupportedOperationException if there is no implementation in
451     *             the sub-class.
452     */
453    public GenPolynomial<GenPolynomial<C>> recursiveResultant(GenPolynomial<GenPolynomial<C>> P,
454                    GenPolynomial<GenPolynomial<C>> S) {
455        if (S == null || S.isZERO()) {
456            return S;
457        }
458        if (P == null || P.isZERO()) {
459            return P;
460        }
461        GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
462        GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rfac.coFac;
463        GenPolynomialRing<C> dfac = cfac.extend(rfac.getVars());
464        GenPolynomial<C> Pp = PolyUtil.<C> distribute(dfac, P);
465        GenPolynomial<C> Sp = PolyUtil.<C> distribute(dfac, S);
466        GenPolynomial<C> res = resultant(Pp, Sp);
467        GenPolynomial<GenPolynomial<C>> Rr = PolyUtil.<C> recursive(rfac, res);
468        return Rr;
469    }
470
471
472    /**
473     * GenPolynomial resultant. The input polynomials are considered as
474     * univariate polynomials in the main variable.
475     * @param P GenPolynomial.
476     * @param S GenPolynomial.
477     * @return res(P,S).
478     * @see edu.jas.ufd.GreatestCommonDivisorSubres#recursiveResultant
479     * @throws UnsupportedOperationException if there is no implementation in
480     *             the sub-class.
481     */
482    public GenPolynomial<C> resultant(GenPolynomial<C> P, GenPolynomial<C> S) {
483        if (S == null || S.isZERO()) {
484            return S;
485        }
486        if (P == null || P.isZERO()) {
487            return P;
488        }
489        // no more hacked: GreatestCommonDivisorSubres<C> ufd_sr = new GreatestCommonDivisorSubres<C>();
490        GenPolynomialRing<C> pfac = P.ring;
491        if (pfac.nvar <= 1) {
492            return baseResultant(P, S);
493        }
494        GenPolynomialRing<C> cfac = pfac.contract(1);
495        GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
496
497        GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
498        GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
499
500        GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateResultant(Pr, Sr);
501        GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
502        return D;
503    }
504
505
506    /**
507     * GenPolynomial co-prime list.
508     * @param A list of GenPolynomials.
509     * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
510     *         a in A there exists b in B with b|a. B does not contain zero or
511     *         constant polynomials.
512     */
513    public List<GenPolynomial<C>> coPrime(List<GenPolynomial<C>> A) {
514        if (A == null || A.isEmpty()) {
515            return A;
516        }
517        List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(A.size());
518        // make a coprime to rest of list
519        GenPolynomial<C> a = A.get(0);
520        //System.out.println("a = " + a);
521        if (!a.isZERO() && !a.isConstant()) {
522            for (int i = 1; i < A.size(); i++) {
523                GenPolynomial<C> b = A.get(i);
524                GenPolynomial<C> g = gcd(a, b).abs();
525                if (!g.isONE()) {
526                    a = PolyUtil.<C> basePseudoDivide(a, g);
527                    b = PolyUtil.<C> basePseudoDivide(b, g);
528                    GenPolynomial<C> gp = gcd(a, g).abs();
529                    while (!gp.isONE()) {
530                        a = PolyUtil.<C> basePseudoDivide(a, gp);
531                        g = PolyUtil.<C> basePseudoDivide(g, gp);
532                        B.add(g); // gcd(a,g) == 1
533                        g = gp;
534                        gp = gcd(a, gp).abs();
535                    }
536                    if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
537                        B.add(g); // gcd(a,g) == 1
538                    }
539                }
540                if (!b.isZERO() && !b.isConstant()) {
541                    B.add(b); // gcd(a,b) == 1
542                }
543            }
544        } else {
545            B.addAll(A.subList(1, A.size()));
546        }
547        // make rest coprime
548        B = coPrime(B);
549        //System.out.println("B = " + B);
550        if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
551            a = a.abs();
552            B.add(a);
553        }
554        return B;
555    }
556
557
558    /**
559     * GenPolynomial co-prime list.
560     * @param A list of GenPolynomials.
561     * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
562     *         a in A there exists b in B with b|a. B does not contain zero or
563     *         constant polynomials.
564     */
565    public List<GenPolynomial<C>> coPrimeRec(List<GenPolynomial<C>> A) {
566        if (A == null || A.isEmpty()) {
567            return A;
568        }
569        List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>();
570        // make a co-prime to rest of list
571        for (GenPolynomial<C> a : A) {
572            //System.out.println("a = " + a);
573            B = coPrime(a, B);
574            //System.out.println("B = " + B);
575        }
576        return B;
577    }
578
579
580    /**
581     * GenPolynomial co-prime list.
582     * @param a GenPolynomial.
583     * @param P co-prime list of GenPolynomials.
584     * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a
585     *         there exists b in P with b|a. B does not contain zero or constant
586     *         polynomials.
587     */
588    public List<GenPolynomial<C>> coPrime(GenPolynomial<C> a, List<GenPolynomial<C>> P) {
589        if (a == null || a.isZERO() || a.isConstant()) {
590            return P;
591        }
592        List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(P.size() + 1);
593        // make a coprime to elements of the list P
594        for (int i = 0; i < P.size(); i++) {
595            GenPolynomial<C> b = P.get(i);
596            GenPolynomial<C> g = gcd(a, b).abs();
597            if (!g.isONE()) {
598                a = PolyUtil.<C> basePseudoDivide(a, g);
599                b = PolyUtil.<C> basePseudoDivide(b, g);
600                // make g co-prime to new a, g is co-prime to c != b in P, B
601                GenPolynomial<C> gp = gcd(a, g).abs();
602                while (!gp.isONE()) {
603                    a = PolyUtil.<C> basePseudoDivide(a, gp);
604                    g = PolyUtil.<C> basePseudoDivide(g, gp);
605                    if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
606                        B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
607                    }
608                    g = gp;
609                    gp = gcd(a, gp).abs();
610                }
611                // make new g co-prime to new b
612                gp = gcd(b, g).abs();
613                while (!gp.isONE()) {
614                    b = PolyUtil.<C> basePseudoDivide(b, gp);
615                    g = PolyUtil.<C> basePseudoDivide(g, gp);
616                    if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
617                        B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
618                    }
619                    g = gp;
620                    gp = gcd(b, gp).abs();
621                }
622                if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
623                    B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
624                }
625            }
626            if (!b.isZERO() && !b.isConstant() /*&& !B.contains(b)*/) {
627                B.add(b); // gcd(a,b) == 1 and gcd(b,c) == 1 for c != b in P, B
628            }
629        }
630        if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
631            B.add(a);
632        }
633        return B;
634    }
635
636
637    /**
638     * GenPolynomial test for co-prime list.
639     * @param A list of GenPolynomials.
640     * @return true if gcd(b,c) = 1 for all b != c in B, else false.
641     */
642    public boolean isCoPrime(List<GenPolynomial<C>> A) {
643        if (A == null || A.isEmpty()) {
644            return true;
645        }
646        if (A.size() == 1) {
647            return true;
648        }
649        for (int i = 0; i < A.size(); i++) {
650            GenPolynomial<C> a = A.get(i);
651            for (int j = i + 1; j < A.size(); j++) {
652                GenPolynomial<C> b = A.get(j);
653                GenPolynomial<C> g = gcd(a, b);
654                if (!g.isONE()) {
655                    System.out.println("not co-prime, a: " + a);
656                    System.out.println("not co-prime, b: " + b);
657                    System.out.println("not co-prime, g: " + g);
658                    return false;
659                }
660            }
661        }
662        return true;
663    }
664
665
666    /**
667     * GenPolynomial test for co-prime list of given list.
668     * @param A list of GenPolynomials.
669     * @param P list of co-prime GenPolynomials.
670     * @return true if isCoPrime(P) and for all a in A exists p in P with p | a,
671     *         else false.
672     */
673    public boolean isCoPrime(List<GenPolynomial<C>> P, List<GenPolynomial<C>> A) {
674        if (!isCoPrime(P)) {
675            return false;
676        }
677        if (A == null || A.isEmpty()) {
678            return true;
679        }
680        for (GenPolynomial<C> q : A) {
681            if (q.isZERO() || q.isConstant()) {
682                continue;
683            }
684            boolean divides = false;
685            for (GenPolynomial<C> p : P) {
686                GenPolynomial<C> a = PolyUtil.<C> baseSparsePseudoRemainder(q, p);
687                if (a.isZERO()) { // p divides q
688                    divides = true;
689                    break;
690                }
691            }
692            if (!divides) {
693                System.out.println("no divisor for: " + q);
694                return false;
695            }
696        }
697        return true;
698    }
699
700
701    /**
702     * Univariate GenPolynomial extended greatest common divisor. Uses sparse
703     * pseudoRemainder for remainder.
704     * @param P univariate GenPolynomial.
705     * @param S univariate GenPolynomial.
706     * @return [ gcd(P,S), a, b ] with a*P + b*S = gcd(P,S).
707     */
708    public GenPolynomial<C>[] baseExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
709        //return P.egcd(S);
710        GenPolynomial<C>[] hegcd = baseHalfExtendedGcd(P, S);
711        GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
712        ret[0] = hegcd[0];
713        ret[1] = hegcd[1];
714        GenPolynomial<C> x = hegcd[0].subtract(hegcd[1].multiply(P));
715        GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(x, S);
716        // assert qr[1].isZERO() 
717        ret[2] = qr[0];
718        return ret;
719    }
720
721
722    /**
723     * Univariate GenPolynomial half extended greatest comon divisor. Uses
724     * sparse pseudoRemainder for remainder.
725     * @param S GenPolynomial.
726     * @return [ gcd(P,S), a ] with a*P + b*S = gcd(P,S).
727     */
728    public GenPolynomial<C>[] baseHalfExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
729        //if ( P == null ) {
730        //    throw new IllegalArgumentException("null P not allowed");
731        //}
732        GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
733        ret[0] = null;
734        ret[1] = null;
735        if (S == null || S.isZERO()) {
736            ret[0] = P;
737            ret[1] = P.ring.getONE();
738            return ret;
739        }
740        if (P == null || P.isZERO()) {
741            ret[0] = S;
742            ret[1] = S.ring.getZERO();
743            return ret;
744        }
745        if (P.ring.nvar != 1) {
746            throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials "
747                            + P.ring);
748        }
749        GenPolynomial<C> q = P;
750        GenPolynomial<C> r = S;
751        GenPolynomial<C> c1 = P.ring.getONE().copy();
752        GenPolynomial<C> d1 = P.ring.getZERO().copy();
753        while (!r.isZERO()) {
754            GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(q, r);
755            //q.divideAndRemainder(r);
756            q = qr[0];
757            GenPolynomial<C> x = c1.subtract(q.multiply(d1));
758            c1 = d1;
759            d1 = x;
760            q = r;
761            r = qr[1];
762        }
763        // normalize ldcf(q) to 1, i.e. make monic
764        C g = q.leadingBaseCoefficient();
765        if (g.isUnit()) {
766            C h = g.inverse();
767            q = q.multiply(h);
768            c1 = c1.multiply(h);
769        }
770        //assert ( ((c1.multiply(P)).remainder(S).equals(q) )); 
771        ret[0] = q;
772        ret[1] = c1;
773        return ret;
774    }
775
776
777    /**
778     * Univariate GenPolynomial greatest common divisor diophantine version.
779     * @param P univariate GenPolynomial.
780     * @param S univariate GenPolynomial.
781     * @param c univariate GenPolynomial.
782     * @return [ a, b ] with a*P + b*S = c and deg(a) < deg(S).
783     */
784    public GenPolynomial<C>[] baseGcdDiophant(GenPolynomial<C> P, GenPolynomial<C> S, GenPolynomial<C> c) {
785        GenPolynomial<C>[] egcd = baseExtendedGcd(P, S);
786        GenPolynomial<C> g = egcd[0];
787        GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(c, g);
788        if (!qr[1].isZERO()) {
789            throw new ArithmeticException("not solvable, r = " + qr[1] + ", c = " + c + ", g = " + g);
790        }
791        GenPolynomial<C> q = qr[0];
792        GenPolynomial<C> a = egcd[1].multiply(q);
793        GenPolynomial<C> b = egcd[2].multiply(q);
794        if (!a.isZERO() && a.degree(0) >= S.degree(0)) {
795            qr = PolyUtil.<C> basePseudoQuotientRemainder(a, S);
796            a = qr[1];
797            b = b.sum(P.multiply(qr[0]));
798        }
799        GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
800        ret[0] = a;
801        ret[1] = b;
802
803        if (debug) {
804            GenPolynomial<C> y = ret[0].multiply(P).sum(ret[1].multiply(S));
805            if (!y.equals(c)) {
806                System.out.println("P  = " + P);
807                System.out.println("S  = " + S);
808                System.out.println("c  = " + c);
809                System.out.println("a  = " + a);
810                System.out.println("b  = " + b);
811                System.out.println("y  = " + y);
812                throw new ArithmeticException("not diophant, x = " + y.subtract(c));
813            }
814        }
815        return ret;
816    }
817
818
819    /**
820     * Univariate GenPolynomial partial fraction decomposition.
821     * @param A univariate GenPolynomial.
822     * @param P univariate GenPolynomial.
823     * @param S univariate GenPolynomial.
824     * @return [ A0, Ap, As ] with A/(P*S) = A0 + Ap/P + As/S with deg(Ap) <
825     *         deg(P) and deg(As) < deg(S).
826     */
827    public GenPolynomial<C>[] basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, GenPolynomial<C> S) {
828        GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
829        ret[0] = null;
830        ret[1] = null;
831        ret[2] = null;
832        GenPolynomial<C> ps = P.multiply(S);
833        GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, ps);
834        ret[0] = qr[0];
835        GenPolynomial<C> r = qr[1];
836        GenPolynomial<C>[] diop = baseGcdDiophant(S, P, r); // switch arguments
837
838        //         GenPolynomial<C> x = diop[0].multiply(S).sum( diop[1].multiply(P) );
839        //         if ( !x.equals(r) ) {
840        //             System.out.println("r  = " + r);
841        //             System.out.println("x  = " + x);
842        //             throw new RuntimeException("not partial fraction, x = " + x);
843        //         }
844
845        ret[1] = diop[0];
846        ret[2] = diop[1];
847        if (ret[1].degree(0) >= P.degree(0)) {
848            qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[1], P);
849            ret[0] = ret[0].sum(qr[0]);
850            ret[1] = qr[1];
851        }
852        if (ret[2].degree(0) >= S.degree(0)) {
853            qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[2], S);
854            ret[0] = ret[0].sum(qr[0]);
855            ret[2] = qr[1];
856        }
857        return ret;
858    }
859
860
861    /**
862     * Univariate GenPolynomial partial fraction decomposition.
863     * @param A univariate GenPolynomial.
864     * @param P univariate GenPolynomial.
865     * @param e exponent for P.
866     * @return [ F0, F1, ..., Fe ] with A/(P^e) = sum( Fi / P^i ) with deg(Fi) <
867     *         deg(P).
868     */
869    public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e) {
870        if (A == null || P == null || e == 0) {
871            throw new IllegalArgumentException("null A, P or e = 0 not allowed");
872        }
873        List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>(e);
874        if (A.isZERO()) {
875            for (int i = 0; i < e; i++) {
876                pf.add(A);
877            }
878            return pf;
879        }
880        if (e == 1) {
881            GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P);
882            pf.add(qr[0]);
883            pf.add(qr[1]);
884            return pf;
885        }
886        GenPolynomial<C> a = A;
887        for (int j = e; j > 0; j--) {
888            GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(a, P);
889            a = qr[0];
890            pf.add(0, qr[1]);
891        }
892        pf.add(0, a);
893        return pf;
894    }
895
896
897    /**
898     * Univariate GenPolynomial partial fraction decomposition.
899     * @param A univariate GenPolynomial.
900     * @param D list of co-prime univariate GenPolynomials.
901     * @return [ A0, A1,..., An ] with A/prod(D) = A0 + sum( Ai/Di ) with
902     *         deg(Ai) < deg(Di).
903     */
904    public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D) {
905        if (D == null || A == null) {
906            throw new IllegalArgumentException("null A or D not allowed");
907        }
908        List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>(D.size() + 1);
909        if (A.isZERO() || D.size() == 0) {
910            pf.add(A);
911            for (int i = 0; i < D.size(); i++) {
912                pf.add(A);
913            }
914            return pf;
915        }
916        List<GenPolynomial<C>> Dp = new ArrayList<GenPolynomial<C>>(D.size() - 1);
917        GenPolynomial<C> P = A.ring.getONE();
918        GenPolynomial<C> d1 = null;
919        for (GenPolynomial<C> d : D) {
920            if (d1 == null) {
921                d1 = d;
922            } else {
923                P = P.multiply(d);
924                Dp.add(d);
925            }
926        }
927        GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P.multiply(d1));
928        GenPolynomial<C> A0 = qr[0];
929        GenPolynomial<C> r = qr[1];
930        if (D.size() == 1) {
931            pf.add(A0);
932            pf.add(r);
933            return pf;
934        }
935        GenPolynomial<C>[] diop = baseGcdDiophant(P, d1, r); // switch arguments
936        GenPolynomial<C> A1 = diop[0];
937        GenPolynomial<C> S = diop[1];
938        List<GenPolynomial<C>> Fr = basePartialFraction(S, Dp);
939        A0 = A0.sum(Fr.remove(0));
940        pf.add(A0);
941        pf.add(A1);
942        pf.addAll(Fr);
943        return pf;
944    }
945
946
947    /**
948     * Test for Univariate GenPolynomial partial fraction decomposition.
949     * @param A univariate GenPolynomial.
950     * @param D list of (co-prime) univariate GenPolynomials.
951     * @param F list of univariate GenPolynomials from a partial fraction
952     *            computation.
953     * @return true if A/prod(D) = F0 + sum( Fi/Di ) with deg(Fi) < deg(Di), Fi
954     *         in F, else false.
955     */
956    public boolean isBasePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D,
957                    List<GenPolynomial<C>> F) {
958        if (D == null || A == null || F == null) {
959            throw new IllegalArgumentException("null A, F or D not allowed");
960        }
961        if (D.size() != F.size() - 1) {
962            return false;
963        }
964        // A0*prod(D) + sum( Ai * Dip ), Dip = prod(D,j!=i)
965        GenPolynomial<C> P = A.ring.getONE();
966        for (GenPolynomial<C> d : D) {
967            P = P.multiply(d);
968        }
969        List<GenPolynomial<C>> Fp = new ArrayList<GenPolynomial<C>>(F);
970        GenPolynomial<C> A0 = Fp.remove(0).multiply(P);
971        //System.out.println("A0 = " + A0);
972        int j = 0;
973        for (GenPolynomial<C> Fi : Fp) {
974            P = A.ring.getONE();
975            int i = 0;
976            for (GenPolynomial<C> d : D) {
977                if (i != j) {
978                    P = P.multiply(d);
979                }
980                i++;
981            }
982            //System.out.println("Fi = " + Fi);
983            //System.out.println("P  = " + P);
984            A0 = A0.sum(Fi.multiply(P));
985            //System.out.println("A0 = " + A0);
986            j++;
987        }
988        boolean t = A.equals(A0);
989        if (!t) {
990            System.out.println("not isPartFrac = " + A0);
991        }
992        return t;
993    }
994
995
996    /**
997     * Test for Univariate GenPolynomial partial fraction decomposition.
998     * @param A univariate GenPolynomial.
999     * @param P univariate GenPolynomial.
1000     * @param e exponent for P.
1001     * @param F list of univariate GenPolynomials from a partial fraction
1002     *            computation.
1003     * @return true if A/(P^e) = F0 + sum( Fi / P^i ) with deg(Fi) < deg(P), Fi
1004     *         in F, else false.
1005     */
1006    public boolean isBasePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e,
1007                    List<GenPolynomial<C>> F) {
1008        if (A == null || P == null || F == null || e == 0) {
1009            throw new IllegalArgumentException("null A, P, F or e = 0 not allowed");
1010        }
1011        GenPolynomial<C> A0 = basePartialFractionValue(P, e, F);
1012        //         A.ring.getZERO();
1013        //         for ( GenPolynomial<C> Fi : F ) {
1014        //             A0 = A0.multiply(P);
1015        //             A0 = A0.sum(Fi);
1016        //             //System.out.println("A0 = " + A0);
1017        //         }
1018        boolean t = A.equals(A0);
1019        if (!t) {
1020            System.out.println("not isPartFrac = " + A0);
1021        }
1022        return t;
1023    }
1024
1025
1026    /**
1027     * Test for Univariate GenPolynomial partial fraction decomposition.
1028     * @param P univariate GenPolynomial.
1029     * @param e exponent for P.
1030     * @param F list of univariate GenPolynomials from a partial fraction
1031     *            computation.
1032     * @return (F0 + sum( Fi / P^i )) * P^e.
1033     */
1034    public GenPolynomial<C> basePartialFractionValue(GenPolynomial<C> P, int e, List<GenPolynomial<C>> F) {
1035        if (P == null || F == null || e == 0) {
1036            throw new IllegalArgumentException("null P, F or e = 0 not allowed");
1037        }
1038        GenPolynomial<C> A0 = P.ring.getZERO();
1039        for (GenPolynomial<C> Fi : F) {
1040            A0 = A0.multiply(P);
1041            A0 = A0.sum(Fi);
1042            //System.out.println("A0 = " + A0);
1043        }
1044        return A0;
1045    }
1046
1047}