001/* 002 * $Id$ 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 {} ? 0 = {}", im, 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 logger.debug("sqrt(re) = {}", d); 632 return new BigDecimalComplex(d); 633 } 634 635 636 /** 637 * Complex number absolute value. 638 * @param A is a complex number. 639 * @return the absolute value of A, a rational number. Note: The square root 640 * is not jet implemented. 641 */ 642 public static BigDecimal CABS(BigDecimalComplex A) { 643 if (A == null) { 644 return null; 645 } 646 return A.abs().re; 647 } 648 649 650 /** 651 * Complex number product. 652 * @param A and B are complex numbers. 653 * @return A*B. 654 */ 655 public static BigDecimalComplex CPROD(BigDecimalComplex A, BigDecimalComplex B) { 656 if (A == null) { 657 return null; 658 } 659 return A.multiply(B); 660 } 661 662 663 /* arithmetic operations: *, inverse, / 664 */ 665 666 667 /** 668 * Complex number product. 669 * @param B is a complex number. 670 * @return this*B. 671 */ 672 public BigDecimalComplex multiply(BigDecimalComplex B) { 673 return new BigDecimalComplex(re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum( 674 im.multiply(B.re))); 675 } 676 677 678 /** 679 * Complex number inverse. 680 * @param A is a non-zero complex number. 681 * @return S with S*A = 1. 682 */ 683 public static BigDecimalComplex CINV(BigDecimalComplex A) { 684 if (A == null) { 685 return null; 686 } 687 return A.inverse(); 688 } 689 690 691 /** 692 * Complex number inverse. 693 * @return S with S*this = 1. 694 * @see edu.jas.structure.RingElem#inverse() 695 */ 696 public BigDecimalComplex inverse() { 697 BigDecimal a = norm().re.inverse(); 698 return new BigDecimalComplex(re.multiply(a), im.multiply(a.negate())); 699 } 700 701 702 /** 703 * Complex number inverse. 704 * @param S is a complex number. 705 * @return 0. 706 */ 707 public BigDecimalComplex remainder(BigDecimalComplex S) { 708 if (S.isZERO()) { 709 throw new ArithmeticException("division by zero"); 710 } 711 return ZERO; 712 } 713 714 715 /** 716 * Complex number quotient. 717 * @param A and B are complex numbers, B non-zero. 718 * @return A/B. 719 */ 720 public static BigDecimalComplex CQ(BigDecimalComplex A, BigDecimalComplex B) { 721 if (A == null) { 722 return null; 723 } 724 return A.divide(B); 725 } 726 727 728 /** 729 * Complex number divide. 730 * @param B is a complex number, non-zero. 731 * @return this/B. 732 */ 733 public BigDecimalComplex divide(BigDecimalComplex B) { 734 return this.multiply(B.inverse()); 735 } 736 737 738 /** 739 * Quotient and remainder by division of this by S. 740 * @param S a complex number 741 * @return [this/S, this - (this/S)*S]. 742 */ 743 public BigDecimalComplex[] quotientRemainder(BigDecimalComplex S) { 744 return new BigDecimalComplex[] { divide(S), ZERO }; 745 } 746 747 748 /** 749 * Complex number, random. Random rational numbers A and B are generated 750 * using random(n). Then R is the complex number with real part A and 751 * imaginary part B. 752 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 753 * @return R. 754 */ 755 public BigDecimalComplex random(int n) { 756 return random(n, random); 757 } 758 759 760 /** 761 * Complex number, random. Random rational numbers A and B are generated 762 * using random(n). Then R is the complex number with real part A and 763 * imaginary part B. 764 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 765 * @param rnd is a source for random bits. 766 * @return R. 767 */ 768 public BigDecimalComplex random(int n, Random rnd) { 769 BigDecimal r = BigDecimal.ONE.random(n, rnd); 770 BigDecimal i = BigDecimal.ONE.random(n, rnd); 771 return new BigDecimalComplex(r, i); 772 } 773 774 775 /** 776 * Complex number, random. Random rational numbers A and B are generated 777 * using random(n). Then R is the complex number with real part A and 778 * imaginary part B. 779 * @param n such that 0 ≤ A, B ≤ (2<sup>n</sup>-1). 780 * @return R. 781 */ 782 public static BigDecimalComplex CRAND(int n) { 783 return ONE.random(n, random); 784 } 785 786 787 /** 788 * Parse complex number from string. 789 * @param s String. 790 * @return BigDecimalComplex from s. 791 */ 792 public BigDecimalComplex parse(String s) { 793 return new BigDecimalComplex(s); 794 } 795 796 797 /** 798 * Parse complex number from Reader. 799 * @param r Reader. 800 * @return next BigDecimalComplex from r. 801 */ 802 public BigDecimalComplex parse(Reader r) { 803 return parse(StringUtil.nextString(r)); 804 } 805 806 807 /** 808 * Complex number greatest common divisor. 809 * @param S BigDecimalComplex. 810 * @return gcd(this,S). 811 */ 812 public BigDecimalComplex gcd(BigDecimalComplex S) { 813 if (S == null || S.isZERO()) { 814 return this; 815 } 816 if (this.isZERO()) { 817 return S; 818 } 819 return ONE; 820 } 821 822 823 /** 824 * BigDecimalComplex extended greatest common divisor. 825 * @param S BigDecimalComplex. 826 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 827 */ 828 public BigDecimalComplex[] egcd(BigDecimalComplex S) { 829 BigDecimalComplex[] ret = new BigDecimalComplex[3]; 830 ret[0] = null; 831 ret[1] = null; 832 ret[2] = null; 833 if (S == null || S.isZERO()) { 834 ret[0] = this; 835 return ret; 836 } 837 if (this.isZERO()) { 838 ret[0] = S; 839 return ret; 840 } 841 BigDecimalComplex half = fromInteger(2).inverse(); 842 ret[0] = ONE; 843 ret[1] = this.inverse().multiply(half); 844 ret[2] = S.inverse().multiply(half); 845 return ret; 846 } 847 848 849 /** 850 * Returns the number of bits in the representation of this 851 * BigDecimalComplex, including a sign bit. It is equivalent to 852 * {@code re.bitLength() + im.bitLength()}.) 853 * @return number of bits in the representation of this BigDecimalComplex, 854 * including a sign bit. 855 */ 856 public long bitLength() { 857 return re.bitLength() + im.bitLength(); 858 } 859 860}