
edu.jas.poly.Complex Maven / Gradle / Ivy
The newest version!
/*
* $Id: Complex.java 4125 2012-08-19 19:05:22Z kredel $
*/
package edu.jas.poly;
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.structure.RingElem;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.StarRingElem;
/**
* Generic Complex class implementing the RingElem interface. Objects of this
* class are immutable.
* @param base type of RingElem (for complex polynomials).
* @author Heinz Kredel
*/
public class Complex> implements StarRingElem>, GcdRingElem> {
private static final Logger logger = Logger.getLogger(Complex.class);
private static final boolean debug = logger.isDebugEnabled();
/**
* Complex class factory data structure.
*/
public final ComplexRing ring;
/**
* Real part of the data structure.
*/
protected final C re;
/**
* Imaginary part of the data structure.
*/
protected final C im;
/**
* The constructor creates a Complex object from two C objects as real and
* imaginary part.
* @param ring factory for Complex objects.
* @param r real part.
* @param i imaginary part.
*/
public Complex(ComplexRing ring, C r, C i) {
this.ring = ring;
re = r;
im = i;
}
/**
* The constructor creates a Complex object from a C object as real part,
* the imaginary part is set to 0.
* @param r real part.
*/
public Complex(ComplexRing ring, C r) {
this(ring, r, ring.ring.getZERO());
}
/**
* The constructor creates a Complex object from a long element as real
* part, the imaginary part is set to 0.
* @param r real part.
*/
public Complex(ComplexRing ring, long r) {
this(ring, ring.ring.fromInteger(r));
}
/**
* The constructor creates a Complex object with real part 0 and imaginary
* part 0.
*/
public Complex(ComplexRing ring) {
this(ring, ring.ring.getZERO());
}
/**
* The constructor creates a Complex object from a String representation.
* @param s string of a Complex.
* @throws NumberFormatException
*/
public Complex(ComplexRing ring, String s) throws NumberFormatException {
this.ring = ring;
if (s == null || s.length() == 0) {
re = ring.ring.getZERO();
im = ring.ring.getZERO();
return;
}
s = s.trim();
int i = s.indexOf("i");
if (i < 0) {
re = ring.ring.parse(s);
im = ring.ring.getZERO();
return;
}
//logger.warn("String constructor not done");
String sr = "";
if (i > 0) {
sr = s.substring(0, i);
}
String si = "";
if (i < s.length()) {
si = s.substring(i + 1, s.length());
}
//int j = sr.indexOf("+");
re = ring.ring.parse(sr.trim());
im = ring.ring.parse(si.trim());
}
/**
* Get the corresponding element factory.
* @return factory for this Element.
* @see edu.jas.structure.Element#factory()
*/
public ComplexRing factory() {
return ring;
}
/**
* Get the real part.
* @return re.
*/
public C getRe() {
return re;
}
/**
* Get the imaginary part.
* @return im.
*/
public C getIm() {
return im;
}
/**
* Clone this.
* @see java.lang.Object#clone()
*/
@Override
public Complex copy() {
return new Complex(ring, re, im);
}
/**
* Get the String representation.
*/
@Override
public String toString() {
String s = re.toString();
//logger.info("compareTo "+im+" ? 0 = "+i);
if (im.isZERO()) {
return s;
}
s += "i" + im;
return s;
}
/**
* Get a scripting compatible string representation.
* @return script compatible representation for this Element.
* @see edu.jas.structure.Element#toScript()
*/
//JAVA6only: @Override
public String toScript() {
// Python case
StringBuffer s = new StringBuffer();
if (im.isZERO()) {
s.append(re.toScript());
} else {
C mi = im;
//s.append("");
if (!re.isZERO()) {
s.append(re.toScript());
if (mi.signum() > 0) {
s.append(" + ");
} else {
s.append(" - ");
mi = mi.negate();
}
}
if (mi.isONE()) {
s.append("I");
} else {
s.append(mi.toScript()).append(" * I");
}
s.append("");
}
return s.toString();
}
/**
* Get a scripting compatible string representation of the factory.
* @return script compatible representation for this ElemFactory.
* @see edu.jas.structure.Element#toScriptFactory()
*/
//JAVA6only: @Override
public String toScriptFactory() {
// Python case
return ring.toScript();
}
/**
* Is Complex number zero.
* @return If this is 0 then true is returned, else false.
* @see edu.jas.structure.RingElem#isZERO()
*/
public boolean isZERO() {
return re.isZERO() && im.isZERO();
}
/**
* Is Complex number one.
* @return If this is 1 then true is returned, else false.
* @see edu.jas.structure.RingElem#isONE()
*/
public boolean isONE() {
return re.isONE() && im.isZERO();
}
/**
* Is Complex imaginary one.
* @return If this is i then true is returned, else false.
*/
public boolean isIMAG() {
return re.isZERO() && im.isONE();
}
/**
* Is Complex unit element.
* @return If this is a unit then true is returned, else false.
* @see edu.jas.structure.RingElem#isUnit()
*/
public boolean isUnit() {
if (isZERO()) {
return false;
}
if (ring.isField()) {
return true;
}
return norm().re.isUnit();
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object b) {
if (!(b instanceof Complex)) {
return false;
}
Complex bc = null;
try {
bc = (Complex) b;
} catch (ClassCastException e) {
}
if (bc == null) {
return false;
}
if (!ring.equals(bc.ring)) {
return false;
}
return re.equals(bc.re) && im.equals(bc.im);
}
/**
* Hash code for this Complex.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return 37 * re.hashCode() + im.hashCode();
}
/**
* Since complex numbers are unordered, we use lexicographical order of re
* and im.
* @return 0 if this is equal to b; 1 if re > b.re, or re == b.re and im >
* b.im; -1 if re < b.re, or re == b.re and im < b.im
*/
//JAVA6only: @Override
public int compareTo(Complex b) {
int s = re.compareTo(b.re);
if (s != 0) {
return s;
}
return im.compareTo(b.im);
}
/**
* Since complex numbers are unordered, we use lexicographical order of re
* and im.
* @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0; -1
* if re < 0, or re == 0 and im < 0
* @see edu.jas.structure.RingElem#signum()
*/
public int signum() {
int s = re.signum();
if (s != 0) {
return s;
}
return im.signum();
}
/* arithmetic operations: +, -, -
*/
/**
* Complex number summation.
* @param B a Complex number.
* @return this+B.
*/
public Complex sum(Complex B) {
return new Complex(ring, re.sum(B.re), im.sum(B.im));
}
/**
* Complex number subtract.
* @param B a Complex number.
* @return this-B.
*/
public Complex subtract(Complex B) {
return new Complex(ring, re.subtract(B.re), im.subtract(B.im));
}
/**
* Complex number negative.
* @return -this.
* @see edu.jas.structure.RingElem#negate()
*/
public Complex negate() {
return new Complex(ring, re.negate(), im.negate());
}
/* arithmetic operations: conjugate, absolut value
*/
/**
* Complex number conjugate.
* @return the complex conjugate of this.
*/
public Complex conjugate() {
return new Complex(ring, re, im.negate());
}
/**
* Complex number norm.
* @see edu.jas.structure.StarRingElem#norm()
* @return ||this||.
*/
public Complex norm() {
// this.conjugate().multiply(this);
C v = re.multiply(re);
v = v.sum(im.multiply(im));
return new Complex(ring, v);
}
/**
* Complex number absolute value.
* @see edu.jas.structure.RingElem#abs()
* @return |this|^2. Note: The square root is not jet implemented.
*/
public Complex abs() {
Complex n = norm();
logger.error("abs() square root missing");
// n = n.sqrt();
return n;
}
/* arithmetic operations: *, inverse, /
*/
/**
* Complex number product.
* @param B is a complex number.
* @return this*B.
*/
public Complex multiply(Complex B) {
return new Complex(ring, re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum(
im.multiply(B.re)));
}
/**
* Complex number inverse.
* @return S with S*this = 1, if it is defined.
* @see edu.jas.structure.RingElem#inverse()
*/
public Complex inverse() {
C a = norm().re.inverse();
return new Complex(ring, re.multiply(a), im.multiply(a.negate()));
}
/**
* Complex number remainder.
* @param S is a complex number.
* @return 0.
*/
public Complex remainder(Complex S) {
if (ring.isField()) {
return ring.getZERO();
}
return quotientRemainder(S)[1];
}
/**
* Complex number divide.
* @param B is a complex number, non-zero.
* @return this/B.
*/
public Complex divide(Complex B) {
if (ring.isField()) {
return this.multiply(B.inverse());
}
return quotientRemainder(B)[0];
}
/**
* Complex number quotient and remainder.
* @param S Complex.
* @return Complex[] { q, r } with q = this/S and r = rem(this,S).
*/
@SuppressWarnings("unchecked")
public Complex[] quotientRemainder(Complex S) {
Complex[] ret = new Complex[2];
C n = S.norm().re;
Complex Sp = this.multiply(S.conjugate()); // == this*inv(S)*n
C qr = Sp.re.divide(n);
C rr = Sp.re.remainder(n);
C qi = Sp.im.divide(n);
C ri = Sp.im.remainder(n);
C rr1 = rr;
C ri1 = ri;
if (rr.signum() < 0) {
rr = rr.negate();
}
if (ri.signum() < 0) {
ri = ri.negate();
}
C one = n.factory().fromInteger(1);
if (rr.sum(rr).compareTo(n) > 0) { // rr > n/2
if (rr1.signum() < 0) {
qr = qr.subtract(one);
} else {
qr = qr.sum(one);
}
}
if (ri.sum(ri).compareTo(n) > 0) { // ri > n/2
if (ri1.signum() < 0) {
qi = qi.subtract(one);
} else {
qi = qi.sum(one);
}
}
Sp = new Complex(ring, qr, qi);
Complex Rp = this.subtract(Sp.multiply(S));
if (debug && n.compareTo(Rp.norm().re) < 0) {
System.out.println("n = " + n);
System.out.println("qr = " + qr);
System.out.println("qi = " + qi);
System.out.println("rr = " + rr);
System.out.println("ri = " + ri);
System.out.println("rr1 = " + rr1);
System.out.println("ri1 = " + ri1);
System.out.println("this = " + this);
System.out.println("S = " + S);
System.out.println("Sp = " + Sp);
BigInteger tr = (BigInteger) (Object) this.re;
BigInteger ti = (BigInteger) (Object) this.im;
BigInteger sr = (BigInteger) (Object) S.re;
BigInteger si = (BigInteger) (Object) S.im;
BigComplex tc = new BigComplex(new BigRational(tr), new BigRational(ti));
BigComplex sc = new BigComplex(new BigRational(sr), new BigRational(si));
BigComplex qc = tc.divide(sc);
System.out.println("qc = " + qc);
BigDecimal qrd = new BigDecimal(qc.getRe());
BigDecimal qid = new BigDecimal(qc.getIm());
System.out.println("qrd = " + qrd);
System.out.println("qid = " + qid);
throw new ArithmeticException("QR norm not decreasing " + Rp + ", " + Rp.norm());
}
ret[0] = Sp;
ret[1] = Rp;
return ret;
}
/**
* Complex number quotient and remainder.
* @param S Complex.
* @return Complex[] { q, r } with q = this/S and r = rem(this,S).
* @deprecated use quotientRemainder()
*/
@Deprecated
public Complex[] divideAndRemainder(Complex S) {
return quotientRemainder(S);
}
/**
* Complex number greatest common divisor.
* @param S Complex.
* @return gcd(this,S).
*/
public Complex gcd(Complex S) {
if (S == null || S.isZERO()) {
return this;
}
if (this.isZERO()) {
return S;
}
if (ring.isField()) {
return ring.getONE();
}
Complex a = this;
Complex b = S;
if (a.re.signum() < 0) {
a = a.negate();
}
if (b.re.signum() < 0) {
b = b.negate();
}
while (!b.isZERO()) {
if (debug) {
logger.info("norm(b), a, b = " + b.norm() + ", " + a + ", " + b);
}
Complex[] qr = a.quotientRemainder(b);
if (qr[0].isZERO()) {
System.out.println("a = " + a);
}
a = b;
b = qr[1];
}
if (a.re.signum() < 0) {
a = a.negate();
}
return a;
}
/**
* Complex extended greatest common divisor.
* @param S Complex.
* @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
*/
@SuppressWarnings("unchecked")
public Complex[] egcd(Complex S) {
Complex[] ret = new Complex[3];
ret[0] = null;
ret[1] = null;
ret[2] = null;
if (S == null || S.isZERO()) {
ret[0] = this;
return ret;
}
if (this.isZERO()) {
ret[0] = S;
return ret;
}
if (ring.isField()) {
Complex half = new Complex(ring, ring.ring.fromInteger(1).divide(ring.ring.fromInteger(2)));
ret[0] = ring.getONE();
ret[1] = this.inverse().multiply(half);
ret[2] = S.inverse().multiply(half);
return ret;
}
Complex[] qr;
Complex q = this;
Complex r = S;
Complex c1 = ring.getONE();
Complex d1 = ring.getZERO();
Complex c2 = ring.getZERO();
Complex d2 = ring.getONE();
Complex x1;
Complex x2;
while (!r.isZERO()) {
if (debug) {
logger.info("norm(r), q, r = " + r.norm() + ", " + q + ", " + r);
}
qr = q.quotientRemainder(r);
q = qr[0];
x1 = c1.subtract(q.multiply(d1));
x2 = c2.subtract(q.multiply(d2));
c1 = d1;
c2 = d2;
d1 = x1;
d2 = x2;
q = r;
r = qr[1];
}
if (q.re.signum() < 0) {
q = q.negate();
c1 = c1.negate();
c2 = c2.negate();
}
ret[0] = q;
ret[1] = c1;
ret[2] = c2;
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy