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