/*
* $Id$
*/
package edu.jas.poly;
import org.apache.log4j.Logger;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.RingElem;
import edu.jas.structure.QuotPair;
/**
* Local element based on RingElem pairs. Objects of this class are (nearly)
* immutable.
* @author Heinz Kredel
*/
public class Local>
implements RingElem>, QuotPair {
private static final Logger logger = Logger.getLogger(Local.class);
private final boolean debug = logger.isDebugEnabled();
/**
* Local class factory data structure.
*/
protected final LocalRing ring;
/**
* Numerator part of the element data structure.
*/
protected final C num;
/**
* Denominator part of the element data structure.
*/
protected final C den;
/**
* Flag to remember if this local element is a unit. -1 is unknown, 1 is
* unit, 0 not a unit.
*/
protected int isunit = -1; // initially unknown
/**
* The constructor creates a Local object from a ring factory.
* @param r ring factory.
*/
public Local(LocalRing r) {
this(r, r.ring.getZERO());
}
/**
* The constructor creates a Local object from a ring factory and a
* numerator element. The denominator is assumed to be 1.
* @param r ring factory.
* @param n numerator.
*/
public Local(LocalRing r, C n) {
this(r, n, r.ring.getONE(), true);
}
/**
* The constructor creates a Local object from a ring factory and a
* numerator and denominator element.
* @param r ring factory.
* @param n numerator.
* @param d denominator.
*/
public Local(LocalRing r, C n, C d) {
this(r, n, d, false);
}
/**
* The constructor creates a Local object from a ring factory and a
* numerator and denominator element.
* @param r ring factory.
* @param n numerator.
* @param d denominator.
* @param isred true if gcd(n,d) == 1, else false.
*/
@SuppressWarnings("unchecked")
protected Local(LocalRing r, C n, C d, boolean isred) {
if (d == null || d.isZERO()) {
throw new IllegalArgumentException("denominator may not be zero");
}
ring = r;
if (d.signum() < 0) {
n = n.negate();
d = d.negate();
}
if (isred) {
num = n;
den = d;
return;
}
C p = d.remainder(ring.ideal);
if (p == null || p.isZERO()) {
throw new IllegalArgumentException("denominator may not be in ideal");
}
// must reduce to lowest terms
if (n instanceof GcdRingElem && d instanceof GcdRingElem) {
GcdRingElem ng = (GcdRingElem) n;
GcdRingElem dg = (GcdRingElem) d;
C gcd = (C) ng.gcd(dg);
if (debug) {
logger.info("gcd = " + gcd);
}
//RingElem gcd = ring.ring.getONE();
if (gcd.isONE()) {
num = n;
den = d;
} else {
num = n.divide(gcd);
den = d.divide(gcd);
}
// } else { // univariate polynomial?
} else {
logger.warn("gcd = ????");
num = n;
den = d;
}
}
/**
* Get the corresponding element factory.
* @return factory for this Element.
* @see edu.jas.structure.Element#factory()
*/
public LocalRing factory() {
return ring;
}
/**
* Numerator.
* @see edu.jas.structure.QuotPair#numerator()
*/
public C numerator() {
return num;
}
/**
* Denominator.
* @see edu.jas.structure.QuotPair#denominator()
*/
public C denominator() {
return den;
}
/**
* Is Local a constant.
* Not implemented.
* @throws UnsupportedOperationException.
*/
public boolean isConstant() {
throw new UnsupportedOperationException("isConstant not implemented");
}
/**
* Clone this.
* @see java.lang.Object#clone()
*/
@Override
public Local copy() {
return new Local(ring, num, den, true);
}
/**
* Is Local 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 Local one.
* @return If this is 1 then true is returned, else false.
* @see edu.jas.structure.RingElem#isONE()
*/
public boolean isONE() {
return num.equals(den);
}
/**
* Is Local unit.
* @return If this is a unit then true is returned, else false.
* @see edu.jas.structure.RingElem#isUnit()
*/
public boolean isUnit() {
if (isunit > 0) {
return true;
}
if (isunit == 0) {
return false;
}
// not jet known
if (num.isZERO()) {
isunit = 0;
return false;
}
C p = num.remainder(ring.ideal);
boolean u = (p != null && !p.isZERO());
if (u) {
isunit = 1;
} else {
isunit = 0;
}
return (u);
}
/**
* Get the String representation as RingElem.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Local[ " + 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() {
// Python case
return "Local( " + 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() {
// Python case
return factory().toScript();
}
/**
* Local comparison.
* @param b Local.
* @return sign(this-b).
*/
@Override
public int compareTo(Local b) {
if (b == null || b.isZERO()) {
return this.signum();
}
C r = num.multiply(b.den);
C s = den.multiply(b.num);
C x = r.subtract(s);
return x.signum();
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object b) {
if (!(b instanceof Local)) {
return false;
}
Local a = null;
try {
a = (Local) b;
} catch (ClassCastException e) {
}
if (a == null) {
return false;
}
return (0 == compareTo(a));
}
/**
* Hash code for this local.
* @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;
}
/**
* Local absolute value.
* @return the absolute value of this.
* @see edu.jas.structure.RingElem#abs()
*/
public Local abs() {
return new Local(ring, num.abs(), den, true);
}
/**
* Local summation.
* @param S Local.
* @return this+S.
*/
public Local sum(Local S) {
if (S == null || S.isZERO()) {
return this;
}
C n = num.multiply(S.den);
n = n.sum(den.multiply(S.num));
C d = den.multiply(S.den);
return new Local(ring, n, d, false);
}
/**
* Local negate.
* @return -this.
* @see edu.jas.structure.RingElem#negate()
*/
public Local negate() {
return new Local(ring, num.negate(), den, true);
}
/**
* Local signum.
* @see edu.jas.structure.RingElem#signum()
* @return signum(this).
*/
public int signum() {
return num.signum();
}
/**
* Local subtraction.
* @param S Local.
* @return this-S.
*/
public Local subtract(Local S) {
if (S == null || S.isZERO()) {
return this;
}
C n = num.multiply(S.den);
n = n.subtract(den.multiply(S.num));
C d = den.multiply(S.den);
return new Local(ring, n, d, false);
}
/**
* Local division.
* @param S Local.
* @return this/S.
*/
public Local divide(Local S) {
return multiply(S.inverse());
}
/**
* Local inverse.
* @see edu.jas.structure.RingElem#inverse()
* @return S with S = 1/this if defined.
*/
public Local inverse() {
if (isONE()) {
return this;
}
if (isUnit()) {
return new Local(ring, den, num, true);
}
throw new ArithmeticException("element not invertible " + this);
}
/**
* Local remainder.
* @param S Local.
* @return this - (this/S)*S.
*/
public Local remainder(Local S) {
if (num.isZERO()) {
throw new ArithmeticException("element not invertible " + this);
}
if (S.isUnit()) {
return ring.getZERO();
}
throw new UnsupportedOperationException("remainder not implemented" + S);
}
/**
* Quotient and remainder by division of this by S.
* @param S a Local
* @return [this/S, this - (this/S)*S].
*/
public Local[] quotientRemainder(Local S) {
return new Local[] { divide(S), remainder(S) };
}
/**
* Local multiplication.
* @param S Local.
* @return this*S.
*/
public Local multiply(Local S) {
if (S == null || S.isZERO()) {
return S;
}
if (num.isZERO()) {
return this;
}
if (S.isONE()) {
return this;
}
if (this.isONE()) {
return S;
}
C n = num.multiply(S.num);
C d = den.multiply(S.den);
return new Local(ring, n, d, false);
}
/**
* Greatest common divisor. Note: Not implemented, throws
* UnsupportedOperationException.
* @param b other element.
* @return gcd(this,b).
*/
public Local gcd(Local b) {
throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName());
}
/**
* Extended greatest common divisor. Note: Not implemented, throws
* UnsupportedOperationException.
* @param b other element.
* @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
*/
public Local[] egcd(Local b) {
throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName());
}
}
Ads help maintain this website.