/jas/src/main/java/edu/jas/ufd/GreatestCommonDivisorAbstract.java
http://symja.googlecode.com/ · Java · 1036 lines · 670 code · 95 blank · 271 comment · 227 complexity · ca22dd9499a0d42047f2a2579e9d7911 MD5 · raw file
- /*
- * $Id: GreatestCommonDivisorAbstract.java 3853 2012-01-01 19:32:34Z kredel $
- */
- package edu.jas.ufd;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.log4j.Logger;
- import edu.jas.poly.GenPolynomial;
- import edu.jas.poly.GenPolynomialRing;
- import edu.jas.poly.PolyUtil;
- import edu.jas.structure.GcdRingElem;
- import edu.jas.structure.RingFactory;
- /**
- * Greatest common divisor algorithms.
- * @author Heinz Kredel
- */
- public abstract class GreatestCommonDivisorAbstract<C extends GcdRingElem<C>> implements
- GreatestCommonDivisor<C> {
- private static final Logger logger = Logger.getLogger(GreatestCommonDivisorAbstract.class);
- private final boolean debug = logger.isDebugEnabled();
- /**
- * Get the String representation.
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return getClass().getName();
- }
- /**
- * GenPolynomial base coefficient content.
- * @param P GenPolynomial.
- * @return cont(P).
- */
- public C baseContent(GenPolynomial<C> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P.ring.getZEROCoefficient();
- }
- C d = null;
- for (C c : P.getMap().values()) {
- if (d == null) {
- d = c;
- } else {
- d = d.gcd(c);
- }
- if (d.isONE()) {
- return d;
- }
- }
- if ( d.signum() < 0 ) {
- d = d.negate();
- }
- return d;
- }
- /**
- * GenPolynomial base coefficient primitive part.
- * @param P GenPolynomial.
- * @return pp(P).
- */
- public GenPolynomial<C> basePrimitivePart(GenPolynomial<C> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P;
- }
- C d = baseContent(P);
- if (d.isONE()) {
- return P;
- }
- GenPolynomial<C> pp = P.divide(d);
- if (debug) {
- GenPolynomial<C> p = pp.multiply(d);
- if (!p.equals(P)) {
- throw new ArithmeticException("pp(p)*cont(p) != p: ");
- }
- }
- return pp;
- }
- /**
- * Univariate GenPolynomial greatest common divisor. Uses sparse
- * pseudoRemainder for remainder.
- * @param P univariate GenPolynomial.
- * @param S univariate GenPolynomial.
- * @return gcd(P,S).
- */
- public abstract GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S);
- /**
- * GenPolynomial recursive content.
- * @param P recursive GenPolynomial.
- * @return cont(P).
- */
- public GenPolynomial<C> recursiveContent(GenPolynomial<GenPolynomial<C>> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P.ring.getZEROCoefficient();
- }
- GenPolynomial<C> d = null;
- for (GenPolynomial<C> c : P.getMap().values()) {
- if (d == null) {
- d = c;
- } else {
- d = gcd(d, c); // go to recursion
- }
- if (d.isONE()) {
- return d;
- }
- }
- return d.abs();
- }
- /**
- * GenPolynomial recursive primitive part.
- * @param P recursive GenPolynomial.
- * @return pp(P).
- */
- public GenPolynomial<GenPolynomial<C>> recursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P;
- }
- GenPolynomial<C> d = recursiveContent(P);
- if (d.isONE()) {
- return P;
- }
- GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> recursiveDivide(P, d);
- return pp;
- }
- /**
- * GenPolynomial base recursive content.
- * @param P recursive GenPolynomial.
- * @return baseCont(P).
- */
- public C baseRecursiveContent(GenPolynomial<GenPolynomial<C>> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- GenPolynomialRing<C> cf = (GenPolynomialRing<C>) P.ring.coFac;
- return cf.coFac.getZERO();
- }
- C d = null;
- for (GenPolynomial<C> c : P.getMap().values()) {
- C cc = baseContent(c);
- if (d == null) {
- d = cc;
- } else {
- d = gcd(d, cc);
- }
- if (d.isONE()) {
- return d;
- }
- }
- if ( d.signum() < 0 ) {
- d = d.negate();
- }
- return d;
- }
- /**
- * GenPolynomial base recursive primitive part.
- * @param P recursive GenPolynomial.
- * @return basePP(P).
- */
- public GenPolynomial<GenPolynomial<C>> baseRecursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P;
- }
- C d = baseRecursiveContent(P);
- if (d.isONE()) {
- return P;
- }
- GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> baseRecursiveDivide(P, d);
- return pp;
- }
- /**
- * GenPolynomial recursive greatest common divisor. Uses pseudoRemainder for
- * remainder.
- * @param P recursive GenPolynomial.
- * @param S recursive GenPolynomial.
- * @return gcd(P,S).
- */
- public GenPolynomial<GenPolynomial<C>> recursiveGcd(GenPolynomial<GenPolynomial<C>> P,
- GenPolynomial<GenPolynomial<C>> S) {
- if (S == null || S.isZERO()) {
- return P;
- }
- if (P == null || P.isZERO()) {
- return S;
- }
- if (P.ring.nvar <= 1) {
- return recursiveUnivariateGcd(P, S);
- }
- // distributed polynomials gcd
- GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
- RingFactory<GenPolynomial<C>> rrfac = rfac.coFac;
- GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rrfac;
- GenPolynomialRing<C> dfac = cfac.extend(rfac.nvar);
- GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac, P);
- GenPolynomial<C> Sd = PolyUtil.<C> distribute(dfac, S);
- GenPolynomial<C> Dd = gcd(Pd, Sd);
- // convert to recursive
- GenPolynomial<GenPolynomial<C>> C = PolyUtil.<C> recursive(rfac, Dd);
- return C;
- }
- /**
- * Univariate GenPolynomial recursive greatest common divisor. Uses
- * pseudoRemainder for remainder.
- * @param P univariate recursive GenPolynomial.
- * @param S univariate recursive GenPolynomial.
- * @return gcd(P,S).
- */
- public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P,
- GenPolynomial<GenPolynomial<C>> S);
- /**
- * GenPolynomial content.
- * @param P GenPolynomial.
- * @return cont(P).
- */
- public GenPolynomial<C> content(GenPolynomial<C> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- GenPolynomialRing<C> pfac = P.ring;
- if (pfac.nvar <= 1) {
- // baseContent not possible by return type
- throw new IllegalArgumentException(this.getClass().getName()
- + " use baseContent for univariate polynomials");
- }
- GenPolynomialRing<C> cfac = pfac.contract(1);
- GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
- GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
- GenPolynomial<C> D = recursiveContent(Pr);
- return D;
- }
- /**
- * GenPolynomial primitive part.
- * @param P GenPolynomial.
- * @return pp(P).
- */
- public GenPolynomial<C> primitivePart(GenPolynomial<C> P) {
- if (P == null) {
- throw new IllegalArgumentException(this.getClass().getName() + " P != null");
- }
- if (P.isZERO()) {
- return P;
- }
- GenPolynomialRing<C> pfac = P.ring;
- if (pfac.nvar <= 1) {
- return basePrimitivePart(P);
- }
- GenPolynomialRing<C> cfac = pfac.contract(1);
- GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
- GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
- GenPolynomial<GenPolynomial<C>> PP = recursivePrimitivePart(Pr);
- GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PP);
- return D;
- }
- /**
- * GenPolynomial division. Indirection to GenPolynomial method.
- * @param a GenPolynomial.
- * @param b coefficient.
- * @return a/b.
- */
- public GenPolynomial<C> divide(GenPolynomial<C> a, C b) {
- if (b == null || b.isZERO()) {
- throw new IllegalArgumentException(this.getClass().getName() + " division by zero");
- }
- if (a == null || a.isZERO()) {
- return a;
- }
- return a.divide(b);
- }
- /**
- * Coefficient greatest common divisor. Indirection to coefficient method.
- * @param a coefficient.
- * @param b coefficient.
- * @return gcd(a,b).
- */
- public C gcd(C a, C b) {
- if (b == null || b.isZERO()) {
- return a;
- }
- if (a == null || a.isZERO()) {
- return b;
- }
- return a.gcd(b);
- }
- /**
- * GenPolynomial greatest common divisor.
- * @param P GenPolynomial.
- * @param S GenPolynomial.
- * @return gcd(P,S).
- */
- public GenPolynomial<C> gcd(GenPolynomial<C> P, GenPolynomial<C> S) {
- if (S == null || S.isZERO()) {
- return P;
- }
- if (P == null || P.isZERO()) {
- return S;
- }
- GenPolynomialRing<C> pfac = P.ring;
- if (pfac.nvar <= 1) {
- GenPolynomial<C> T = baseGcd(P, S);
- return T;
- }
- GenPolynomialRing<C> cfac = pfac.contract(1);
- GenPolynomialRing<GenPolynomial<C>> rfac;
- if ( pfac.getVars() != null && pfac.getVars().length > 0 ) {
- String[] v = new String[] { pfac.getVars()[pfac.nvar-1] };
- rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1, v);
- } else {
- rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
- }
- GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
- GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
- GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateGcd(Pr, Sr);
- GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
- return D;
- }
- /**
- * GenPolynomial least common multiple.
- * @param P GenPolynomial.
- * @param S GenPolynomial.
- * @return lcm(P,S).
- */
- public GenPolynomial<C> lcm(GenPolynomial<C> P, GenPolynomial<C> S) {
- if (S == null || S.isZERO()) {
- return S;
- }
- if (P == null || P.isZERO()) {
- return P;
- }
- GenPolynomial<C> C = gcd(P, S);
- GenPolynomial<C> A = P.multiply(S);
- return PolyUtil.<C> basePseudoDivide(A, C);
- }
- /**
- * List of GenPolynomials greatest common divisor.
- * @param A non empty list of GenPolynomials.
- * @return gcd(A_i).
- */
- public GenPolynomial<C> gcd(List<GenPolynomial<C>> A) {
- if (A == null || A.isEmpty()) {
- throw new IllegalArgumentException("A may not be empty");
- }
- GenPolynomial<C> g = A.get(0);
- for ( int i = 1; i < A.size(); i++ ) {
- GenPolynomial<C> f = A.get(i);
- g = gcd(g,f);
- }
- return g;
- }
- /**
- * Univariate GenPolynomial resultant.
- * @param P univariate GenPolynomial.
- * @param S univariate GenPolynomial.
- * @return res(P,S).
- * @throws UnsupportedOperationException if there is no implementation in the sub-class.
- */
- public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) {
- // can not be abstract
- throw new UnsupportedOperationException("not implmented");
- }
- /**
- * Univariate GenPolynomial recursive resultant.
- * @param P univariate recursive GenPolynomial.
- * @param S univariate recursive GenPolynomial.
- * @return res(P,S).
- * @throws UnsupportedOperationException if there is no implementation in the sub-class.
- */
- public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P,
- GenPolynomial<GenPolynomial<C>> S) {
- // can not be abstract
- throw new UnsupportedOperationException("not implmented");
- }
- /**
- * GenPolynomial recursive resultant.
- * @param P univariate recursive GenPolynomial.
- * @param S univariate recursive GenPolynomial.
- * @return res(P,S).
- * @throws UnsupportedOperationException if there is no implementation in the sub-class.
- */
- public GenPolynomial<GenPolynomial<C>> recursiveResultant(GenPolynomial<GenPolynomial<C>> P,
- GenPolynomial<GenPolynomial<C>> S) {
- if (S == null || S.isZERO()) {
- return S;
- }
- if (P == null || P.isZERO()) {
- return P;
- }
- GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
- GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rfac.coFac;
- GenPolynomialRing<C> dfac = cfac.extend(rfac.getVars());
- GenPolynomial<C> Pp = PolyUtil.<C> distribute(dfac, P);
- GenPolynomial<C> Sp = PolyUtil.<C> distribute(dfac, S);
- GenPolynomial<C> res = resultant(Pp,Sp);
- GenPolynomial<GenPolynomial<C>> Rr = PolyUtil.<C> recursive(rfac, res);
- return Rr;
- }
- /**
- * GenPolynomial resultant.
- * The input polynomials are considered as univariate polynomials in the main variable.
- * @param P GenPolynomial.
- * @param S GenPolynomial.
- * @return res(P,S).
- * @see edu.jas.ufd.GreatestCommonDivisorSubres#recursiveResultant
- * @throws UnsupportedOperationException if there is no implementation in the sub-class.
- */
- public GenPolynomial<C> resultant(GenPolynomial<C> P, GenPolynomial<C> S) {
- if (S == null || S.isZERO()) {
- return S;
- }
- if (P == null || P.isZERO()) {
- return P;
- }
- // no more hacked: GreatestCommonDivisorSubres<C> ufd_sr = new GreatestCommonDivisorSubres<C>();
- GenPolynomialRing<C> pfac = P.ring;
- if (pfac.nvar <= 1) {
- return baseResultant(P, S);
- }
- GenPolynomialRing<C> cfac = pfac.contract(1);
- GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
- GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
- GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
- GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateResultant(Pr, Sr);
- GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
- return D;
- }
- /**
- * GenPolynomial co-prime list.
- * @param A list of GenPolynomials.
- * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
- * a in A there exists b in B with b|a. B does not contain zero or
- * constant polynomials.
- */
- public List<GenPolynomial<C>> coPrime(List<GenPolynomial<C>> A) {
- if (A == null || A.isEmpty()) {
- return A;
- }
- List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(A.size());
- // make a coprime to rest of list
- GenPolynomial<C> a = A.get(0);
- //System.out.println("a = " + a);
- if (!a.isZERO() && !a.isConstant()) {
- for (int i = 1; i < A.size(); i++) {
- GenPolynomial<C> b = A.get(i);
- GenPolynomial<C> g = gcd(a, b).abs();
- if (!g.isONE()) {
- a = PolyUtil.<C> basePseudoDivide(a, g);
- b = PolyUtil.<C> basePseudoDivide(b, g);
- GenPolynomial<C> gp = gcd(a, g).abs();
- while (!gp.isONE()) {
- a = PolyUtil.<C> basePseudoDivide(a, gp);
- g = PolyUtil.<C> basePseudoDivide(g, gp);
- B.add(g); // gcd(a,g) == 1
- g = gp;
- gp = gcd(a, gp).abs();
- }
- if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
- B.add(g); // gcd(a,g) == 1
- }
- }
- if (!b.isZERO() && !b.isConstant()) {
- B.add(b); // gcd(a,b) == 1
- }
- }
- } else {
- B.addAll(A.subList(1, A.size()));
- }
- // make rest coprime
- B = coPrime(B);
- //System.out.println("B = " + B);
- if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
- a = a.abs();
- B.add(a);
- }
- return B;
- }
- /**
- * GenPolynomial co-prime list.
- * @param A list of GenPolynomials.
- * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
- * a in A there exists b in B with b|a. B does not contain zero or
- * constant polynomials.
- */
- public List<GenPolynomial<C>> coPrimeRec(List<GenPolynomial<C>> A) {
- if (A == null || A.isEmpty()) {
- return A;
- }
- List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>();
- // make a co-prime to rest of list
- for (GenPolynomial<C> a : A) {
- //System.out.println("a = " + a);
- B = coPrime(a, B);
- //System.out.println("B = " + B);
- }
- return B;
- }
- /**
- * GenPolynomial co-prime list.
- * @param a GenPolynomial.
- * @param P co-prime list of GenPolynomials.
- * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a
- * there exists b in P with b|a. B does not contain zero or constant
- * polynomials.
- */
- public List<GenPolynomial<C>> coPrime(GenPolynomial<C> a, List<GenPolynomial<C>> P) {
- if (a == null || a.isZERO() || a.isConstant()) {
- return P;
- }
- List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(P.size() + 1);
- // make a coprime to elements of the list P
- for (int i = 0; i < P.size(); i++) {
- GenPolynomial<C> b = P.get(i);
- GenPolynomial<C> g = gcd(a, b).abs();
- if (!g.isONE()) {
- a = PolyUtil.<C> basePseudoDivide(a, g);
- b = PolyUtil.<C> basePseudoDivide(b, g);
- // make g co-prime to new a, g is co-prime to c != b in P, B
- GenPolynomial<C> gp = gcd(a, g).abs();
- while (!gp.isONE()) {
- a = PolyUtil.<C> basePseudoDivide(a, gp);
- g = PolyUtil.<C> basePseudoDivide(g, gp);
- if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
- B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
- }
- g = gp;
- gp = gcd(a, gp).abs();
- }
- // make new g co-prime to new b
- gp = gcd(b, g).abs();
- while (!gp.isONE()) {
- b = PolyUtil.<C> basePseudoDivide(b, gp);
- g = PolyUtil.<C> basePseudoDivide(g, gp);
- if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
- B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
- }
- g = gp;
- gp = gcd(b, gp).abs();
- }
- if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
- B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
- }
- }
- if (!b.isZERO() && !b.isConstant() /*&& !B.contains(b)*/) {
- B.add(b); // gcd(a,b) == 1 and gcd(b,c) == 1 for c != b in P, B
- }
- }
- if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
- B.add(a);
- }
- return B;
- }
- /**
- * GenPolynomial test for co-prime list.
- * @param A list of GenPolynomials.
- * @return true if gcd(b,c) = 1 for all b != c in B, else false.
- */
- public boolean isCoPrime(List<GenPolynomial<C>> A) {
- if (A == null || A.isEmpty()) {
- return true;
- }
- if (A.size() == 1) {
- return true;
- }
- for (int i = 0; i < A.size(); i++) {
- GenPolynomial<C> a = A.get(i);
- for (int j = i + 1; j < A.size(); j++) {
- GenPolynomial<C> b = A.get(j);
- GenPolynomial<C> g = gcd(a, b);
- if (!g.isONE()) {
- System.out.println("not co-prime, a: " + a);
- System.out.println("not co-prime, b: " + b);
- System.out.println("not co-prime, g: " + g);
- return false;
- }
- }
- }
- return true;
- }
- /**
- * GenPolynomial test for co-prime list of given list.
- * @param A list of GenPolynomials.
- * @param P list of co-prime GenPolynomials.
- * @return true if isCoPrime(P) and for all a in A exists p in P with p | a,
- * else false.
- */
- public boolean isCoPrime(List<GenPolynomial<C>> P, List<GenPolynomial<C>> A) {
- if (!isCoPrime(P)) {
- return false;
- }
- if (A == null || A.isEmpty()) {
- return true;
- }
- for (GenPolynomial<C> q : A) {
- if (q.isZERO() || q.isConstant()) {
- continue;
- }
- boolean divides = false;
- for (GenPolynomial<C> p : P) {
- GenPolynomial<C> a = PolyUtil.<C> baseSparsePseudoRemainder(q, p);
- if (a.isZERO()) { // p divides q
- divides = true;
- break;
- }
- }
- if (!divides) {
- System.out.println("no divisor for: " + q);
- return false;
- }
- }
- return true;
- }
- /**
- * Univariate GenPolynomial extended greatest common divisor. Uses sparse
- * pseudoRemainder for remainder.
- * @param P univariate GenPolynomial.
- * @param S univariate GenPolynomial.
- * @return [ gcd(P,S), a, b ] with a*P + b*S = gcd(P,S).
- */
- public GenPolynomial<C>[] baseExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
- //return P.egcd(S);
- GenPolynomial<C>[] hegcd = baseHalfExtendedGcd(P,S);
- GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
- ret[0] = hegcd[0];
- ret[1] = hegcd[1];
- GenPolynomial<C> x = hegcd[0].subtract( hegcd[1].multiply(P) );
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(x, S);
- // assert qr[1].isZERO()
- ret[2] = qr[0];
- return ret;
- }
- /**
- * Univariate GenPolynomial half extended greatest comon divisor.
- * Uses sparse pseudoRemainder for remainder.
- * @param S GenPolynomial.
- * @return [ gcd(P,S), a ] with a*P + b*S = gcd(P,S).
- */
- public GenPolynomial<C>[] baseHalfExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
- //if ( P == null ) {
- // throw new IllegalArgumentException("null P not allowed");
- //}
- GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
- ret[0] = null;
- ret[1] = null;
- if ( S == null || S.isZERO() ) {
- ret[0] = P;
- ret[1] = P.ring.getONE();
- return ret;
- }
- if ( P == null || P.isZERO() ) {
- ret[0] = S;
- ret[1] = S.ring.getZERO();
- return ret;
- }
- if ( P.ring.nvar != 1 ) {
- throw new IllegalArgumentException(this.getClass().getName()
- + " not univariate polynomials " + P.ring);
- }
- GenPolynomial<C> q = P;
- GenPolynomial<C> r = S;
- GenPolynomial<C> c1 = P.ring.getONE().clone();
- GenPolynomial<C> d1 = P.ring.getZERO().clone();
- while ( !r.isZERO() ) {
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(q, r);
- //q.divideAndRemainder(r);
- q = qr[0];
- GenPolynomial<C> x = c1.subtract( q.multiply(d1) );
- c1 = d1;
- d1 = x;
- q = r;
- r = qr[1];
- }
- // normalize ldcf(q) to 1, i.e. make monic
- C g = q.leadingBaseCoefficient();
- if ( g.isUnit() ) {
- C h = g.inverse();
- q = q.multiply( h );
- c1 = c1.multiply( h );
- }
- //assert ( ((c1.multiply(P)).remainder(S).equals(q) ));
- ret[0] = q;
- ret[1] = c1;
- return ret;
- }
- /**
- * Univariate GenPolynomial greatest common divisor diophantine version.
- * @param P univariate GenPolynomial.
- * @param S univariate GenPolynomial.
- * @param c univariate GenPolynomial.
- * @return [ a, b ] with a*P + b*S = c and deg(a) < deg(S).
- */
- public GenPolynomial<C>[] baseGcdDiophant(GenPolynomial<C> P, GenPolynomial<C> S, GenPolynomial<C> c) {
- GenPolynomial<C>[] egcd = baseExtendedGcd(P,S);
- GenPolynomial<C> g = egcd[0];
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(c, g);
- if ( !qr[1].isZERO() ) {
- throw new ArithmeticException("not solvable, r = " + qr[1] + ", c = " + c + ", g = " + g);
- }
- GenPolynomial<C> q = qr[0];
- GenPolynomial<C> a = egcd[1].multiply(q);
- GenPolynomial<C> b = egcd[2].multiply(q);
- if ( !a.isZERO() && a.degree(0) >= S.degree(0) ) {
- qr = PolyUtil.<C> basePseudoQuotientRemainder(a, S);
- a = qr[1];
- b = b.sum( P.multiply( qr[0] ) );
- }
- GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
- ret[0] = a;
- ret[1] = b;
- if ( true ) {
- return ret;
- }
- GenPolynomial<C> y = ret[0].multiply(P).sum( ret[1].multiply(S) );
- if ( !y.equals(c) ) {
- System.out.println("P = " + P);
- System.out.println("S = " + S);
- System.out.println("c = " + c);
- System.out.println("a = " + a);
- System.out.println("b = " + b);
- System.out.println("y = " + y);
- throw new ArithmeticException("not diophant, x = " + y.subtract(c));
- }
- return ret;
- }
- /**
- * Univariate GenPolynomial partial fraction decomposition.
- * @param A univariate GenPolynomial.
- * @param P univariate GenPolynomial.
- * @param S univariate GenPolynomial.
- * @return [ A0, Ap, As ] with A/(P*S) = A0 + Ap/P + As/S with deg(Ap) < deg(P) and deg(As) < deg(S).
- */
- public GenPolynomial<C>[] basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, GenPolynomial<C> S) {
- GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
- ret[0] = null;
- ret[1] = null;
- ret[2] = null;
- GenPolynomial<C> ps = P.multiply(S);
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, ps);
- ret[0] = qr[0];
- GenPolynomial<C> r = qr[1];
- GenPolynomial<C>[] diop = baseGcdDiophant(S,P,r); // switch arguments
- // GenPolynomial<C> x = diop[0].multiply(S).sum( diop[1].multiply(P) );
- // if ( !x.equals(r) ) {
- // System.out.println("r = " + r);
- // System.out.println("x = " + x);
- // throw new RuntimeException("not partial fraction, x = " + x);
- // }
- ret[1] = diop[0];
- ret[2] = diop[1];
- if ( ret[1].degree(0) >= P.degree(0) ) {
- qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[1], P);
- ret[0] = ret[0].sum( qr[0] );
- ret[1] = qr[1];
- }
- if ( ret[2].degree(0) >= S.degree(0) ) {
- qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[2], S);
- ret[0] = ret[0].sum( qr[0] );
- ret[2] = qr[1];
- }
- return ret;
- }
- /**
- * Univariate GenPolynomial partial fraction decomposition.
- * @param A univariate GenPolynomial.
- * @param P univariate GenPolynomial.
- * @param e exponent for P.
- * @return [ F0, F1, ..., Fe ] with A/(P^e) = sum( Fi / P^i ) with deg(Fi) < deg(P).
- */
- public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e) {
- if ( A == null || P == null || e == 0 ) {
- throw new IllegalArgumentException("null A, P or e = 0 not allowed");
- }
- List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>( e );
- if ( A.isZERO() ) {
- for ( int i = 0; i < e; i++ ) {
- pf.add(A);
- }
- return pf;
- }
- if ( e == 1 ) {
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P);
- pf.add(qr[0]);
- pf.add(qr[1]);
- return pf;
- }
- GenPolynomial<C> a = A;
- for ( int j = e; j > 0; j-- ) {
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(a, P);
- a = qr[0];
- pf.add(0,qr[1]);
- }
- pf.add(0,a);
- return pf;
- }
- /**
- * Univariate GenPolynomial partial fraction decomposition.
- * @param A univariate GenPolynomial.
- * @param D list of co-prime univariate GenPolynomials.
- * @return [ A0, A1,..., An ] with A/prod(D) = A0 + sum( Ai/Di ) with deg(Ai) < deg(Di).
- */
- public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D) {
- if ( D == null || A == null ) {
- throw new IllegalArgumentException("null A or D not allowed");
- }
- List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>( D.size()+1 );
- if ( A.isZERO() || D.size() == 0 ) {
- pf.add(A);
- for ( int i = 0; i < D.size(); i++ ) {
- pf.add(A);
- }
- return pf;
- }
- List<GenPolynomial<C>> Dp = new ArrayList<GenPolynomial<C>>( D.size()-1 );
- GenPolynomial<C> P = A.ring.getONE();
- GenPolynomial<C> d1 = null;
- for ( GenPolynomial<C> d : D ) {
- if ( d1 == null ) {
- d1 = d;
- } else {
- P = P.multiply(d);
- Dp.add(d);
- }
- }
- GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P.multiply(d1));
- GenPolynomial<C> A0 = qr[0];
- GenPolynomial<C> r = qr[1];
- if ( D.size() == 1 ) {
- pf.add(A0);
- pf.add(r);
- return pf;
- }
- GenPolynomial<C>[] diop = baseGcdDiophant(P,d1,r); // switch arguments
- GenPolynomial<C> A1 = diop[0];
- GenPolynomial<C> S = diop[1];
- List<GenPolynomial<C>> Fr = basePartialFraction(S,Dp);
- A0 = A0.sum( Fr.remove(0) );
- pf.add(A0);
- pf.add(A1);
- pf.addAll(Fr);
- return pf;
- }
- /**
- * Test for Univariate GenPolynomial partial fraction decomposition.
- * @param A univariate GenPolynomial.
- * @param D list of (co-prime) univariate GenPolynomials.
- * @param F list of univariate GenPolynomials from a partial fraction computation.
- * @return true if A/prod(D) = F0 + sum( Fi/Di ) with deg(Fi) < deg(Di), Fi in F,
- else false.
- */
- public boolean isBasePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D, List<GenPolynomial<C>> F) {
- if ( D == null || A == null || F == null ) {
- throw new IllegalArgumentException("null A, F or D not allowed");
- }
- if ( D.size() != F.size()-1 ) {
- return false;
- }
- // A0*prod(D) + sum( Ai * Dip ), Dip = prod(D,j!=i)
- GenPolynomial<C> P = A.ring.getONE();
- for ( GenPolynomial<C> d : D ) {
- P = P.multiply(d);
- }
- List<GenPolynomial<C>> Fp = new ArrayList<GenPolynomial<C>>( F );
- GenPolynomial<C> A0 = Fp.remove(0).multiply(P);
- //System.out.println("A0 = " + A0);
- int j = 0;
- for ( GenPolynomial<C> Fi : Fp ) {
- P = A.ring.getONE();
- int i = 0;
- for ( GenPolynomial<C> d : D ) {
- if ( i != j ) {
- P = P.multiply(d);
- }
- i++;
- }
- //System.out.println("Fi = " + Fi);
- //System.out.println("P = " + P);
- A0 = A0.sum( Fi.multiply(P) );
- //System.out.println("A0 = " + A0);
- j++;
- }
- boolean t = A.equals(A0);
- if ( ! t ) {
- System.out.println("not isPartFrac = " + A0);
- }
- return t;
- }
- /**
- * Test for Univariate GenPolynomial partial fraction decomposition.
- * @param A univariate GenPolynomial.
- * @param P univariate GenPolynomial.
- * @param e exponent for P.
- * @param F list of univariate GenPolynomials from a partial fraction computation.
- * @return true if A/(P^e) = F0 + sum( Fi / P^i ) with deg(Fi) < deg(P), Fi in F,
- else false.
- */
- public boolean isBasePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e, List<GenPolynomial<C>> F) {
- if ( A == null || P == null || F == null || e == 0 ) {
- throw new IllegalArgumentException("null A, P, F or e = 0 not allowed");
- }
- GenPolynomial<C> A0 = basePartialFractionValue(P,e,F);
- // A.ring.getZERO();
- // for ( GenPolynomial<C> Fi : F ) {
- // A0 = A0.multiply(P);
- // A0 = A0.sum(Fi);
- // //System.out.println("A0 = " + A0);
- // }
- boolean t = A.equals(A0);
- if ( ! t ) {
- System.out.println("not isPartFrac = " + A0);
- }
- return t;
- }
- /**
- * Test for Univariate GenPolynomial partial fraction decomposition.
- * @param P univariate GenPolynomial.
- * @param e exponent for P.
- * @param F list of univariate GenPolynomials from a partial fraction computation.
- * @return (F0 + sum( Fi / P^i )) * P^e.
- */
- public GenPolynomial<C> basePartialFractionValue(GenPolynomial<C> P, int e, List<GenPolynomial<C>> F) {
- if ( P == null || F == null || e == 0 ) {
- throw new IllegalArgumentException("null P, F or e = 0 not allowed");
- }
- GenPolynomial<C> A0 = P.ring.getZERO();
- for ( GenPolynomial<C> Fi : F ) {
- A0 = A0.multiply(P);
- A0 = A0.sum(Fi);
- //System.out.println("A0 = " + A0);
- }
- return A0;
- }
- }