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