001/* 002 * $Id: BigComplex.java 4125 2012-08-19 19:05:22Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008import java.io.Reader; 009import java.math.BigInteger; 010import java.util.ArrayList; 011import java.util.List; 012import java.util.Random; 013 014import org.apache.log4j.Logger; 015 016import edu.jas.kern.StringUtil; 017import edu.jas.structure.GcdRingElem; 018import edu.jas.structure.RingFactory; 019import edu.jas.structure.StarRingElem; 020 021 022/** 023 * BigComplex class based on BigRational implementing the RingElem respectively 024 * the StarRingElem interface. Objects of this class are immutable. The SAC2 025 * static methods are also provided. 026 * @author Heinz Kredel 027 */ 028public final class BigComplex implements StarRingElem<BigComplex>, GcdRingElem<BigComplex>, 029 RingFactory<BigComplex> { 030 031 032 /** 033 * Real part of the data structure. 034 */ 035 public final BigRational re; 036 037 038 /** 039 * Imaginary part of the data structure. 040 */ 041 public final BigRational im; 042 043 044 private final static Random random = new Random(); 045 046 047 private static final Logger logger = Logger.getLogger(BigComplex.class); 048 049 050 /** 051 * The constructor creates a BigComplex object from two BigRational objects 052 * real and imaginary part. 053 * @param r real part. 054 * @param i imaginary part. 055 */ 056 public BigComplex(BigRational r, BigRational i) { 057 re = r; 058 im = i; 059 } 060 061 062 /** 063 * The constructor creates a BigComplex object from a BigRational object as 064 * real part, the imaginary part is set to 0. 065 * @param r real part. 066 */ 067 public BigComplex(BigRational r) { 068 this(r, BigRational.ZERO); 069 } 070 071 072 /** 073 * The constructor creates a BigComplex object from a long element as real 074 * part, the imaginary part is set to 0. 075 * @param r real part. 076 */ 077 public BigComplex(long r) { 078 this(new BigRational(r), BigRational.ZERO); 079 } 080 081 082 /** 083 * The constructor creates a BigComplex object with real part 0 and 084 * imaginary part 0. 085 */ 086 public BigComplex() { 087 this(BigRational.ZERO); 088 } 089 090 091 /** 092 * The constructor creates a BigComplex object from a String representation. 093 * @param s string of a BigComplex. 094 * @throws NumberFormatException 095 */ 096 public BigComplex(String s) throws NumberFormatException { 097 if (s == null || s.length() == 0) { 098 re = BigRational.ZERO; 099 im = BigRational.ZERO; 100 return; 101 } 102 s = s.trim(); 103 int i = s.indexOf("i"); 104 if (i < 0) { 105 re = new BigRational(s); 106 im = BigRational.ZERO; 107 return; 108 } 109 //logger.warn("String constructor not done"); 110 String sr = ""; 111 if (i > 0) { 112 sr = s.substring(0, i); 113 } 114 String si = ""; 115 if (i < s.length()) { 116 si = s.substring(i + 1, s.length()); 117 } 118 //int j = sr.indexOf("+"); 119 re = new BigRational(sr.trim()); 120 im = new BigRational(si.trim()); 121 } 122 123 124 /** 125 * Get the corresponding element factory. 126 * @return factory for this Element. 127 * @see edu.jas.structure.Element#factory() 128 */ 129 public BigComplex factory() { 130 return this; 131 } 132 133 134 /** 135 * Get a list of the generating elements. 136 * @return list of generators for the algebraic structure. 137 * @see edu.jas.structure.ElemFactory#generators() 138 */ 139 public List<BigComplex> generators() { 140 List<BigComplex> g = new ArrayList<BigComplex>(2); 141 g.add(getONE()); 142 g.add(getIMAG()); 143 return g; 144 } 145 146 147 /** 148 * Is this structure finite or infinite. 149 * @return true if this structure is finite, else false. 150 * @see edu.jas.structure.ElemFactory#isFinite() 151 */ 152 public boolean isFinite() { 153 return false; 154 } 155 156 157 /** 158 * Clone this. 159 * @see java.lang.Object#clone() 160 */ 161 @Override 162 public BigComplex copy() { 163 return new BigComplex(re, im); 164 } 165 166 167 /** 168 * Copy BigComplex element c. 169 * @param c BigComplex. 170 * @return a copy of c. 171 */ 172 public BigComplex copy(BigComplex c) { 173 return new BigComplex(c.re, c.im); 174 } 175 176 177 /** 178 * Get the zero element. 179 * @return 0 as BigComplex. 180 */ 181 public BigComplex getZERO() { 182 return ZERO; 183 } 184 185 186 /** 187 * Get the one element. 188 * @return 1 as BigComplex. 189 */ 190 public BigComplex getONE() { 191 return ONE; 192 } 193 194 195 /** 196 * Get the i element. 197 * @return i as BigComplex. 198 */ 199 public BigComplex getIMAG() { 200 return I; 201 } 202 203 204 /** 205 * Query if this ring is commutative. 206 * @return true. 207 */ 208 public boolean isCommutative() { 209 return true; 210 } 211 212 213 /** 214 * Query if this ring is associative. 215 * @return true. 216 */ 217 public boolean isAssociative() { 218 return true; 219 } 220 221 222 /** 223 * Query if this ring is a field. 224 * @return true. 225 */ 226 public boolean isField() { 227 return true; 228 } 229 230 231 /** 232 * Characteristic of this ring. 233 * @return characteristic of this ring. 234 */ 235 public java.math.BigInteger characteristic() { 236 return java.math.BigInteger.ZERO; 237 } 238 239 240 /** 241 * Get a BigComplex element from a BigInteger. 242 * @param a BigInteger. 243 * @return a BigComplex. 244 */ 245 public BigComplex fromInteger(BigInteger a) { 246 return new BigComplex(new BigRational(a)); 247 } 248 249 250 /** 251 * Get a BigComplex element from a long. 252 * @param a long. 253 * @return a BigComplex. 254 */ 255 public BigComplex fromInteger(long a) { 256 return new BigComplex(new BigRational(a)); 257 } 258 259 260 /** 261 * The constant 0. 262 */ 263 public static final BigComplex ZERO = new BigComplex(); 264 265 266 /** 267 * The constant 1. 268 */ 269 public static final BigComplex ONE = new BigComplex(BigRational.ONE); 270 271 272 /** 273 * The constant i. 274 */ 275 public static final BigComplex I = new BigComplex(BigRational.ZERO, BigRational.ONE); 276 277 278 /** 279 * Get the real part. 280 * @return re. 281 */ 282 public BigRational getRe() { 283 return re; 284 } 285 286 287 /** 288 * Get the imaginary part. 289 * @return im. 290 */ 291 public BigRational getIm() { 292 return im; 293 } 294 295 296 /** 297 * Get the String representation. 298 */ 299 @Override 300 public String toString() { 301 String s = "" + re; 302 int i = im.compareTo(BigRational.ZERO); 303 //logger.info("compareTo "+im+" ? 0 = "+i); 304 if (i == 0) 305 return s; 306 s += "i" + im; 307 return s; 308 } 309 310 311 /** 312 * Get a scripting compatible string representation. 313 * @return script compatible representation for this Element. 314 * @see edu.jas.structure.Element#toScript() 315 */ 316 //JAVA6only: @Override 317 public String toScript() { 318 // Python case: re or re+im*i 319 // was (re,im) or (re,) 320 StringBuffer s = new StringBuffer(); 321 boolean iz = im.isZERO(); 322 if (iz) { 323 s.append(re.toScript()); 324 return s.toString(); 325 } 326 boolean rz = re.isZERO(); 327 if (rz) { 328 if (!im.isONE()) { 329 if (im.signum() > 0) { 330 s.append(im.toScript() + "*"); 331 } else { 332 s.append("-"); 333 BigRational ii = im.negate(); 334 if (!ii.isONE()) { 335 s.append(ii.toScript() + "*"); 336 } 337 } 338 } 339 } else { 340 s.append(re.toScript()); 341 if (im.signum() > 0) { 342 s.append("+"); 343 if (!im.isONE()) { 344 s.append(im.toScript() + "*"); 345 } 346 } else { 347 s.append("-"); 348 BigRational ii = im.negate(); 349 if (!ii.isONE()) { 350 s.append(ii.toScript() + "*"); 351 } 352 } 353 } 354 s.append("I"); 355 return s.toString(); 356 } 357 358 359 /** 360 * Get a scripting compatible string representation of the factory. 361 * @return script compatible representation for this ElemFactory. 362 * @see edu.jas.structure.Element#toScriptFactory() 363 */ 364 //JAVA6only: @Override 365 public String toScriptFactory() { 366 // Python case 367 return "CC()"; 368 } 369 370 371 /** 372 * Complex number zero. 373 * @param A is a complex number. 374 * @return If A is 0 then true is returned, else false. 375 */ 376 public static boolean isCZERO(BigComplex A) { 377 if (A == null) 378 return false; 379 return A.isZERO(); 380 } 381 382 383 /** 384 * Is Complex number zero. 385 * @return If this is 0 then true is returned, else false. 386 * @see edu.jas.structure.RingElem#isZERO() 387 */ 388 public boolean isZERO() { 389 return re.equals(BigRational.ZERO) && im.equals(BigRational.ZERO); 390 } 391 392 393 /** 394 * Complex number one. 395 * @param A is a complex number. 396 * @return If A is 1 then true is returned, else false. 397 */ 398 public static boolean isCONE(BigComplex A) { 399 if (A == null) 400 return false; 401 return A.isONE(); 402 } 403 404 405 /** 406 * Is Complex number one. 407 * @return If this is 1 then true is returned, else false. 408 * @see edu.jas.structure.RingElem#isONE() 409 */ 410 public boolean isONE() { 411 return re.equals(BigRational.ONE) && im.equals(BigRational.ZERO); 412 } 413 414 415 /** 416 * Is Complex imaginary one. 417 * @return If this is i then true is returned, else false. 418 */ 419 public boolean isIMAG() { 420 return re.equals(BigRational.ZERO) && im.equals(BigRational.ONE); 421 } 422 423 424 /** 425 * Is Complex unit element. 426 * @return If this is a unit then true is returned, else false. 427 * @see edu.jas.structure.RingElem#isUnit() 428 */ 429 public boolean isUnit() { 430 return (!isZERO()); 431 } 432 433 434 /** 435 * Comparison with any other object. 436 * @see java.lang.Object#equals(java.lang.Object) 437 */ 438 @Override 439 public boolean equals(Object b) { 440 if (!(b instanceof BigComplex)) { 441 return false; 442 } 443 BigComplex bc = (BigComplex) b; 444 return re.equals(bc.re) && im.equals(bc.im); 445 } 446 447 448 /** 449 * Hash code for this BigComplex. 450 * @see java.lang.Object#hashCode() 451 */ 452 @Override 453 public int hashCode() { 454 return 37 * re.hashCode() + im.hashCode(); 455 } 456 457 458 /** 459 * Since complex numbers are unordered, we use lexicographical order of re 460 * and im. 461 * @return 0 if this is equal to b; 1 if re > b.re, or re == b.re and im > 462 * b.im; -1 if re < b.re, or re == b.re and im < b.im 463 */ 464 //JAVA6only: @Override 465 public int compareTo(BigComplex b) { 466 int s = re.compareTo(b.re); 467 if (s != 0) { 468 return s; 469 } 470 return im.compareTo(b.im); 471 } 472 473 474 /** 475 * Since complex numbers are unordered, we use lexicographical order of re 476 * and im. 477 * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0; -1 478 * if re < 0, or re == 0 and im < 0 479 * @see edu.jas.structure.RingElem#signum() 480 */ 481 public int signum() { 482 int s = re.signum(); 483 if (s != 0) { 484 return s; 485 } 486 return im.signum(); 487 } 488 489 490 /* arithmetic operations: +, -, - 491 */ 492 493 /** 494 * Complex number summation. 495 * @param B a BigComplex number. 496 * @return this+B. 497 */ 498 public BigComplex sum(BigComplex B) { 499 return new BigComplex(re.sum(B.re), im.sum(B.im)); 500 } 501 502 503 /** 504 * Complex number sum. 505 * @param A and B are complex numbers. 506 * @return A+B. 507 */ 508 public static BigComplex CSUM(BigComplex A, BigComplex B) { 509 if (A == null) 510 return null; 511 return A.sum(B); 512 } 513 514 515 /** 516 * Complex number difference. 517 * @param A and B are complex numbers. 518 * @return A-B. 519 */ 520 public static BigComplex CDIF(BigComplex A, BigComplex B) { 521 if (A == null) 522 return null; 523 return A.subtract(B); 524 } 525 526 527 /** 528 * Complex number subtract. 529 * @param B a BigComplex number. 530 * @return this-B. 531 */ 532 public BigComplex subtract(BigComplex B) { 533 return new BigComplex(re.subtract(B.re), im.subtract(B.im)); 534 } 535 536 537 /** 538 * Complex number negative. 539 * @param A is a complex number. 540 * @return -A 541 */ 542 public static BigComplex CNEG(BigComplex A) { 543 if (A == null) 544 return null; 545 return A.negate(); 546 } 547 548 549 /** 550 * Complex number negative. 551 * @return -this. 552 * @see edu.jas.structure.RingElem#negate() 553 */ 554 public BigComplex negate() { 555 return new BigComplex(re.negate(), im.negate()); 556 } 557 558 559 /** 560 * Complex number conjugate. 561 * @param A is a complex number. 562 * @return the complex conjugate of A. 563 */ 564 public static BigComplex CCON(BigComplex A) { 565 if (A == null) 566 return null; 567 return A.conjugate(); 568 } 569 570 571 /* arithmetic operations: conjugate, absolut value 572 */ 573 574 /** 575 * Complex number conjugate. 576 * @return the complex conjugate of this. 577 */ 578 public BigComplex conjugate() { 579 return new BigComplex(re, im.negate()); 580 } 581 582 583 /** 584 * Complex number norm. 585 * @see edu.jas.structure.StarRingElem#norm() 586 * @return ||this||. 587 */ 588 public BigComplex norm() { 589 // this.conjugate().multiply(this); 590 BigRational v = re.multiply(re); 591 v = v.sum(im.multiply(im)); 592 return new BigComplex(v); 593 } 594 595 596 /** 597 * Complex number absolute value. 598 * @see edu.jas.structure.RingElem#abs() 599 * @return |this|^2. Note: The square root is not jet implemented. 600 */ 601 public BigComplex abs() { 602 BigComplex n = norm(); 603 logger.error("abs() square root missing"); 604 // n = n.sqrt(); 605 return n; 606 } 607 608 609 /** 610 * Complex number absolute value. 611 * @param A is a complex number. 612 * @return the absolute value of A, a rational number. Note: The square root 613 * is not jet implemented. 614 */ 615 public static BigRational CABS(BigComplex A) { 616 if (A == null) 617 return null; 618 return A.abs().re; 619 } 620 621 622 /** 623 * Complex number product. 624 * @param A and B are complex numbers. 625 * @return A*B. 626 */ 627 public static BigComplex CPROD(BigComplex A, BigComplex B) { 628 if (A == null) 629 return null; 630 return A.multiply(B); 631 } 632 633 634 /* arithmetic operations: *, inverse, / 635 */ 636 637 638 /** 639 * Complex number product. 640 * @param B is a complex number. 641 * @return this*B. 642 */ 643 public BigComplex multiply(BigComplex B) { 644 return new BigComplex(re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum( 645 im.multiply(B.re))); 646 } 647 648 649 /** 650 * Complex number inverse. 651 * @param A is a non-zero complex number. 652 * @return S with S*A = 1. 653 */ 654 public static BigComplex CINV(BigComplex A) { 655 if (A == null) 656 return null; 657 return A.inverse(); 658 } 659 660 661 /** 662 * Complex number inverse. 663 * @return S with S*this = 1. 664 * @see edu.jas.structure.RingElem#inverse() 665 */ 666 public BigComplex inverse() { 667 BigRational a = norm().re.inverse(); 668 return new BigComplex(re.multiply(a), im.multiply(a.negate())); 669 } 670 671 672 /** 673 * Complex number inverse. 674 * @param S is a complex number. 675 * @return 0. 676 */ 677 public BigComplex remainder(BigComplex S) { 678 if (S.isZERO()) { 679 throw new ArithmeticException("division by zero"); 680 } 681 return ZERO; 682 } 683 684 685 /** 686 * Complex number quotient. 687 * @param A and B are complex numbers, B non-zero. 688 * @return A/B. 689 */ 690 public static BigComplex CQ(BigComplex A, BigComplex B) { 691 if (A == null) 692 return null; 693 return A.divide(B); 694 } 695 696 697 /** 698 * Complex number divide. 699 * @param B is a complex number, non-zero. 700 * @return this/B. 701 */ 702 public BigComplex divide(BigComplex B) { 703 return this.multiply(B.inverse()); 704 } 705 706 707 /** 708 * Complex number, random. Random rational numbers A and B are generated 709 * using random(n). Then R is the complex number with real part A and 710 * imaginary part B. 711 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 712 * @return R. 713 */ 714 public BigComplex random(int n) { 715 return random(n, random); 716 } 717 718 719 /** 720 * Complex number, random. Random rational numbers A and B are generated 721 * using random(n). Then R is the complex number with real part A and 722 * imaginary part B. 723 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 724 * @param rnd is a source for random bits. 725 * @return R. 726 */ 727 public BigComplex random(int n, Random rnd) { 728 BigRational r = BigRational.ONE.random(n, rnd); 729 BigRational i = BigRational.ONE.random(n, rnd); 730 return new BigComplex(r, i); 731 } 732 733 734 /** 735 * Complex number, random. Random rational numbers A and B are generated 736 * using random(n). Then R is the complex number with real part A and 737 * imaginary part B. 738 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 739 * @return R. 740 */ 741 public static BigComplex CRAND(int n) { 742 return ONE.random(n, random); 743 } 744 745 746 /** 747 * Parse complex number from string. 748 * @param s String. 749 * @return BigComplex from s. 750 */ 751 public BigComplex parse(String s) { 752 return new BigComplex(s); 753 } 754 755 756 /** 757 * Parse complex number from Reader. 758 * @param r Reader. 759 * @return next BigComplex from r. 760 */ 761 public BigComplex parse(Reader r) { 762 return parse(StringUtil.nextString(r)); 763 } 764 765 766 /** 767 * Complex number greatest common divisor. 768 * @param S BigComplex. 769 * @return gcd(this,S). 770 */ 771 public BigComplex gcd(BigComplex S) { 772 if (S == null || S.isZERO()) { 773 return this; 774 } 775 if (this.isZERO()) { 776 return S; 777 } 778 return ONE; 779 } 780 781 782 /** 783 * BigComplex extended greatest common divisor. 784 * @param S BigComplex. 785 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 786 */ 787 public BigComplex[] egcd(BigComplex S) { 788 BigComplex[] ret = new BigComplex[3]; 789 ret[0] = null; 790 ret[1] = null; 791 ret[2] = null; 792 if (S == null || S.isZERO()) { 793 ret[0] = this; 794 return ret; 795 } 796 if (this.isZERO()) { 797 ret[0] = S; 798 return ret; 799 } 800 BigComplex half = new BigComplex(new BigRational(1, 2)); 801 ret[0] = ONE; 802 ret[1] = this.inverse().multiply(half); 803 ret[2] = S.inverse().multiply(half); 804 return ret; 805 } 806 807}