
edu.jas.poly.PolyUtil Maven / Gradle / Ivy
The newest version!
/*
* $Id: PolyUtil.java 4378 2013-04-26 16:50:33Z kredel $
*/
package edu.jas.poly;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import edu.jas.arith.BigComplex;
import edu.jas.arith.BigDecimal;
import edu.jas.arith.BigInteger;
import edu.jas.arith.BigRational;
import edu.jas.arith.ModInteger;
import edu.jas.arith.ModIntegerRing;
import edu.jas.arith.Modular;
import edu.jas.arith.ModularRingFactory;
import edu.jas.arith.Product;
import edu.jas.arith.ProductRing;
import edu.jas.arith.Rational;
import edu.jas.structure.Element;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.RingElem;
import edu.jas.structure.RingFactory;
import edu.jas.structure.UnaryFunctor;
import edu.jas.util.ListUtil;
/**
* Polynomial utilities, for example conversion between different
* representations, evaluation and interpolation.
* @author Heinz Kredel
*/
public class PolyUtil {
private static final Logger logger = Logger.getLogger(PolyUtil.class);
private static boolean debug = logger.isDebugEnabled();
/**
* Recursive representation. Represent as polynomial in i variables with
* coefficients in n-i variables. Works for arbitrary term orders.
* @param coefficient type.
* @param rfac recursive polynomial ring factory.
* @param A polynomial to be converted.
* @return Recursive represenations of this in the ring rfac.
*/
public static > GenPolynomial> recursive(
GenPolynomialRing> rfac, GenPolynomial A) {
GenPolynomial> B = rfac.getZERO().copy();
if (A.isZERO()) {
return B;
}
int i = rfac.nvar;
GenPolynomial zero = rfac.getZEROCoefficient();
Map> Bv = B.val; //getMap();
for (Map.Entry y : A.getMap().entrySet()) {
ExpVector e = y.getKey();
C a = y.getValue();
ExpVector f = e.contract(0, i);
ExpVector g = e.contract(i, e.length() - i);
GenPolynomial p = Bv.get(f);
if (p == null) {
p = zero;
}
p = p.sum(a, g);
Bv.put(f, p);
}
return B;
}
/**
* Distribute a recursive polynomial to a generic polynomial. Works for
* arbitrary term orders.
* @param coefficient type.
* @param dfac combined polynomial ring factory of coefficients and this.
* @param B polynomial to be converted.
* @return distributed polynomial.
*/
public static > GenPolynomial distribute(GenPolynomialRing dfac,
GenPolynomial> B) {
GenPolynomial C = dfac.getZERO().copy();
if (B.isZERO()) {
return C;
}
Map Cm = C.val; //getMap();
for (Map.Entry> y : B.getMap().entrySet()) {
ExpVector e = y.getKey();
GenPolynomial A = y.getValue();
for (Map.Entry x : A.val.entrySet()) {
ExpVector f = x.getKey();
C b = x.getValue();
ExpVector g = e.combine(f);
assert (Cm.get(g) != null);
//if ( Cm.get(g) != null ) { // todo assert, done
// throw new RuntimeException("PolyUtil debug error");
//}
Cm.put(g, b);
}
}
return C;
}
/**
* Recursive representation. Represent as polynomials in i variables with
* coefficients in n-i variables. Works for arbitrary term orders.
* @param coefficient type.
* @param rfac recursive polynomial ring factory.
* @param L list of polynomials to be converted.
* @return Recursive represenations of the list in the ring rfac.
*/
public static > List>> recursive(
GenPolynomialRing> rfac, List> L) {
return ListUtil., GenPolynomial>> map(L, new DistToRec(rfac));
}
/**
* Distribute a recursive polynomial list to a generic polynomial list.
* Works for arbitrary term orders.
* @param coefficient type.
* @param dfac combined polynomial ring factory of coefficients and this.
* @param L list of polynomials to be converted.
* @return distributed polynomial list.
*/
public static > List> distribute(GenPolynomialRing dfac,
List>> L) {
return ListUtil.>, GenPolynomial> map(L, new RecToDist(dfac));
}
/**
* BigInteger from ModInteger coefficients, symmetric. Represent as
* polynomial with BigInteger coefficients by removing the modules and
* making coefficients symmetric to 0.
* @param fac result polynomial factory.
* @param A polynomial with ModInteger coefficients to be converted.
* @return polynomial with BigInteger coefficients.
*/
public static & Modular> GenPolynomial integerFromModularCoefficients(
GenPolynomialRing fac, GenPolynomial A) {
return PolyUtil. map(fac, A, new ModSymToInt());
}
/**
* BigInteger from ModInteger coefficients, symmetric. Represent as
* polynomial with BigInteger coefficients by removing the modules and
* making coefficients symmetric to 0.
* @param fac result polynomial factory.
* @param L list of polynomials with ModInteger coefficients to be
* converted.
* @return list of polynomials with BigInteger coefficients.
*/
public static & Modular> List> integerFromModularCoefficients(
final GenPolynomialRing fac, List> L) {
return ListUtil., GenPolynomial> map(L,
new UnaryFunctor, GenPolynomial>() {
public GenPolynomial eval(GenPolynomial c) {
return PolyUtil. integerFromModularCoefficients(fac, c);
}
});
}
/**
* BigInteger from ModInteger coefficients, positive. Represent as
* polynomial with BigInteger coefficients by removing the modules.
* @param fac result polynomial factory.
* @param A polynomial with ModInteger coefficients to be converted.
* @return polynomial with BigInteger coefficients.
*/
public static & Modular> GenPolynomial integerFromModularCoefficientsPositive(
GenPolynomialRing fac, GenPolynomial A) {
return PolyUtil. map(fac, A, new ModToInt());
}
/**
* BigInteger from BigRational coefficients. Represent as polynomial with
* BigInteger coefficients by multiplication with the lcm of the numerators
* of the BigRational coefficients.
* @param fac result polynomial factory.
* @param A polynomial with BigRational coefficients to be converted.
* @return polynomial with BigInteger coefficients.
*/
public static GenPolynomial integerFromRationalCoefficients(
GenPolynomialRing fac, GenPolynomial A) {
if (A == null || A.isZERO()) {
return fac.getZERO();
}
java.math.BigInteger c = null;
int s = 0;
// lcm of denominators
for (BigRational y : A.val.values()) {
java.math.BigInteger x = y.denominator();
// c = lcm(c,x)
if (c == null) {
c = x;
s = x.signum();
} else {
java.math.BigInteger d = c.gcd(x);
c = c.multiply(x.divide(d));
}
}
if (s < 0) {
c = c.negate();
}
return PolyUtil. map(fac, A, new RatToInt(c));
}
/**
* BigInteger from BigRational coefficients. Represent as polynomial with
* BigInteger coefficients by multiplication with the gcd of the numerators
* and the lcm of the denominators of the BigRational coefficients.
* Author: Axel Kramer
* @param fac result polynomial factory.
* @param A polynomial with BigRational coefficients to be converted.
* @return Object[] with 3 entries: [0]->gcd [1]->lcm and [2]->polynomial
* with BigInteger coefficients.
*/
public static Object[] integerFromRationalCoefficientsFactor(GenPolynomialRing fac,
GenPolynomial A) {
Object[] result = new Object[3];
if (A == null || A.isZERO()) {
result[0] = java.math.BigInteger.ONE;
result[1] = java.math.BigInteger.ZERO;
result[2] = fac.getZERO();
return result;
}
java.math.BigInteger gcd = null;
java.math.BigInteger lcm = null;
int sLCM = 0;
int sGCD = 0;
// lcm of denominators
for (BigRational y : A.val.values()) {
java.math.BigInteger numerator = y.numerator();
java.math.BigInteger denominator = y.denominator();
// lcm = lcm(lcm,x)
if (lcm == null) {
lcm = denominator;
sLCM = denominator.signum();
} else {
java.math.BigInteger d = lcm.gcd(denominator);
lcm = lcm.multiply(denominator.divide(d));
}
// gcd = gcd(gcd,x)
if (gcd == null) {
gcd = numerator;
sGCD = numerator.signum();
} else {
gcd = gcd.gcd(numerator);
}
}
if (sLCM < 0) {
lcm = lcm.negate();
}
if (sGCD < 0) {
gcd = gcd.negate();
}
result[0] = gcd;
result[1] = lcm;
result[2] = PolyUtil. map(fac, A, new RatToIntFactor(gcd, lcm));
return result;
}
/**
* BigInteger from BigRational coefficients. Represent as list of
* polynomials with BigInteger coefficients by multiplication with the lcm
* of the numerators of the BigRational coefficients of each polynomial.
* @param fac result polynomial factory.
* @param L list of polynomials with BigRational coefficients to be
* converted.
* @return polynomial list with BigInteger coefficients.
*/
public static List> integerFromRationalCoefficients(
GenPolynomialRing fac, List> L) {
return ListUtil., GenPolynomial> map(L, new RatToIntPoly(fac));
}
/**
* From BigInteger coefficients. Represent as polynomial with type C
* coefficients, e.g. ModInteger or BigRational.
* @param coefficient type.
* @param fac result polynomial factory.
* @param A polynomial with BigInteger coefficients to be converted.
* @return polynomial with type C coefficients.
*/
public static > GenPolynomial fromIntegerCoefficients(GenPolynomialRing fac,
GenPolynomial A) {
return PolyUtil. map(fac, A, new FromInteger(fac.coFac));
}
/**
* From BigInteger coefficients. Represent as list of polynomials with type
* C coefficients, e.g. ModInteger or BigRational.
* @param coefficient type.
* @param fac result polynomial factory.
* @param L list of polynomials with BigInteger coefficients to be
* converted.
* @return list of polynomials with type C coefficients.
*/
public static > List> fromIntegerCoefficients(
GenPolynomialRing fac, List> L) {
return ListUtil., GenPolynomial> map(L, new FromIntegerPoly(fac));
}
/**
* Convert to decimal coefficients.
* @param fac result polynomial factory.
* @param A polynomial with Rational coefficients to be converted.
* @return polynomial with BigDecimal coefficients.
*/
public static & Rational> GenPolynomial decimalFromRational(
GenPolynomialRing fac, GenPolynomial A) {
return PolyUtil. map(fac, A, new RatToDec());
}
/**
* Convert to complex decimal coefficients.
* @param fac result polynomial factory.
* @param A polynomial with complex Rational coefficients to be converted.
* @return polynomial with Complex BigDecimal coefficients.
*/
public static & Rational> GenPolynomial> complexDecimalFromRational(
GenPolynomialRing> fac, GenPolynomial> A) {
return PolyUtil., Complex> map(fac, A, new CompRatToDec(fac.coFac));
}
/**
* Real part.
* @param fac result polynomial factory.
* @param A polynomial with BigComplex coefficients to be converted.
* @return polynomial with real part of the coefficients.
*/
public static GenPolynomial realPart(GenPolynomialRing fac,
GenPolynomial A) {
return PolyUtil. map(fac, A, new RealPart());
}
/**
* Imaginary part.
* @param fac result polynomial factory.
* @param A polynomial with BigComplex coefficients to be converted.
* @return polynomial with imaginary part of coefficients.
*/
public static GenPolynomial imaginaryPart(GenPolynomialRing fac,
GenPolynomial A) {
return PolyUtil. map(fac, A, new ImagPart());
}
/**
* Real part.
* @param fac result polynomial factory.
* @param A polynomial with BigComplex coefficients to be converted.
* @return polynomial with real part of the coefficients.
*/
public static > GenPolynomial realPartFromComplex(GenPolynomialRing fac,
GenPolynomial> A) {
return PolyUtil., C> map(fac, A, new RealPartComplex());
}
/**
* Imaginary part.
* @param fac result polynomial factory.
* @param A polynomial with BigComplex coefficients to be converted.
* @return polynomial with imaginary part of coefficients.
*/
public static > GenPolynomial imaginaryPartFromComplex(GenPolynomialRing fac,
GenPolynomial> A) {
return PolyUtil., C> map(fac, A, new ImagPartComplex());
}
/**
* Complex from real polynomial.
* @param fac result polynomial factory.
* @param A polynomial with C coefficients to be converted.
* @return polynomial with Complex coefficients.
*/
public static > GenPolynomial> toComplex(
GenPolynomialRing> fac, GenPolynomial A) {
return PolyUtil.> map(fac, A, new ToComplex(fac.coFac));
}
/**
* Complex from rational coefficients.
* @param fac result polynomial factory.
* @param A polynomial with BigRational coefficients to be converted.
* @return polynomial with BigComplex coefficients.
*/
public static GenPolynomial complexFromRational(GenPolynomialRing fac,
GenPolynomial A) {
return PolyUtil. map(fac, A, new RatToCompl());
}
/**
* Complex from ring element coefficients.
* @param fac result polynomial factory.
* @param A polynomial with RingElem coefficients to be converted.
* @return polynomial with Complex coefficients.
*/
public static > GenPolynomial> complexFromAny(
GenPolynomialRing> fac, GenPolynomial A) {
ComplexRing cr = (ComplexRing) fac.coFac;
return PolyUtil.> map(fac, A, new AnyToComplex(cr));
}
/**
* From AlgebraicNumber coefficients. Represent as polynomial with type
* GenPolynomial<C> coefficients, e.g. ModInteger or BigRational.
* @param rfac result polynomial factory.
* @param A polynomial with AlgebraicNumber coefficients to be converted.
* @return polynomial with type GenPolynomial<C> coefficients.
*/
public static > GenPolynomial> fromAlgebraicCoefficients(
GenPolynomialRing> rfac, GenPolynomial> A) {
return PolyUtil., GenPolynomial> map(rfac, A, new AlgToPoly());
}
/**
* Convert to AlgebraicNumber coefficients. Represent as polynomial with
* AlgebraicNumber coefficients, C is e.g. ModInteger or BigRational.
* @param pfac result polynomial factory.
* @param A polynomial with C coefficients to be converted.
* @return polynomial with AlgebraicNumber<C> coefficients.
*/
public static > GenPolynomial> convertToAlgebraicCoefficients(
GenPolynomialRing> pfac, GenPolynomial A) {
AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac;
return PolyUtil.> map(pfac, A, new CoeffToAlg(afac));
}
/**
* Convert to recursive AlgebraicNumber coefficients. Represent as
* polynomial with recursive AlgebraicNumber coefficients, C is e.g.
* ModInteger or BigRational.
* @param depth recursion depth of AlgebraicNumber coefficients.
* @param pfac result polynomial factory.
* @param A polynomial with C coefficients to be converted.
* @return polynomial with AlgebraicNumber<C> coefficients.
*/
public static > GenPolynomial> convertToRecAlgebraicCoefficients(
int depth, GenPolynomialRing> pfac, GenPolynomial A) {
AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac;
return PolyUtil.> map(pfac, A, new CoeffToRecAlg(depth, afac));
}
/**
* Convert to AlgebraicNumber coefficients. Represent as polynomial with
* AlgebraicNumber coefficients, C is e.g. ModInteger or BigRational.
* @param pfac result polynomial factory.
* @param A recursive polynomial with GenPolynomial<BigInteger>
* coefficients to be converted.
* @return polynomial with AlgebraicNumber<C> coefficients.
*/
public static > GenPolynomial> convertRecursiveToAlgebraicCoefficients(
GenPolynomialRing> pfac, GenPolynomial> A) {
AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac;
return PolyUtil., AlgebraicNumber> map(pfac, A, new PolyToAlg(afac));
}
/**
* Complex from algebraic coefficients.
* @param fac result polynomial factory.
* @param A polynomial with AlgebraicNumber coefficients Q(i) to be
* converted.
* @return polynomial with Complex coefficients.
*/
public static > GenPolynomial> complexFromAlgebraic(
GenPolynomialRing> fac, GenPolynomial> A) {
ComplexRing cfac = (ComplexRing) fac.coFac;
return PolyUtil., Complex> map(fac, A, new AlgebToCompl(cfac));
}
/**
* AlgebraicNumber from complex coefficients.
* @param fac result polynomial factory over Q(i).
* @param A polynomial with Complex coefficients to be converted.
* @return polynomial with AlgebraicNumber coefficients.
*/
public static > GenPolynomial> algebraicFromComplex(
GenPolynomialRing> fac, GenPolynomial> A) {
AlgebraicNumberRing afac = (AlgebraicNumberRing) fac.coFac;
return PolyUtil., AlgebraicNumber> map(fac, A, new ComplToAlgeb(afac));
}
/**
* ModInteger chinese remainder algorithm on coefficients.
* @param fac GenPolynomial<ModInteger> result factory with
* A.coFac.modul*B.coFac.modul = C.coFac.modul.
* @param A GenPolynomial<ModInteger>.
* @param B other GenPolynomial<ModInteger>.
* @param mi inverse of A.coFac.modul in ring B.coFac.
* @return S = cra(A,B), with S mod A.coFac.modul == A and S mod
* B.coFac.modul == B.
*/
public static & Modular> GenPolynomial chineseRemainder(
GenPolynomialRing fac, GenPolynomial A, C mi, GenPolynomial B) {
ModularRingFactory cfac = (ModularRingFactory) fac.coFac; // get RingFactory
GenPolynomial S = fac.getZERO().copy();
GenPolynomial Ap = A.copy();
SortedMap av = Ap.val; //getMap();
SortedMap bv = B.getMap();
SortedMap sv = S.val; //getMap();
C c = null;
for (Map.Entry me : bv.entrySet()) {
ExpVector e = me.getKey();
C y = me.getValue(); //bv.get(e); // assert y != null
C x = av.get(e);
if (x != null) {
av.remove(e);
c = cfac.chineseRemainder(x, mi, y);
if (!c.isZERO()) { // 0 cannot happen
sv.put(e, c);
}
} else {
//c = cfac.fromInteger( y.getVal() );
c = cfac.chineseRemainder(A.ring.coFac.getZERO(), mi, y);
if (!c.isZERO()) { // 0 cannot happen
sv.put(e, c); // c != null
}
}
}
// assert bv is empty = done
for (Map.Entry me : av.entrySet()) { // rest of av
ExpVector e = me.getKey();
C x = me.getValue(); // av.get(e); // assert x != null
//c = cfac.fromInteger( x.getVal() );
c = cfac.chineseRemainder(x, mi, B.ring.coFac.getZERO());
if (!c.isZERO()) { // 0 cannot happen
sv.put(e, c); // c != null
}
}
return S;
}
/**
* GenPolynomial monic, i.e. leadingBaseCoefficient == 1. If
* leadingBaseCoefficient is not invertible returns this unmodified.
* @param coefficient type.
* @param p recursive GenPolynomial>.
* @return monic(p).
*/
public static > GenPolynomial> monic(
GenPolynomial> p) {
if (p == null || p.isZERO()) {
return p;
}
C lc = p.leadingBaseCoefficient().leadingBaseCoefficient();
if (!lc.isUnit()) {
return p;
}
C lm = lc.inverse();
GenPolynomial L = p.ring.coFac.getONE();
L = L.multiply(lm);
return p.multiply(L);
}
/**
* Polynomial list monic.
* @param coefficient type.
* @param L list of polynomials with field coefficients.
* @return list of polynomials with leading coefficient 1.
*/
public static > List> monic(List> L) {
return ListUtil., GenPolynomial> map(L,
new UnaryFunctor, GenPolynomial>() {
public GenPolynomial eval(GenPolynomial c) {
if (c == null) {
return null;
}
return c.monic();
}
});
}
/**
* Recursive polynomial list monic.
* @param coefficient type.
* @param L list of recursive polynomials with field coefficients.
* @return list of polynomials with leading base coefficient 1.
*/
public static > List>> monicRec(List>> L) {
return ListUtil.>, GenPolynomial>> map(L,
new UnaryFunctor>, GenPolynomial>>() {
public GenPolynomial> eval(GenPolynomial> c) {
if (c == null) {
return null;
}
return PolyUtil. monic(c);
}
});
}
/**
* Polynomial list leading exponent vectors.
* @param coefficient type.
* @param L list of polynomials.
* @return list of leading exponent vectors.
*/
public static > List leadingExpVector(List> L) {
return ListUtil., ExpVector> map(L, new UnaryFunctor, ExpVector>() {
public ExpVector eval(GenPolynomial c) {
if (c == null) {
return null;
}
return c.leadingExpVector();
}
});
}
/**
* Extend coefficient variables. Extend all coefficient ExpVectors by i
* elements and multiply by x_j^k.
* @param pfac extended polynomial ring factory (by i variables in the
* coefficients).
* @param j index of variable to be used for multiplication.
* @param k exponent for x_j.
* @return extended polynomial.
*/
public static > GenPolynomial> extendCoefficients(
GenPolynomialRing> pfac, GenPolynomial> A, int j, long k) {
GenPolynomial> Cp = pfac.getZERO().copy();
if (A.isZERO()) {
return Cp;
}
GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac;
//GenPolynomialRing acfac = (GenPolynomialRing) A.ring.coFac;
//int i = cfac.nvar - acfac.nvar;
Map> CC = Cp.val; //getMap();
for (Map.Entry> y : A.val.entrySet()) {
ExpVector e = y.getKey();
GenPolynomial