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