/*
* $Id$
*/
package edu.jas.application;
import java.util.Arrays;
import org.apache.log4j.Logger;
import edu.jas.gbufd.PolyGBUtil;
import edu.jas.kern.PrettyPrint;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenSolvablePolynomial;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.QuotPair;
/**
* SolvableLocalResidue, that is a (left) rational function, based on
* SolvableResidue and GenSolvablePolynomial with RingElem interface. Objects of
* this class are immutable.
* @author Heinz Kredel
*/
public class SolvableLocalResidue>
implements GcdRingElem>, QuotPair> {
// Can not extend SolvableLocal or SolvableQuotient because of
// different constructor semantics.
private static final Logger logger = Logger.getLogger(SolvableLocalResidue.class);
private final boolean debug = logger.isDebugEnabled();
/**
* SolvableLocalResidue class factory data structure.
*/
public final SolvableLocalResidueRing ring;
/**
* Numerator part of the element data structure.
*/
public final GenSolvablePolynomial num;
/**
* Denominator part of the element data structure.
*/
public final GenSolvablePolynomial den;
/**
* The constructor creates a SolvableLocalResidue object from a ring
* factory.
* @param r ring factory.
*/
public SolvableLocalResidue(SolvableLocalResidueRing r) {
this(r, r.ring.getZERO());
}
/**
* The constructor creates a SolvableLocalResidue object from a ring factory
* and a numerator polynomial. The denominator is assumed to be 1.
* @param r ring factory.
* @param n numerator solvable polynomial.
*/
public SolvableLocalResidue(SolvableLocalResidueRing r, GenSolvablePolynomial n) {
this(r, n, r.ring.getONE(), false); // false because of normalform
}
/**
* The constructor creates a SolvableLocalResidue object from a ring factory
* and a numerator and denominator solvable polynomial.
* @param r ring factory.
* @param n numerator polynomial.
* @param d denominator polynomial.
*/
public SolvableLocalResidue(SolvableLocalResidueRing r, GenSolvablePolynomial n,
GenSolvablePolynomial d) {
this(r, n, d, false);
}
/**
* The constructor creates a SolvableLocalResidue object from a ring factory
* and a numerator and denominator polynomial.
* @param r ring factory.
* @param n numerator polynomial.
* @param d denominator polynomial.
* @param isred unused at the moment.
*/
protected SolvableLocalResidue(SolvableLocalResidueRing r, GenSolvablePolynomial n,
GenSolvablePolynomial d, boolean isred) {
if (d == null || d.isZERO()) {
throw new IllegalArgumentException("denominator may not be zero");
}
ring = r;
if (d.signum() < 0) {
n = (GenSolvablePolynomial) n.negate();
d = (GenSolvablePolynomial) d.negate();
}
if (isred) {
num = n;
den = d;
return;
}
GenSolvablePolynomial p = ring.ideal.normalform(d);
if (p.isZERO()) {
throw new IllegalArgumentException("denominator may not be in ideal, d = " + d);
}
//d = p; // not always working
GenSolvablePolynomial nr = ring.ideal.normalform(n); // leftNF
if (nr.isZERO()) {
num = nr;
den = ring.ring.getONE();
return;
}
//logger.info("constructor: n = " + n + ", NF(n) = " + nr);
//n = nr; // not always working, failed
C lc = d.leadingBaseCoefficient();
if (!lc.isONE() && lc.isUnit()) {
lc = lc.inverse();
n = n.multiply(lc);
d = d.multiply(lc);
}
if (n.compareTo(d) == 0) {
num = ring.ring.getONE();
den = ring.ring.getONE();
return;
}
if (n.negate().compareTo(d) == 0) {
num = (GenSolvablePolynomial) ring.ring.getONE().negate();
den = ring.ring.getONE();
return;
}
if (n.isZERO()) {
num = n;
den = ring.ring.getONE();
return;
}
if (n.isONE()) {
num = n;
den = d;
return;
}
// must reduce to lowest terms
// not perfect, TODO
GenSolvablePolynomial[] gcd = PolyGBUtil. syzGcdCofactors(r.ring, n, d);
if (!gcd[0].isONE()) {
logger.info("constructor: gcd = " + Arrays.toString(gcd)); // + ", " + n + ", " +d);
n = gcd[1];
d = gcd[2];
// d not in ideal --> gcd not in ideal
}
// not perfect, TODO
GenSolvablePolynomial[] simp = ring.engine.leftSimplifier(n, d);
logger.info("simp: " + Arrays.toString(simp) + ", " + n + ", " + d);
num = simp[0];
den = simp[1];
}
/**
* Get the corresponding element factory.
* @return factory for this Element.
* @see edu.jas.structure.Element#factory()
*/
public SolvableLocalResidueRing factory() {
return ring;
}
/**
* Numerator.
* @see edu.jas.structure.QuotPair#numerator()
*/
public GenSolvablePolynomial numerator() {
return num;
}
/**
* Denominator.
* @see edu.jas.structure.QuotPair#denominator()
*/
public GenSolvablePolynomial denominator() {
return den;
}
/**
* Clone this.
* @see java.lang.Object#clone()
*/
@Override
public SolvableLocalResidue copy() {
return new SolvableLocalResidue(ring, num, den, true);
}
/**
* Is SolvableLocalResidue zero.
* @return If this is 0 then true is returned, else false.
* @see edu.jas.structure.RingElem#isZERO()
*/
public boolean isZERO() {
return num.isZERO();
}
/**
* Is SolvableLocalResidue one.
* @return If this is 1 then true is returned, else false.
* @see edu.jas.structure.RingElem#isONE()
*/
public boolean isONE() {
return num.compareTo(den) == 0;
}
/**
* Is SolvableLocalResidue a unit.
* @return If this is a unit then true is returned, else false.
* @see edu.jas.structure.RingElem#isUnit()
*/
public boolean isUnit() {
if (num.isZERO()) {
return false;
}
return true;
}
/**
* Is Quotient a constant.
* @return true, if this has constant numerator and denominator, else false.
*/
public boolean isConstant() {
return num.isConstant() && den.isConstant();
}
/**
* Get the String representation as RingElem.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (PrettyPrint.isTrue()) {
String s = "{ " + num.toString(ring.ring.getVars());
if (!den.isONE()) {
s += " | " + den.toString(ring.ring.getVars());
}
return s + " }";
}
return "SolvableLocalResidue[ " + num.toString() + " | " + den.toString() + " ]";
}
/**
* Get a scripting compatible string representation.
* @return script compatible representation for this Element.
* @see edu.jas.structure.Element#toScript()
*/
@Override
public String toScript() {
// any scripting case
if (den.isONE()) {
return num.toScript();
}
return num.toScript() + " / " + den.toScript();
}
/**
* Get a scripting compatible string representation of the factory.
* @return script compatible representation for this ElemFactory.
* @see edu.jas.structure.Element#toScriptFactory()
*/
@Override
public String toScriptFactory() {
return factory().toScript();
}
/**
* SolvableLocalResidue comparison.
* @param b SolvableLocalResidue.
* @return sign(this-b).
*/
@Override
public int compareTo(SolvableLocalResidue b) {
if (b == null || b.isZERO()) {
return this.signum();
}
if (this.isZERO()) {
return -b.signum();
}
return this.subtract(b).signum();
// GenSolvablePolynomial n, p, q;
// if ( den.compareTo(b.den) == 0 ) {
// n = (GenSolvablePolynomial) num.subtract(b.num);
// //\\ p = ring.ideal.normalform(n);
// //logger.info("p.signum() = " + p.signum());
// return p.signum();
// }
// GenSolvablePolynomial r, s;
// // if (den.isONE()) { }
// // if (b.den.isONE()) { }
// GenSolvablePolynomial[] oc = ring.engine.leftOreCond(den,b.den);
// if (debug) {
// logger.info("oc[0] den =<>= oc[1] b.den: (" + oc[0] + ") (" + den + ") = (" + oc[1]
// + ") (" + b.den + ")");
// }
// q = oc[0].multiply(den);
// q = ring.ideal.normalform(q);
// int t = q.signum(); //oc[0].signum() * den.signum(); // sign only
// r = oc[0].multiply(num);
// s = oc[1].multiply(b.num);
// p = (GenSolvablePolynomial) r.subtract(s);
// //\\ p = ring.ideal.normalform(p);
// //logger.info("p.signum() = " + p.signum());
// if ( t == 0 ) {
// throw new RuntimeException("can not happen: denominator is zero: this " + this + ", b = " + b);
// }
// return t * p.signum();
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object b) {
if (!(b instanceof SolvableLocalResidue)) {
return false;
}
SolvableLocalResidue a = null;
try {
a = (SolvableLocalResidue) b;
} catch (ClassCastException e) {
}
if (a == null) {
return false;
}
return compareTo(a) == 0;
}
/**
* Hash code for this element.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int h;
h = ring.hashCode();
h = 37 * h + num.hashCode();
h = 37 * h + den.hashCode();
return h;
}
/**
* SolvableLocalResidue absolute value.
* @return the absolute value of this.
* @see edu.jas.structure.RingElem#abs()
*/
public SolvableLocalResidue abs() {
return new SolvableLocalResidue(ring, (GenSolvablePolynomial) num.abs(), den, true);
}
/**
* SolvableLocalResidue summation.
* @param S SolvableLocalResidue.
* @return this+S.
*/
public SolvableLocalResidue sum(SolvableLocalResidue S) {
if (S == null || S.isZERO()) {
return this;
}
if (this.isZERO()) {
return S;
}
GenSolvablePolynomial n, d, n1, n2;
if (den.isONE() && S.den.isONE()) {
n = (GenSolvablePolynomial) num.sum(S.num);
return new SolvableLocalResidue(ring, n, den, false); // true
}
/* wrong:
if (den.isONE()) { }
if (S.den.isONE()) { }
*/
if (den.compareTo(S.den) == 0) { // correct ?
n = (GenSolvablePolynomial) num.sum(S.num);
return new SolvableLocalResidue(ring, n, den, false);
}
// general case
GenSolvablePolynomial[] oc = ring.engine.leftOreCond(den, S.den);
if (debug) {
logger.info("oc[0] den =sum= oc[1] S.den: (" + oc[0] + ") (" + den + ") = (" + oc[1] + ") ("
+ S.den + ")");
}
d = oc[0].multiply(den);
n1 = oc[0].multiply(num);
n2 = oc[1].multiply(S.num);
n = (GenSolvablePolynomial) n1.sum(n2);
//logger.info("n = " + n + ", d = " + d);
return new SolvableLocalResidue(ring, n, d, false);
}
/**
* SolvableLocalResidue negate.
* @return -this.
* @see edu.jas.structure.RingElem#negate()
*/
public SolvableLocalResidue negate() {
return new SolvableLocalResidue(ring, (GenSolvablePolynomial) num.negate(), den, true);
}
/**
* SolvableLocalResidue signum.
* @see edu.jas.structure.RingElem#signum()
* @return signum(this).
*/
public int signum() {
// assume sign(den) > 0
return num.signum();
}
/**
* SolvableLocalResidue subtraction.
* @param S SolvableLocalResidue.
* @return this-S.
*/
public SolvableLocalResidue subtract(SolvableLocalResidue S) {
return sum(S.negate());
}
/**
* SolvableLocalResidue division.
* @param S SolvableLocalResidue.
* @return this/S.
*/
public SolvableLocalResidue divide(SolvableLocalResidue S) {
return multiply(S.inverse());
}
/**
* SolvableLocalResidue inverse.
* @see edu.jas.structure.RingElem#inverse()
* @return S with S = 1/this.
*/
public SolvableLocalResidue inverse() {
if (num.isZERO()) {
throw new ArithmeticException("element not invertible " + this);
}
return new SolvableLocalResidue(ring, den, num, false); // true
}
/**
* SolvableLocalResidue remainder.
* @param S SolvableLocalResidue.
* @return this - (this/S)*S.
*/
public SolvableLocalResidue remainder(SolvableLocalResidue S) {
if (S.isZERO()) {
throw new ArithmeticException("element not invertible " + S);
}
return ring.getZERO();
}
/**
* SolvableLocalResidue multiplication.
* @param S SolvableLocalResidue.
* @return this*S.
*/
public SolvableLocalResidue multiply(SolvableLocalResidue S) {
if (S == null || S.isZERO()) {
return S;
}
if (num.isZERO()) {
return this;
}
if (S.isONE()) {
return this;
}
if (this.isONE()) {
return S;
}
GenSolvablePolynomial n, d;
if (den.isONE() && S.den.isONE()) {
n = num.multiply(S.num);
return new SolvableLocalResidue(ring, n, den, false); // true
}
/* wrong:
if (den.isONE()) { }
if (S.den.isONE()) { }
if ( den.compareTo(S.den) == 0 ) { }
*/
GenSolvablePolynomial[] oc = ring.engine.leftOreCond(num, S.den);
if (debug) {
System.out.println("oc[0] num =mult= oc[1] S.den: (" + oc[0] + ") (" + num + ") = (" + oc[1]
+ ") (" + S.den + ")");
}
n = oc[1].multiply(S.num);
d = oc[0].multiply(den);
return new SolvableLocalResidue(ring, n, d, false);
}
/**
* SolvableLocalResidue multiplication by GenSolvablePolynomial.
* @param b GenSolvablePolynomial.
* @return this*b.
*/
public SolvableLocalResidue multiply(GenSolvablePolynomial b) {
if (b == null || b.isZERO()) {
return ring.getZERO();
}
if (num.isZERO()) {
return this;
}
if (b.isONE()) {
return this;
}
SolvableLocalResidue B = new SolvableLocalResidue(ring, b);
return multiply(B);
}
/**
* SolvableLocalResidue multiplication by coefficient.
* @param b coefficient.
* @return this*b.
*/
public SolvableLocalResidue multiply(C b) {
if (b == null || b.isZERO()) {
return ring.getZERO();
}
if (num.isZERO()) {
return this;
}
if (b.isONE()) {
return this;
}
GenSolvablePolynomial B = ring.ring.getONE().multiply(b);
return multiply(B);
}
/**
* SolvableLocalResidue multiplication by exponent.
* @param e exponent vector.
* @return this*b.
*/
public SolvableLocalResidue multiply(ExpVector e) {
if (e == null || e.isZERO()) {
return this;
}
if (num.isZERO()) {
return this;
}
GenSolvablePolynomial B = ring.ring.getONE().multiply(e);
return multiply(B);
}
/**
* SolvableLocalResidue monic.
* @return this with monic value part.
*/
public SolvableLocalResidue monic() {
if (num.isZERO()) {
return this;
}
return this;
}
/**
* Greatest common divisor.
* @param b other element.
* @return gcd(this,b).
*/
public SolvableLocalResidue gcd(SolvableLocalResidue b) {
if (b == null || b.isZERO()) {
return this;
}
if (this.isZERO()) {
return b;
}
return ring.getONE();
}
/**
* Extended greatest common divisor.
* @param b other element.
* @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
*/
@SuppressWarnings("unchecked")
public SolvableLocalResidue[] egcd(SolvableLocalResidue b) {
SolvableLocalResidue[] ret = (SolvableLocalResidue[]) new SolvableLocalResidue[3];
ret[0] = null;
ret[1] = null;
ret[2] = null;
if (b == null || b.isZERO()) {
ret[0] = this;
return ret;
}
if (this.isZERO()) {
ret[0] = b;
return ret;
}
GenSolvablePolynomial two = ring.ring.fromInteger(2);
ret[0] = ring.getONE();
ret[1] = (this.multiply(two)).inverse();
ret[2] = (b.multiply(two)).inverse();
return ret;
}
}
Ads help maintain this website.