1 package JSci.maths; 2 3 import java.lang.Double ; 4 5 import JSci.GlobalSettings; 6 import JSci.maths.groups.AbelianGroup; 7 import JSci.maths.fields.*; 8 import JSci.maths.algebras.*; 9 10 16 public final class Complex extends Object implements Field.Member, CStarAlgebra.Member { 17 private static final long serialVersionUID = 6561957920497208796L; 18 19 private double re; 20 private double im; 21 24 private transient boolean isModCached=false; 25 private transient double modCache; 26 private transient boolean isArgCached=false; 27 private transient double argCache; 28 31 public static final Complex I=ComplexField.I; 32 35 public static final Complex ONE=ComplexField.ONE; 36 39 public static final Complex ZERO=ComplexField.ZERO; 40 45 public Complex(final double x,final double y) { 46 re=x; 47 im=y; 48 } 49 54 public Complex(final String s) throws NumberFormatException { 55 final int iPos = s.indexOf('i'); 56 if(iPos == -1) { 57 re = Double.parseDouble(s); 59 im = 0.0; 60 } else { 61 int signPos = indexOf(s, '+', '-', 1); 62 int expPos = indexOf(s, 'E', 'e', 1); 63 if(signPos == expPos+1) 64 signPos = indexOf(s, '+', '-', signPos+1); 65 String imStr; 66 if(signPos == -1) { 67 re=0.0; 68 imStr=s; 69 } else { 70 if(iPos<signPos) { 71 imStr=s.substring(0,signPos); 73 re=Double.parseDouble(s.substring(signPos)); 74 } else { 75 re=Double.parseDouble(s.substring(0,signPos)); 77 imStr=s.substring(signPos); 78 } 79 } 80 if(imStr.endsWith("i")) { 81 im=Double.parseDouble(imStr.substring(0,imStr.length()-1)); 82 } else { 83 char ch = imStr.charAt(0); 84 if(ch == 'i') { 85 im=Double.parseDouble(imStr.substring(1)); 86 } else if((ch == '+' || ch == '-') && imStr.charAt(1) == 'i') { 87 im=Double.parseDouble(imStr.substring(2)); 88 im=(ch == '+' ? im : -im); 89 } else 90 throw new NumberFormatException ("The imaginary unit, 'i', is in an invalid position"); 91 } 92 } 93 } 94 private static int indexOf(String s, char a, char b, final int start) { 95 final int aPos = s.indexOf(a, start); 96 final int bPos = s.indexOf(b, start); 97 return (aPos == -1 ? bPos : aPos); 98 } 99 104 public static Complex polar(final double mod,final double arg) { 105 final Complex z=new Complex(mod*Math.cos(arg),mod*Math.sin(arg)); 106 z.modCache=mod; 107 z.isModCached=true; 108 z.argCache=arg; 109 z.isArgCached=true; 110 return z; 111 } 112 116 public boolean equals(Object obj) { 117 return equals(obj, GlobalSettings.ZERO_TOL); 118 } 119 public boolean equals(Object obj, double tol) { 120 if(obj instanceof Complex) { 121 final Complex z=(Complex)obj; 122 return equals(z.re,z.im,tol); 123 } else 124 return false; 125 } 126 129 public boolean equals(double real,double imag) { 130 return equals(real, imag, GlobalSettings.ZERO_TOL); 131 } 132 public boolean equals(double real, double imag, double tol) { 133 return (mod(re-real, im-imag) <= tol); 134 } 135 138 public String toString() { 139 return toString(re,im); 140 } 141 144 public static String toString(double real, double imag) { 145 final StringBuffer buf = new StringBuffer (); 146 buf.append(real); 147 if(imag>=0.0) 148 buf.append("+"); 149 buf.append(imag); 150 buf.append("i"); 151 return buf.toString(); 152 } 153 156 public int hashCode() { 157 return (int)(Math.exp(mod())); 158 } 159 162 public boolean isZero() { 163 return (mod() <= GlobalSettings.ZERO_TOL); 164 } 165 168 public boolean isNaN() { 169 return (re==Double.NaN) || (im==Double.NaN); 170 } 171 174 public boolean isInfinite() { 175 return (re==Double.POSITIVE_INFINITY) || (re==Double.NEGATIVE_INFINITY) 176 || (im==Double.POSITIVE_INFINITY) || (im==Double.NEGATIVE_INFINITY); 177 } 178 181 public double real() { 182 return re; 183 } 184 187 public double imag() { 188 return im; 189 } 190 193 public double mod() { 194 if(isModCached) 195 return modCache; 196 modCache=mod(re,im); 197 isModCached=true; 198 return modCache; 199 } 200 private static double mod(final double real,final double imag) { 201 final double reAbs=Math.abs(real); 202 final double imAbs=Math.abs(imag); 203 if(reAbs==0.0 && imAbs==0.0) 204 return 0.0; 205 else if(reAbs<imAbs) 206 return imAbs*Math.sqrt(1.0+(real/imag)*(real/imag)); 207 else 208 return reAbs*Math.sqrt(1.0+(imag/real)*(imag/real)); 209 } 210 213 public double modSqr() { 214 return re*re+im*im; 215 } 216 219 public double arg() { 220 if(isArgCached) 221 return argCache; 222 argCache=arg(re,im); 223 isArgCached=true; 224 return argCache; 225 } 226 private static double arg(final double real,final double imag) { 227 return Math.atan2(imag,real); 228 } 229 232 public double norm() { 233 return mod(); 234 } 235 public Object getSet() { 236 return ComplexField.getInstance(); 237 } 238 239 243 246 public AbelianGroup.Member negate() { 247 return new Complex(-re,-im); 248 } 249 252 public Field.Member inverse() { 253 double denominator,real,imag; 254 if(Math.abs(re)<Math.abs(im)) { 255 real=re/im; 256 imag=-1.0; 257 denominator=re*real+im; 258 } else { 259 real=1.0; 260 imag=-im/re; 261 denominator=re-im*imag; 262 } 263 return new Complex(real/denominator,imag/denominator); 264 } 265 268 public CStarAlgebra.Member involution() { 269 return conjugate(); 270 } 271 274 public Complex conjugate() { 275 return new Complex(re,-im); 276 } 277 278 280 283 public AbelianGroup.Member add(final AbelianGroup.Member x) { 284 if(x instanceof Complex) 285 return add((Complex)x); 286 else if(x instanceof MathDouble) 287 return addReal(((MathDouble)x).value()); 288 else if(x instanceof MathInteger) 289 return addReal(((MathInteger)x).value()); 290 else 291 throw new IllegalArgumentException ("Member class not recognised by this method."); 292 } 293 297 public Complex add(final Complex z) { 298 return new Complex(re+z.re,im+z.im); 299 } 300 304 public Complex addReal(final double real) { 305 return new Complex(re+real,im); 306 } 307 311 public Complex addImag(final double imag) { 312 return new Complex(re,im+imag); 313 } 314 315 317 320 public AbelianGroup.Member subtract(final AbelianGroup.Member x) { 321 if(x instanceof Complex) 322 return subtract((Complex)x); 323 else if(x instanceof MathDouble) 324 return subtractReal(((MathDouble)x).value()); 325 else if(x instanceof MathInteger) 326 return subtractReal(((MathInteger)x).value()); 327 else 328 throw new IllegalArgumentException ("Member class not recognised by this method."); 329 } 330 334 public Complex subtract(final Complex z) { 335 return new Complex(re-z.re,im-z.im); 336 } 337 341 public Complex subtractReal(final double real) { 342 return new Complex(re-real,im); 343 } 344 348 public Complex subtractImag(final double imag) { 349 return new Complex(re,im-imag); 350 } 351 352 354 357 public Module.Member scalarMultiply(final Ring.Member x) { 358 return (Complex)multiply(x); 359 } 360 363 public Ring.Member multiply(final Ring.Member x) { 364 if(x instanceof Complex) 365 return multiply((Complex)x); 366 else if(x instanceof MathDouble) 367 return multiply(((MathDouble)x).value()); 368 else if(x instanceof MathInteger) 369 return multiply(((MathInteger)x).value()); 370 else 371 throw new IllegalArgumentException ("Member class not recognised by this method."); 372 } 373 377 public Complex multiply(final Complex z) { 378 return new Complex(re*z.re-im*z.im,re*z.im+im*z.re); 379 } 380 384 public Complex multiply(final double x) { 385 return new Complex(x*re,x*im); 386 } 387 388 390 393 public VectorSpace.Member scalarDivide(final Field.Member x) { 394 return (Complex)divide(x); 395 } 396 399 public Field.Member divide(final Field.Member x) { 400 if(x instanceof Complex) 401 return divide((Complex)x); 402 else if(x instanceof MathDouble) 403 return divide(((MathDouble)x).value()); 404 else 405 throw new IllegalArgumentException ("Member class not recognised by this method."); 406 } 407 412 public Complex divide(final Complex z) { 413 final double denominator,real,imag,a; 414 if(Math.abs(z.re)<Math.abs(z.im)) { 415 a=z.re/z.im; 416 denominator=z.re*a+z.im; 417 real=re*a+im; 418 imag=im*a-re; 419 } else { 420 a=z.im/z.re; 421 denominator=z.re+z.im*a; 422 real=re+im*a; 423 imag=im-re*a; 424 } 425 return new Complex(real/denominator,imag/denominator); 426 } 427 432 public Complex divide(final double x) { 433 return new Complex(re/x,im/x); 434 } 435 436 438 442 public Complex pow(final Complex z) { 443 final double thisMod=mod(); 444 final double thisArg=arg(); 445 final double r=Math.pow(thisMod,z.re)/Math.exp(thisArg*z.im); 446 final double a=thisArg*z.re+Math.log(thisMod)*z.im; 447 return polar(r,a); 448 } 449 453 public Complex pow(final double x) { 454 return polar(Math.pow(mod(),x),arg()*x); 455 } 456 459 public Complex sqr() { 460 return new Complex(re*re-im*im,2.0*re*im); 461 } 462 465 public Complex sqrt() { 466 return polar(Math.sqrt(mod()),arg()/2.0); 467 } 468 private static Complex sqrt(final double real,final double imag) { 469 return polar(Math.sqrt(mod(real,imag)),arg(real,imag)/2.0); 470 } 471 472 476 478 483 public static Complex exp(final Complex z) { 484 return new Complex( 485 Math.exp(z.re)*Math.cos(z.im), 486 Math.exp(z.re)*Math.sin(z.im) 487 ); 488 } 489 490 492 497 public static Complex log(final Complex z) { 498 return new Complex(Math.log(z.mod()),z.arg()); 499 } 500 private final static Complex log(final double real,final double imag) { 501 return new Complex(Math.log(mod(real,imag)),arg(real,imag)); 502 } 503 private final static Complex log_2(final double real,final double imag) { 504 return new Complex(Math.log(mod(real,imag))/2.0,arg(real,imag)/2.0); 505 } 506 private final static Complex log_2I(final double real,final double imag) { 507 return new Complex(arg(real,imag)/2.0,-Math.log(mod(real,imag))/2.0); 508 } 509 private final static Complex log_2IplusPI_2(final double real,final double imag) { 510 return new Complex((arg(real,imag)+Math.PI)/2.0,-Math.log(mod(real,imag))/2.0); 511 } 512 513 515 519 public static Complex sin(final Complex z) { 520 return new Complex( 521 Math.sin(z.re)*ExtraMath.cosh(z.im), 522 Math.cos(z.re)*ExtraMath.sinh(z.im) 523 ); 524 } 525 526 528 532 public static Complex cos(final Complex z) { 533 return new Complex( 534 Math.cos(z.re)*ExtraMath.cosh(z.im), 535 -Math.sin(z.re)*ExtraMath.sinh(z.im) 536 ); 537 } 538 539 541 545 public static Complex tan(final Complex z) { 546 final double sinRe=Math.sin(z.re); 547 final double cosRe=Math.cos(z.re); 548 final double sinhIm=ExtraMath.sinh(z.im); 549 final double coshIm=ExtraMath.cosh(z.im); 550 final double denom=cosRe*cosRe*coshIm*coshIm+sinRe*sinRe*sinhIm*sinhIm; 551 return new Complex(sinRe*cosRe/denom,sinhIm*coshIm/denom); 552 } 553 554 556 560 public static Complex sinh(final Complex z) { 561 return new Complex( 562 ExtraMath.sinh(z.re)*Math.cos(z.im), 563 ExtraMath.cosh(z.re)*Math.sin(z.im) 564 ); 565 } 566 567 569 573 public static Complex cosh(final Complex z) { 574 return new Complex( 575 ExtraMath.cosh(z.re)*Math.cos(z.im), 576 ExtraMath.sinh(z.re)*Math.sin(z.im) 577 ); 578 } 579 580 582 586 public static Complex tanh(final Complex z) { 587 final double sinhRe=ExtraMath.sinh(z.re); 588 final double coshRe=ExtraMath.cosh(z.re); 589 final double sinIm=Math.sin(z.im); 590 final double cosIm=Math.cos(z.im); 591 final double denom=coshRe*coshRe*cosIm*cosIm+sinhRe*sinhRe*sinIm*sinIm; 592 return new Complex(sinhRe*coshRe/denom,sinIm*cosIm/denom); 593 } 594 595 597 603 public static Complex asin(final Complex z) { 604 if(z.equals(ONE)) 605 return ComplexField.PI_2; 606 else if(z.equals(ComplexField.MINUS_ONE)) 607 return ComplexField.MINUS_PI_2; 608 else { 609 final Complex root=sqrt(1.0-z.re*z.re+z.im*z.im,-2.0*z.re*z.im); 611 final double zModSqr=z.re*z.re+z.im*z.im; 612 final double rootModSqr=root.re*root.re+root.im*root.im; 613 final double denom=rootModSqr+zModSqr+2.0*(root.re*z.im-root.im*z.re); 614 return log_2I((rootModSqr-zModSqr)/denom,2.0*(root.re*z.re+root.im*z.im)/denom); 615 } 616 } 617 618 620 626 public static Complex acos(final Complex z) { 627 if(z.equals(ONE)) 628 return ZERO; 629 else if(z.equals(ComplexField.MINUS_ONE)) 630 return ComplexField.PI; 631 else { 632 final Complex root=sqrt(1.0-z.re*z.re+z.im*z.im,-2.0*z.re*z.im); 634 final double zModSqr=z.re*z.re+z.im*z.im; 635 final double rootModSqr=root.re*root.re+root.im*root.im; 636 final double denom=rootModSqr+zModSqr+2.0*(root.im*z.re-root.re*z.im); 637 return log_2IplusPI_2((rootModSqr-zModSqr)/denom,-2.0*(root.re*z.re+root.im*z.im)/denom); 638 } 639 } 640 641 643 649 public static Complex atan(final Complex z) { 650 final double modSqr=z.modSqr(); 652 final double denom=1.0+modSqr+2.0*z.im; 653 return log_2I((1.0-modSqr)/denom,2.0*z.re/denom); 654 } 655 656 658 664 public static Complex asinh(final Complex z) { 665 if(z.equals(I)) 666 return ComplexField.PI_2_I; 667 else if(z.equals(ComplexField.MINUS_I)) 668 return ComplexField.MINUS_PI_2_I; 669 else { 670 final Complex root=sqrt(z.re*z.re-z.im*z.im+1.0,2.0*z.re*z.im); 672 return log(z.re+root.re,z.im+root.im); 673 } 674 } 675 676 678 684 public static Complex acosh(final Complex z) { 685 if(z.equals(ONE)) 686 return ZERO; 687 else if(z.equals(ComplexField.MINUS_ONE)) 688 return ComplexField.PI_I; 689 else { 690 final Complex root=sqrt(z.re*z.re-z.im*z.im-1.0,2.0*z.re*z.im); 692 return log(z.re+root.re,z.im+root.im); 693 } 694 } 695 696 698 704 public static Complex atanh(final Complex z) { 705 final double modSqr=z.modSqr(); 707 final double denom=1.0+modSqr-2.0*z.re; 708 return log_2((1.0-modSqr)/denom,2.0*z.im/denom); 709 } 710 } 711 | Popular Tags |