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