/*
* $Id$
*/
package edu.jas.poly;
import org.apache.log4j.Logger;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.NotInvertibleException;
import edu.jas.structure.RingElem;
/**
* Residue element based on RingElem residue. Objects of this class are (nearly)
* immutable.
* @author Heinz Kredel
*/
public class Residue> implements RingElem> {
private static final Logger logger = Logger.getLogger(Residue.class);
private final boolean debug = logger.isDebugEnabled();
/**
* Residue class factory data structure.
*/
protected final ResidueRing ring;
/**
* Value part of the element data structure.
*/
protected final C val;
/**
* Flag to remember if this residue element is a unit. -1 is unknown, 1 is
* unit, 0 not a unit.
*/
protected int isunit = -1; // initially unknown
/**
* The constructor creates a Residue object from a ring factory.
* @param r ring factory.
*/
public Residue(ResidueRing r) {
this(r, r.ring.getZERO(), 0);
}
/**
* The constructor creates a Residue object from a ring factory and a ring
* element.
* @param r ring factory.
* @param a ring element.
*/
public Residue(ResidueRing r, C a) {
this(r, a, -1);
}
/**
* The constructor creates a Residue object from a ring factory, a ring
* element and an indicator if a is a unit.
* @param r ring factory.
* @param a ring element.
* @param u isunit indicator, -1, 0, 1.
*/
public Residue(ResidueRing r, C a, int u) {
ring = r;
C v = a.remainder(ring.modul);
if (v.signum() < 0) {
v = v.sum(ring.modul);
}
val = v;
if (u == 0 || u == 1) {
isunit = u;
return;
}
if (val.isZERO()) {
isunit = 0;
return;
}
if (val.isUnit()) {
isunit = 1;
//} else { // not possible
//isunit = 0;
}
isunit = -1;
}
/**
* Get the corresponding element factory.
* @return factory for this Element.
* @see edu.jas.structure.Element#factory()
*/
public ResidueRing factory() {
return ring;
}
/**
* Clone this.
* @see java.lang.Object#clone()
*/
@Override
public Residue copy() {
return new Residue(ring, val);
}
/**
* Is Residue zero.
* @return If this is 0 then true is returned, else false.
* @see edu.jas.structure.RingElem#isZERO()
*/
public boolean isZERO() {
return val.equals(ring.ring.getZERO());
}
/**
* Is Residue one.
* @return If this is 1 then true is returned, else false.
* @see edu.jas.structure.RingElem#isONE()
*/
public boolean isONE() {
return val.equals(ring.ring.getONE());
}
/**
* Is Residue unit.
* @return If this is a unit then true is returned, else false.
* @see edu.jas.structure.RingElem#isUnit()
*/
@SuppressWarnings("unchecked")
public boolean isUnit() {
if (isunit == 1) {
return true;
}
if (isunit == 0) {
return false;
}
// val.isUnit() already tested
// not jet known
if (val instanceof GcdRingElem && ring.modul instanceof GcdRingElem) {
GcdRingElem v = (GcdRingElem) val;
GcdRingElem m = (GcdRingElem) ring.modul;
C gcd = (C) v.gcd(m);
if (debug) {
logger.info("gcd = " + gcd);
}
boolean u = gcd.isONE();
if (u) {
isunit = 1;
} else {
isunit = 0;
}
return u;
}
// still unknown
return false;
}
/**
* Get the String representation as RingElem.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Residue[ " + val.toString() + " mod " + ring.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 "Residue( " + val.toScript() + " , " + ring.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();
}
/**
* Residue comparison.
* @param b Residue.
* @return sign(this-b), 0 means that this and b are equivalent in this
* residue class ring.
*/
@Override
public int compareTo(Residue b) {
C v = b.val;
if (!ring.equals(b.ring)) {
v = v.remainder(ring.modul);
}
return val.compareTo(v);
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
* @return true means that this and b are equivalent in this residue class
* ring.
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object b) {
if (!(b instanceof Residue)) {
return false;
}
Residue a = null;
try {
a = (Residue) 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 + val.hashCode();
return h;
}
/**
* Residue absolute value.
* @return the absolute value of this.
* @see edu.jas.structure.RingElem#abs()
*/
public Residue abs() {
return new Residue(ring, val.abs());
}
/**
* Residue summation.
* @param S Residue.
* @return this+S.
*/
public Residue sum(Residue S) {
return new Residue(ring, val.sum(S.val));
}
/**
* Residue negate.
* @return -this.
* @see edu.jas.structure.RingElem#negate()
*/
public Residue negate() {
return new Residue(ring, val.negate());
}
/**
* Residue signum.
* @see edu.jas.structure.RingElem#signum()
* @return signum(this).
*/
public int signum() {
return val.signum();
}
/**
* Residue subtraction.
* @param S Residue.
* @return this-S.
*/
public Residue subtract(Residue S) {
return new Residue(ring, val.subtract(S.val));
}
/**
* Residue division.
* @param S Residue.
* @return this/S.
*/
public Residue divide(Residue S) {
return multiply(S.inverse());
}
/**
* Residue inverse.
* @see edu.jas.structure.RingElem#inverse()
* @return S with S = 1/this if defined.
*/
@SuppressWarnings("unchecked")
public Residue inverse() {
if (isunit == 0) {
throw new NotInvertibleException("element not invertible (0) " + this);
}
if (val instanceof GcdRingElem && ring.modul instanceof GcdRingElem) {
GcdRingElem v = (GcdRingElem) val;
GcdRingElem m = (GcdRingElem) ring.modul;
C[] egcd = (C[]) v.egcd(m);
if (debug) {
logger.info("egcd = " + egcd[0] + ", f = " + egcd[1]);
}
if (!egcd[0].isONE()) {
isunit = 0;
throw new NotInvertibleException("element not invertible (gcd)" + this);
}
isunit = 1;
C x = egcd[1];
return new Residue(ring, x);
}
if (val.isUnit()) {
C x = val.inverse();
return new Residue(ring, x);
}
System.out.println("isunit = " + isunit + ", isUnit() = " + this.isUnit());
throw new NotInvertibleException("element not invertible (!gcd)" + this);
}
/**
* Residue remainder.
* @param S Residue.
* @return this - (this/S)*S.
*/
public Residue remainder(Residue S) {
C x = val.remainder(S.val);
return new Residue(ring, x);
}
/**
* Quotient and remainder by division of this by S.
* @param S a Residue
* @return [this/S, this - (this/S)*S].
*/
public Residue[] quotientRemainder(Residue S) {
return new Residue[] { divide(S), remainder(S) };
}
/**
* Residue multiplication.
* @param S Residue.
* @return this*S.
*/
public Residue multiply(Residue S) {
return new Residue(ring, val.multiply(S.val));
}
/**
* Greatest common divisor. Note: Not implemented, throws
* UnsupportedOperationException.
* @param b other element.
* @return gcd(this,b).
*/
public Residue gcd(Residue 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 Residue[] egcd(Residue b) {
throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName());
}
}
Ads help maintain this website.