001 /* 002 * $Id: Complex.java 3364 2010-10-24 12:56:06Z kredel $ 003 */ 004 005 package edu.jas.poly; 006 007 008 import org.apache.log4j.Logger; 009 010 import edu.jas.arith.BigComplex; 011 import edu.jas.arith.BigDecimal; 012 import edu.jas.arith.BigInteger; 013 import edu.jas.arith.BigRational; 014 import edu.jas.structure.GcdRingElem; 015 import edu.jas.structure.RingElem; 016 import edu.jas.structure.StarRingElem; 017 018 019 /** 020 * Generic Complex class implementing the RingElem interface. Objects of this 021 * class are immutable. 022 * @param <C> base type. 023 * @author Heinz Kredel 024 */ 025 public class Complex<C extends RingElem<C>> implements StarRingElem<Complex<C>>, GcdRingElem<Complex<C>> { 026 027 028 private static final Logger logger = Logger.getLogger(Complex.class); 029 030 031 private static final boolean debug = logger.isDebugEnabled(); 032 033 034 /** 035 * Complex class factory data structure. 036 */ 037 public final ComplexRing<C> ring; 038 039 040 /** 041 * Real part of the data structure. 042 */ 043 protected final C re; 044 045 046 /** 047 * Imaginary part of the data structure. 048 */ 049 protected final C im; 050 051 052 /** 053 * The constructor creates a Complex object from two C objects as real and 054 * imaginary part. 055 * @param ring factory for Complex objects. 056 * @param r real part. 057 * @param i imaginary part. 058 */ 059 public Complex(ComplexRing<C> ring, C r, C i) { 060 this.ring = ring; 061 re = r; 062 im = i; 063 } 064 065 066 /** 067 * The constructor creates a Complex object from a C object as real part, 068 * the imaginary part is set to 0. 069 * @param r real part. 070 */ 071 public Complex(ComplexRing<C> ring, C r) { 072 this(ring, r, ring.ring.getZERO()); 073 } 074 075 076 /** 077 * The constructor creates a Complex object from a long element as real 078 * part, the imaginary part is set to 0. 079 * @param r real part. 080 */ 081 public Complex(ComplexRing<C> ring, long r) { 082 this(ring, ring.ring.fromInteger(r)); 083 } 084 085 086 /** 087 * The constructor creates a Complex object with real part 0 and imaginary 088 * part 0. 089 */ 090 public Complex(ComplexRing<C> ring) { 091 this(ring, ring.ring.getZERO()); 092 } 093 094 095 /** 096 * The constructor creates a Complex object from a String representation. 097 * @param s string of a Complex. 098 * @throws NumberFormatException 099 */ 100 public Complex(ComplexRing<C> ring, String s) throws NumberFormatException { 101 this.ring = ring; 102 if (s == null || s.length() == 0) { 103 re = ring.ring.getZERO(); 104 im = ring.ring.getZERO(); 105 return; 106 } 107 s = s.trim(); 108 int i = s.indexOf("i"); 109 if (i < 0) { 110 re = ring.ring.parse(s); 111 im = ring.ring.getZERO(); 112 return; 113 } 114 //logger.warn("String constructor not done"); 115 String sr = ""; 116 if (i > 0) { 117 sr = s.substring(0, i); 118 } 119 String si = ""; 120 if (i < s.length()) { 121 si = s.substring(i + 1, s.length()); 122 } 123 //int j = sr.indexOf("+"); 124 re = ring.ring.parse(sr.trim()); 125 im = ring.ring.parse(si.trim()); 126 } 127 128 129 /** 130 * Get the corresponding element factory. 131 * @return factory for this Element. 132 * @see edu.jas.structure.Element#factory() 133 */ 134 public ComplexRing<C> factory() { 135 return ring; 136 } 137 138 139 /** 140 * Get the real part. 141 * @return re. 142 */ 143 public C getRe() { 144 return re; 145 } 146 147 148 /** 149 * Get the imaginary part. 150 * @return im. 151 */ 152 public C getIm() { 153 return im; 154 } 155 156 157 /** 158 * Clone this. 159 * @see java.lang.Object#clone() 160 */ 161 @Override 162 public Complex<C> clone() { 163 return new Complex<C>(ring, re, im); 164 } 165 166 167 /** 168 * Get the String representation. 169 */ 170 @Override 171 public String toString() { 172 String s = re.toString(); 173 //logger.info("compareTo "+im+" ? 0 = "+i); 174 if (im.isZERO()) { 175 return s; 176 } 177 s += "i" + im; 178 return s; 179 } 180 181 182 /** 183 * Get a scripting compatible string representation. 184 * @return script compatible representation for this Element. 185 * @see edu.jas.structure.Element#toScript() 186 */ 187 //JAVA6only: @Override 188 public String toScript() { 189 // Python case 190 StringBuffer s = new StringBuffer(); 191 if (im.isZERO()) { 192 s.append(re.toScript()); 193 } else { 194 s.append(""); 195 if (!re.isZERO()) { 196 s.append(re.toScript()); 197 s.append(" + "); 198 } 199 if (im.isONE()) { 200 s.append("I"); 201 } else { 202 s.append(im.toScript()).append(" * I"); 203 } 204 s.append(""); 205 } 206 return s.toString(); 207 } 208 209 210 /** 211 * Get a scripting compatible string representation of the factory. 212 * @return script compatible representation for this ElemFactory. 213 * @see edu.jas.structure.Element#toScriptFactory() 214 */ 215 //JAVA6only: @Override 216 public String toScriptFactory() { 217 // Python case 218 return ring.toScript(); 219 } 220 221 222 /** 223 * Is Complex number zero. 224 * @return If this is 0 then true is returned, else false. 225 * @see edu.jas.structure.RingElem#isZERO() 226 */ 227 public boolean isZERO() { 228 return re.isZERO() && im.isZERO(); 229 } 230 231 232 /** 233 * Is Complex number one. 234 * @return If this is 1 then true is returned, else false. 235 * @see edu.jas.structure.RingElem#isONE() 236 */ 237 public boolean isONE() { 238 return re.isONE() && im.isZERO(); 239 } 240 241 242 /** 243 * Is Complex imaginary one. 244 * @return If this is i then true is returned, else false. 245 */ 246 public boolean isIMAG() { 247 return re.isZERO() && im.isONE(); 248 } 249 250 251 /** 252 * Is Complex unit element. 253 * @return If this is a unit then true is returned, else false. 254 * @see edu.jas.structure.RingElem#isUnit() 255 */ 256 public boolean isUnit() { 257 if (isZERO()) { 258 return false; 259 } 260 if (ring.isField()) { 261 return true; 262 } 263 return norm().re.isUnit(); 264 } 265 266 267 /** 268 * Comparison with any other object. 269 * @see java.lang.Object#equals(java.lang.Object) 270 */ 271 @Override 272 @SuppressWarnings("unchecked") 273 public boolean equals(Object b) { 274 if (!(b instanceof Complex)) { 275 return false; 276 } 277 Complex<C> bc = null; 278 try { 279 bc = (Complex<C>) b; 280 } catch (ClassCastException e) { 281 } 282 if (bc == null) { 283 return false; 284 } 285 if (!ring.equals(bc.ring)) { 286 return false; 287 } 288 return re.equals(bc.re) && im.equals(bc.im); 289 } 290 291 292 /** 293 * Hash code for this Complex. 294 * @see java.lang.Object#hashCode() 295 */ 296 @Override 297 public int hashCode() { 298 return 37 * re.hashCode() + im.hashCode(); 299 } 300 301 302 /** 303 * Since complex numbers are unordered, we use lexicographical order of re 304 * and im. 305 * @return 0 if this is equal to b; 1 if re > b.re, or re == b.re and im > 306 * b.im; -1 if re < b.re, or re == b.re and im < b.im 307 */ 308 //JAVA6only: @Override 309 public int compareTo(Complex<C> b) { 310 int s = re.compareTo(b.re); 311 if (s != 0) { 312 return s; 313 } 314 return im.compareTo(b.im); 315 } 316 317 318 /** 319 * Since complex numbers are unordered, we use lexicographical order of re 320 * and im. 321 * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0; -1 322 * if re < 0, or re == 0 and im < 0 323 * @see edu.jas.structure.RingElem#signum() 324 */ 325 public int signum() { 326 int s = re.signum(); 327 if (s != 0) { 328 return s; 329 } 330 return im.signum(); 331 } 332 333 334 /* arithmetic operations: +, -, - 335 */ 336 337 /** 338 * Complex number summation. 339 * @param B a Complex<C> number. 340 * @return this+B. 341 */ 342 public Complex<C> sum(Complex<C> B) { 343 return new Complex<C>(ring, re.sum(B.re), im.sum(B.im)); 344 } 345 346 347 /** 348 * Complex number subtract. 349 * @param B a Complex<C> number. 350 * @return this-B. 351 */ 352 public Complex<C> subtract(Complex<C> B) { 353 return new Complex<C>(ring, re.subtract(B.re), im.subtract(B.im)); 354 } 355 356 357 /** 358 * Complex number negative. 359 * @return -this. 360 * @see edu.jas.structure.RingElem#negate() 361 */ 362 public Complex<C> negate() { 363 return new Complex<C>(ring, re.negate(), im.negate()); 364 } 365 366 367 /* arithmetic operations: conjugate, absolut value 368 */ 369 370 /** 371 * Complex number conjugate. 372 * @return the complex conjugate of this. 373 */ 374 public Complex<C> conjugate() { 375 return new Complex<C>(ring, re, im.negate()); 376 } 377 378 379 /** 380 * Complex number norm. 381 * @see edu.jas.structure.StarRingElem#norm() 382 * @return ||this||. 383 */ 384 public Complex<C> norm() { 385 // this.conjugate().multiply(this); 386 C v = re.multiply(re); 387 v = v.sum(im.multiply(im)); 388 return new Complex<C>(ring, v); 389 } 390 391 392 /** 393 * Complex number absolute value. 394 * @see edu.jas.structure.RingElem#abs() 395 * @return |this|^2. <b>Note:</b> The square root is not jet implemented. 396 */ 397 public Complex<C> abs() { 398 Complex<C> n = norm(); 399 logger.error("abs() square root missing"); 400 // n = n.sqrt(); 401 return n; 402 } 403 404 405 /* arithmetic operations: *, inverse, / 406 */ 407 408 409 /** 410 * Complex number product. 411 * @param B is a complex number. 412 * @return this*B. 413 */ 414 public Complex<C> multiply(Complex<C> B) { 415 return new Complex<C>(ring, re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum( 416 im.multiply(B.re))); 417 } 418 419 420 /** 421 * Complex number inverse. 422 * @return S with S*this = 1, if it is defined. 423 * @see edu.jas.structure.RingElem#inverse() 424 */ 425 public Complex<C> inverse() { 426 C a = norm().re.inverse(); 427 return new Complex<C>(ring, re.multiply(a), im.multiply(a.negate())); 428 } 429 430 431 /** 432 * Complex number remainder. 433 * @param S is a complex number. 434 * @return 0. 435 */ 436 public Complex<C> remainder(Complex<C> S) { 437 if (ring.isField()) { 438 return ring.getZERO(); 439 } 440 return quotientRemainder(S)[1]; 441 } 442 443 444 /** 445 * Complex number divide. 446 * @param B is a complex number, non-zero. 447 * @return this/B. 448 */ 449 public Complex<C> divide(Complex<C> B) { 450 if (ring.isField()) { 451 return this.multiply(B.inverse()); 452 } 453 return quotientRemainder(B)[0]; 454 } 455 456 457 /** 458 * Complex number quotient and remainder. 459 * @param S Complex. 460 * @return Complex[] { q, r } with q = this/S and r = rem(this,S). 461 */ 462 @SuppressWarnings("unchecked") 463 public Complex<C>[] quotientRemainder(Complex<C> S) { 464 Complex<C>[] ret = new Complex[2]; 465 C n = S.norm().re; 466 Complex<C> Sp = this.multiply(S.conjugate()); // == this*inv(S)*n 467 C qr = Sp.re.divide(n); 468 C rr = Sp.re.remainder(n); 469 C qi = Sp.im.divide(n); 470 C ri = Sp.im.remainder(n); 471 C rr1 = rr; 472 C ri1 = ri; 473 if (rr.signum() < 0) { 474 rr = rr.negate(); 475 } 476 if (ri.signum() < 0) { 477 ri = ri.negate(); 478 } 479 C one = n.factory().fromInteger(1); 480 if (rr.sum(rr).compareTo(n) > 0) { // rr > n/2 481 if (rr1.signum() < 0) { 482 qr = qr.subtract(one); 483 } else { 484 qr = qr.sum(one); 485 } 486 } 487 if (ri.sum(ri).compareTo(n) > 0) { // ri > n/2 488 if (ri1.signum() < 0) { 489 qi = qi.subtract(one); 490 } else { 491 qi = qi.sum(one); 492 } 493 } 494 Sp = new Complex<C>(ring, qr, qi); 495 Complex<C> Rp = this.subtract(Sp.multiply(S)); 496 if (debug && n.compareTo(Rp.norm().re) < 0) { 497 System.out.println("n = " + n); 498 System.out.println("qr = " + qr); 499 System.out.println("qi = " + qi); 500 System.out.println("rr = " + rr); 501 System.out.println("ri = " + ri); 502 System.out.println("rr1 = " + rr1); 503 System.out.println("ri1 = " + ri1); 504 System.out.println("this = " + this); 505 System.out.println("S = " + S); 506 System.out.println("Sp = " + Sp); 507 BigInteger tr = (BigInteger) (Object) this.re; 508 BigInteger ti = (BigInteger) (Object) this.im; 509 BigInteger sr = (BigInteger) (Object) S.re; 510 BigInteger si = (BigInteger) (Object) S.im; 511 BigComplex tc = new BigComplex(new BigRational(tr), new BigRational(ti)); 512 BigComplex sc = new BigComplex(new BigRational(sr), new BigRational(si)); 513 BigComplex qc = tc.divide(sc); 514 System.out.println("qc = " + qc); 515 BigDecimal qrd = new BigDecimal(qc.getRe()); 516 BigDecimal qid = new BigDecimal(qc.getIm()); 517 System.out.println("qrd = " + qrd); 518 System.out.println("qid = " + qid); 519 throw new ArithmeticException("QR norm not decreasing " + Rp + ", " + Rp.norm()); 520 } 521 ret[0] = Sp; 522 ret[1] = Rp; 523 return ret; 524 } 525 526 527 /** 528 * Complex number quotient and remainder. 529 * @param S Complex. 530 * @return Complex[] { q, r } with q = this/S and r = rem(this,S). 531 * @deprecated use quotientRemainder() 532 */ 533 @Deprecated 534 public Complex<C>[] divideAndRemainder(Complex<C> S) { 535 return quotientRemainder(S); 536 } 537 538 539 /** 540 * Complex number greatest common divisor. 541 * @param S Complex<C>. 542 * @return gcd(this,S). 543 */ 544 public Complex<C> gcd(Complex<C> S) { 545 if (S == null || S.isZERO()) { 546 return this; 547 } 548 if (this.isZERO()) { 549 return S; 550 } 551 if (ring.isField()) { 552 return ring.getONE(); 553 } 554 Complex<C> a = this; 555 Complex<C> b = S; 556 if (a.re.signum() < 0) { 557 a = a.negate(); 558 } 559 if (b.re.signum() < 0) { 560 b = b.negate(); 561 } 562 while (!b.isZERO()) { 563 if (debug) { 564 logger.info("norm(b), a, b = " + b.norm() + ", " + a + ", " + b); 565 } 566 Complex<C>[] qr = a.quotientRemainder(b); 567 if (qr[0].isZERO()) { 568 System.out.println("a = " + a); 569 } 570 a = b; 571 b = qr[1]; 572 } 573 if (a.re.signum() < 0) { 574 a = a.negate(); 575 } 576 return a; 577 } 578 579 580 /** 581 * Complex extended greatest common divisor. 582 * @param S Complex<C>. 583 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 584 */ 585 @SuppressWarnings("unchecked") 586 public Complex<C>[] egcd(Complex<C> S) { 587 Complex<C>[] ret = new Complex[3]; 588 ret[0] = null; 589 ret[1] = null; 590 ret[2] = null; 591 if (S == null || S.isZERO()) { 592 ret[0] = this; 593 return ret; 594 } 595 if (this.isZERO()) { 596 ret[0] = S; 597 return ret; 598 } 599 if (ring.isField()) { 600 Complex<C> half = new Complex<C>(ring, ring.ring.fromInteger(1).divide(ring.ring.fromInteger(2))); 601 ret[0] = ring.getONE(); 602 ret[1] = this.inverse().multiply(half); 603 ret[2] = S.inverse().multiply(half); 604 return ret; 605 } 606 Complex<C>[] qr; 607 Complex<C> q = this; 608 Complex<C> r = S; 609 Complex<C> c1 = ring.getONE(); 610 Complex<C> d1 = ring.getZERO(); 611 Complex<C> c2 = ring.getZERO(); 612 Complex<C> d2 = ring.getONE(); 613 Complex<C> x1; 614 Complex<C> x2; 615 while (!r.isZERO()) { 616 if (debug) { 617 logger.info("norm(r), q, r = " + r.norm() + ", " + q + ", " + r); 618 } 619 qr = q.quotientRemainder(r); 620 q = qr[0]; 621 x1 = c1.subtract(q.multiply(d1)); 622 x2 = c2.subtract(q.multiply(d2)); 623 c1 = d1; 624 c2 = d2; 625 d1 = x1; 626 d2 = x2; 627 q = r; 628 r = qr[1]; 629 } 630 if (q.re.signum() < 0) { 631 q = q.negate(); 632 c1 = c1.negate(); 633 c2 = c2.negate(); 634 } 635 ret[0] = q; 636 ret[1] = c1; 637 ret[2] = c2; 638 return ret; 639 } 640 641 }