package com.nr; /* File: Complex.java * -- A Java class for performing complex * number arithmetic to double precision. * * Copyright (c) 1997 - 2001, Alexander Anderson. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ import java.io.Serializable; /** *

* @version * 1.0.1
* * Last change: ALM 23 Mar 2001 8:56 pm * *

* A Java class for performing complex number arithmetic to double * precision. * *

*

* * Make yours a Java enabled browser and OS! * *

* This applet has been adapted
from a Vector * Visualization applet by Vladimir Sorokin. *

*
* *

* @author Sandy Anderson * @author Priyantha Jayanetti *

* *

*  Copyright (c) 1997 - 2001, Alexander Anderson.
*
*  This  program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published  by
*  the Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be  useful,  but
*  WITHOUT   ANY   WARRANTY;   without  even  the  implied  warranty  of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE.   See  the  GNU
*  General Public License for more details.
*
*  You  should  have  received  a copy of the GNU General Public License
*  along  with  this  program;  if  not,  write  to  the  Free  Software
*  Foundation,  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
*  USA.
* 
* *

* The latest version of this Complex class is available from * the Netlib Repository. *

* Here's an example of the style the class permits:
* *

*         import  ORG.netlib.math.complex.Complex;
* public class Test {
* public boolean isInMandelbrot (Complex c, int maxIter) { * Complex z= new Complex(0, 0);
* for (int i= 0; i < maxIter; i++) { * z= z.mul(z).add(c); * if (z.abs() > 2) return false; * }
* return true; * }
* } *
* *

*

This class was developed by * Sandy Anderson at the * School of Electronic Engineering, * Middlesex University, UK, and * Priyantha Jayanetti at The Power Systems Program, the * University of Maine, USA. *
*

*

And many, many thanks to Mr. Daniel * Hirsch, for his constant advice on the mathematics, his exasperating * ability to uncover bugs blindfold, and for his persistent badgering over * the exact wording of this documentation. *
*

*

For instance, he starts to growl like a badger if you say "infinite set".

*
"Grrr...What's that mean? Countably infinite?"

*
You think for a while.

*
"Grrr..."

*
"Yes."

*
"Ah! Then you mean infinitely many."

*

**/ public class Complex implements Cloneable, Serializable { private static final long serialVersionUID = 1L; public static final String VERSION = "1.0.1"; public static final String DATE = "Fri 23-Mar-2001 8:56 pm"; public static final String AUTHOR = "sandy@almide.demon.co.uk"; public static final String REMARK = "Class available from " + "http://www.netlib.org/"; /** * Switches on debugging information. *

**/ // protected static boolean debug = false; /** * Whilst debugging: the nesting level when tracing method calls. *

**/ // private static int trace_nesting = 0; /** * Twice PI * radians is the same thing as 360 degrees. *

**/ protected static final double TWO_PI = 2.0 * Math.PI; /** * A constant representing i, the famous square root of * -1. *

* The other square root of -1 is - i. *

**/ public static final Complex I = new Complex(0.0, 1.0); // private static long objectCount; // !!! private double re; private double im; //---------------------------------// // CONSTRUCTORS // //---------------------------------// /** * Constructs a Complex representing the number zero. * *

**/ public Complex () { this(0.0, 0.0); }//end Complex() /** * Constructs a Complex representing a real number. * *

* @param re The real number *

* @see Complex#real(double) **/ public Complex (double re) { this(re, 0.0); }//end Complex(double) /** * Constructs a separate new Complex from an existing * Complex. * *

* @param z A Complex number *

**/ public Complex (Complex z) { this(z.re, z.im); }//end Complex(Complex) /** * Constructs a Complex from real and imaginary parts. * *

* Note:

*

* @param re Real part * @param im Imaginary part *

* @see Complex#cart(double, double) * @see Complex#polar(double, double) **/ public Complex (double re, double im) { this.re = re; this.im = im; // if (debug) System.out.println(indent(trace_nesting) + "new Complex, #" + (++objectCount));// !!! }//end Complex(double,double) //---------------------------------// // DEBUG // //---------------------------------// /* // BETA Debugging methods... private static void entering (String what) { System.out.print(indent(trace_nesting) + what); trace_nesting++; }//end entering(String) private static void enter (String what, double param1, double param2) { entering(what); System.out.println("(" + param1 + ", " + param2 + ") "); }//end enter(String,double,double) private static void enter (String what, double param) { entering(what); System.out.println("(" + param + ") "); }//end enter(String,double) private static void enter (String what, Complex z) { entering(what); System.out.println("(" + z + ") "); }//end enter(String,Complex) private static void enter (String what, Complex z1, Complex z2) { entering(what); System.out.println("(" + z1 + ", " + z2 + ") "); }//end enter(String,Complex,Complex) private static void enter (String what, Complex z, double x) { entering(what); System.out.println("(" + z + ", " + x + ") "); }//end enter(String,Complex,double) private static void enter (String what, Complex z, double x, double y) { entering(what); System.out.println("(" + z + ", " + cart(x, y) + ") "); }//end enter(String,Complex,double) private static void enter (String what, Complex z1, Complex z2, double x) { entering(what); System.out.println("(" + z1 + ", " + z2 + ", " + x + ") "); }//end enter(String,Complex,Complex,double) private static void leaving (String what) { trace_nesting--; System.out.print(indent(trace_nesting) + "is "); }//end leaving(String) private static void leave (String what, boolean result) { leaving(what); System.out.println(result); }//end leave(String,boolean) private static void leave (String what, double result) { leaving(what); System.out.println(result); }//end leave(String,double) private static void leave (String what, Complex result) { leaving(what); System.out.println(result); }//end leave(String,Complex) private static String indent (int nesting) { StringBuffer indention = new StringBuffer(""); for (int i = 0; i < nesting; i++) { indention.append(" "); }//endfor return indention.toString(); }//end indent(int) */ /** * Useful for checking up on the exact version. * *

**/ public static void main (String[] args) { System.out.println(); System.out.println("Module : " + Complex.class.getName()); System.out.println("Version: " + Complex.VERSION); System.out.println("Date : " + Complex.DATE); System.out.println("Author : " + Complex.AUTHOR); System.out.println("Remark : " + Complex.REMARK); System.out.println(); System.out.println("Hint: use TestComplex to test the class."); System.out.println(); }//end main(String[]) //---------------------------------// // STATIC // //---------------------------------// /** * Returns a Complex representing a real number. * *

* @param real The real number *

* @return Complex representation of the real *

* @see Complex#re() * @see Complex#cart(double, double) **/ public static Complex real (double real) { return new Complex(real, 0.0); }//end real(double) /** * Returns a Complex from real and imaginary parts. * *

* @param re Real part * @param im Imaginary part *

* @return Complex from Cartesian coordinates *

* @see Complex#re() * @see Complex#im() * @see Complex#polar(double, double) * @see Complex#toString() **/ public static Complex cart (double re, double im) { return new Complex(re, im); }//end cart(double,double) /** * Returns a Complex from a size and direction. * *

* @param r Size * @param theta Direction (in radians) *

* @return Complex from Polar coordinates *

* @see Complex#abs() * @see Complex#arg() * @see Complex#cart(double, double) **/ public static Complex polar (double r, double theta) { if (r < 0.0) { theta += Math.PI; r = -r; }//endif theta = theta % TWO_PI; return cart(r * Math.cos(theta), r * Math.sin(theta)); }//end polar(double,double) /** * Returns the Complex base raised to the power of the exponent. * *

* @param base The base "to raise" * @param exponent The exponent "by which to raise" *

* @return base "raised to the power of" exponent *

* @see Complex#pow(double, Complex) **/ public static Complex pow (Complex base, double exponent) { // return base.log().scale(exponent).exp(); double re = exponent * Math.log(base.abs()); double im = exponent * base.arg(); double scalar = Math.exp(re); return cart( scalar * Math.cos(im), scalar * Math.sin(im) ); }//end pow(Complex,double) /** * Returns the base raised to the power of the Complex exponent. * *

* @param base The base "to raise" * @param exponent The exponent "by which to raise" *

* @return base "raised to the power of" exponent *

* @see Complex#pow(Complex, Complex) * @see Complex#exp() **/ public static Complex pow (double base, Complex exponent) { // return real(base).log().mul(exponent).exp(); double re = Math.log(Math.abs(base)); double im = Math.atan2(0.0, base); double re2 = (re*exponent.re) - (im*exponent.im); double im2 = (re*exponent.im) + (im*exponent.re); double scalar = Math.exp(re2); return cart( scalar * Math.cos(im2), scalar * Math.sin(im2) ); }//end pow(double,Complex) /** * Returns the Complex base raised to the power of the Complex exponent. * *

* @param base The base "to raise" * @param exponent The exponent "by which to raise" *

* @return base "raised to the power of" exponent *

* @see Complex#pow(Complex, double) * @see Complex#pow(Complex) **/ public static Complex pow (Complex base, Complex exponent) { // return base.log().mul(exponent).exp(); double re = Math.log(base.abs()); double im = base.arg(); double re2 = (re*exponent.re) - (im*exponent.im); double im2 = (re*exponent.im) + (im*exponent.re); double scalar = Math.exp(re2); return cart( scalar * Math.cos(im2), scalar * Math.sin(im2) ); }//end pow(Complex,Complex) //---------------------------------// // PUBLIC // //---------------------------------// /** * Returns true if either the real or imaginary component of this * Complex is an infinite value. * *

* @return true if either component of the Complex object is infinite; false, otherwise. *

**/ public boolean isInfinite () { return ( Double.isInfinite(re) || Double.isInfinite(im) ); }//end isInfinite() /** * Returns true if either the real or imaginary component of this * Complex is a Not-a-Number (NaN) value. * *

* @return true if either component of the Complex object is NaN; false, otherwise. *

**/ public boolean isNaN () { return ( Double.isNaN(re) || Double.isNaN(im) ); }//end isNaN() /** * Decides if two Complex numbers are "sufficiently" alike to be * considered equal. * *

* tolerance is the maximum magnitude of the difference between * them before they are considered not equal. *

* Checking for equality between two real numbers on computer hardware is a * tricky business. Try *

*

    System.out.println((1.0/3.0 * 3.0));
*

* and you'll see the nature of the problem! It's just as tricky with * Complex numbers. *

* Realize that because of these complications, it's possible to find that * the magnitude of one Complex number a is less than * another, b, and yet a.equals(b, myTolerance) returns * true. Be aware! *

* @param z The Complex to compare with * @param tolerance The tolerance for equality *

* @return true, or false *

**/ public boolean equals (Complex z, double tolerance) { // still true when _equal_ to tolerance? ... return abs(re - z.re, im - z.im) <= Math.abs(tolerance); // ...and tolerance is always non-negative }//end equals(Complex,double) /** * Test for the equality of two Complex objects. * If both the real and imaginary parts of two complex numbers * are exactly the same, and neither is {@code Double.NaN}, the two * Complex objects are considered to be equal. * All {@code NaN} values are considered to be equal - i.e, if either * (or both) real and imaginary parts of the complex number are equal * to {@code Double.NaN}, the complex number is equal to * {@code NaN}. * * @param other Object to test for equality to this * @return true if two Complex objects are equal, false if object is * {@code null}, not an instance of Complex, or not equal to this Complex * instance. */ @Override public boolean equals(Object other) { if (this == other) { return true; } if (other instanceof Complex){ Complex c = (Complex)other; if (c.isNaN()) { return c.isNaN(); } else { return (re == c.re) && (im == c.im); } } return false; } /** * Returns a hashcode for this complex number. */ public int hashCode() { return (int)(Math.exp(mod())); } /** * Overrides the {@link java.lang.Cloneable Cloneable} interface. * *

* Standard override; no change in semantics. *

* The following Java code example illustrates how to clone, or copy, a * Complex number: *

*

    *     Complex z1 =  new Complex(0, 1);
    *     Complex z2 =  (Complex) z1.clone();
    * 
*

* @return An Object that is a copy of this Complex object. *

* @see java.lang.Cloneable * @see java.lang.Object#clone() **/ public Object clone () { try { return (Object)(super.clone()); } catch (java.lang.CloneNotSupportedException e) { return null; // This cannot happen: there would have to be a serious internal error in the Java runtime if this codepath happens! }//endtry }//end clone() /** * Extracts the real part of a Complex as a double. * *

*

    *     re(x + i*y)  =  x
    * 
*

* @return The real part *

* @see Complex#im() * @see Complex#cart(double, double) * @see Complex#real(double) **/ public double re () { return re; }//end re() /** * Extracts the imaginary part of a Complex as a double. * *

*

    *     im(x + i*y)  =  y
    * 
*

* @return The imaginary part *

* @see Complex#re() * @see Complex#cart(double, double) **/ public double im () { return im; }//end im() /** * Returns the square of the "length" of a Complex number. * *

*

    *     norm(x + i*y)  =  x*x + y*y
    * 
*

* Always non-negative. *

* @return The norm *

* @see Complex#abs() **/ public double norm () { return (re*re) + (im*im); }//end norm() /** * Returns the magnitude of a Complex number. * *

*

    *     abs(z)  =  sqrt(norm(z))
    * 
*

* In other words, it's Pythagorean distance from the origin * (0 + 0i, or zero). *

* The magnitude is also referred to as the "modulus" or "length". *

* Always non-negative. *

* @return The magnitude (or "length") *

* @see Complex#arg() * @see Complex#polar(double, double) * @see Complex#norm() **/ public double abs () { return abs(re, im); }//end abs() public double mod () { return abs(re, im); }//end mod() static private double abs (double x, double y) { // abs(z) = sqrt(norm(z)) // Adapted from // "Numerical Recipes in Fortran 77: The Art of Scientific Computing" // (ISBN 0-521-43064-X) double absX = Math.abs(x); double absY = Math.abs(y); if (absX == 0.0 && absY == 0.0) { // !!! Numerical Recipes, mmm? return 0.0; } else if (absX >= absY) { double d = y / x; return absX*Math.sqrt(1.0 + d*d); } else { double d = x / y; return absY*Math.sqrt(1.0 + d*d); }//endif }//end abs() /** * Returns the principal angle of a Complex number, in * radians, measured counter-clockwise from the real axis. (Think of the * reals as the x-axis, and the imaginaries as the y-axis.) * *

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of arg(z), the others are of * the form: *

*

    *     A + 2*k*PI
    * 
*

* where k is any integer. *

* arg() always returns a double between * -PI and +PI. *

* Note:

*

* Domain Restrictions:

*

* @return Principal angle (in radians) *

* @see Complex#abs() * @see Complex#polar(double, double) **/ public double arg () { return Math.atan2(im, re); }//end arg() /** * Returns the "negative" of a Complex number. * *

*

    *     neg(a + i*b)  =  -a - i*b
    * 
*

* The magnitude of the negative is the same, but the angle is flipped * through PI (or 180 degrees). *

* @return Negative of the Complex *

* @see Complex#scale(double) **/ public Complex neg () { return this.scale(-1.0); }//end neg() /** * Returns the Complex "conjugate". * *

*

    *     conj(x + i*y)  =  x - i*y
    * 
*

* The conjugate appears "flipped" across the real axis. *

* @return The Complex conjugate *

**/ public Complex conj () { return cart(re, -im); }//end conj() static private void inv (Complex z) { double zRe, zIm; double scalar; if (Math.abs(z.re) >= Math.abs(z.im)) { scalar = 1.0 / ( z.re + z.im*(z.im/z.re) ); zRe = scalar; zIm = scalar * (- z.im/z.re); } else { scalar = 1.0 / ( z.re*(z.re/z.im) + z.im ); zRe = scalar * ( z.re/z.im); zIm = - scalar; }//endif z.re = zRe; z.im = zIm; }//end inv(Complex) /** * Returns the Complex scaled by a real number. * *

*

    *     scale((x + i*y), s)  =  (x*s + i*y*s)
    * 
*

* Scaling by the real number 2.0, doubles the magnitude, but leaves * the arg() unchanged. Scaling by -1.0 keeps the magnitude * the same, but flips the arg() by PI (180 degrees). *

* @param scalar A real number scale factor *

* @return Complex scaled by a real number *

* @see Complex#mul(Complex) * @see Complex#div(Complex) * @see Complex#neg() **/ public Complex scale (double scalar) { return cart(scalar*re, scalar*im); }//end scale(double) public Complex mul (double scalar) { return cart(scalar*re, scalar*im); }//end scale(double) /** * To perform z1 + z2, you write z1.add(z2) . * *

*

    *     (a + i*b) + (c + i*d)  =  ((a+c) + i*(b+d))
    * 
*

**/ public Complex add (Complex z) { return cart(re + z.re, im + z.im); }//end add(Complex) /** * To perform z1 - z2, you write z1.sub(z2) . * *

*

    *     (a + i*b) - (c + i*d)  =  ((a-c) + i*(b-d))
    * 
*

**/ public Complex sub (Complex z) { return cart(re - z.re, im - z.im); }//end sub(Complex) /** * To perform z1 * z2, you write z1.mul(z2) . * *

*

    *     (a + i*b) * (c + i*d)  =  ( (a*c) - (b*d) + i*((a*d) + (b*c)) )
    * 
*

* @see Complex#scale(double) **/ public Complex mul (Complex z) { return cart( (re*z.re) - (im*z.im), (re*z.im) + (im*z.re) ); // return cart( (re*z.re) - (im*z.im), (re + im)*(z.re + z.im) - re*z.re - im*z.im); }//end mul(Complex) /** * To perform z1 / z2, you write z1.div(z2) . * *

*

    *     (a + i*b) / (c + i*d)  =  ( (a*c) + (b*d) + i*((b*c) - (a*d)) ) / norm(c + i*d)
    * 
*

* Take care not to divide by zero! *

* Note:

*

* Domain Restrictions:

*

* @see Complex#scale(double) **/ public Complex div (Complex z) { Complex result = new Complex(this); div(result, z.re, z.im); return result; }//end div(Complex) public Complex div(final double x) { return new Complex(re/x,im/x); } static private void div (Complex z, double x, double y) { // Adapted from // "Numerical Recipes in Fortran 77: The Art of Scientific Computing" // (ISBN 0-521-43064-X) double zRe, zIm; double scalar; if (Math.abs(x) >= Math.abs(y)) { scalar = 1.0 / ( x + y*(y/x) ); zRe = scalar * (z.re + z.im*(y/x)); zIm = scalar * (z.im - z.re*(y/x)); } else { scalar = 1.0 / ( x*(x/y) + y ); zRe = scalar * (z.re*(x/y) + z.im); zIm = scalar * (z.im*(x/y) - z.re); }//endif z.re = zRe; z.im = zIm; }//end div(Complex,double,double) /** * Returns a Complex representing one of the two square roots. * *

*

    *     sqrt(z)  =  sqrt(abs(z)) * ( cos(arg(z)/2) + i * sin(arg(z)/2) )
    * 
*

* For any complex number z, sqrt(z) will return the * complex root whose arg is arg(z)/2. *

* Note:

*

* @return The square root whose arg is arg(z)/2. *

* @see Complex#pow(Complex, double) **/ public Complex sqrt () { Complex result = new Complex(this); sqrt(result); return result; }//end sqrt() static private void sqrt (Complex z) { // with thanks to Jim Shapiro // adapted from "Numerical Recipies in C" (ISBN 0-521-43108-5) // by William H. Press et al double mag = z.abs(); if (mag > 0.0) { if (z.re > 0.0) { double temp = Math.sqrt(0.5 * (mag + z.re)); z.re = temp; z.im = 0.5 * z.im / temp; } else { double temp = Math.sqrt(0.5 * (mag - z.re)); if (z.im < 0.0) { temp = -temp; }//endif z.re = 0.5 * z.im / temp; z.im = temp; }//endif } else { z.re = 0.0; z.im = 0.0; }//endif }//end sqrt(Complex) /** * Returns this Complex raised to the power of a Complex exponent. * *

* @param exponent The exponent "by which to raise" *

* @return this Complex "raised to the power of" the exponent *

* @see Complex#pow(Complex, Complex) **/ public Complex pow (Complex exponent) { return Complex.pow(this, exponent); }//end pow(Complex) /** * Returns the number e "raised to" a Complex power. * *

*

    *     exp(x + i*y)  =  exp(x) * ( cos(y) + i * sin(y) )
    * 
*

* Note:

* *

* @return e "raised to the power of" this Complex *

* @see Complex#log() * @see Complex#pow(double, Complex) **/ public Complex exp () { double scalar = Math.exp(re); // e^ix = cis x return cart( scalar * Math.cos(im), scalar * Math.sin(im) ); }//end exp() /** * Returns the principal natural logarithm of a Complex * number. * *

*

    *     log(z)  =  log(abs(z)) + i * arg(z)
    * 
*

* There are infinitely many solutions, besides the principal solution. * If L is the principal solution of log(z), the others are of * the form: *

*

    *     L + (2*k*PI)*i
    * 
*

* where k is any integer. *

* @return Principal Complex natural logarithm *

* @see Complex#exp() **/ public Complex log () { return cart( Math.log(this.abs()), this.arg() ); // principal value }//end log() /** * Returns the principal logarithm (base 10) of a * Complex number. * *

*

    *     log10(z)  =  log(z) / log(10)
    * 
*

* There are infinitely many solutions, besides the principal solution. * If L is the principal solution of log10(z), the others are * of the form: *

*

    *     L + (2*k*PI)*i
    * 
*

* where k is any integer. *

* @return Principal Complex logarithm (base 10) *

* @see Complex#exp() * @see Complex#log() **/ /* DEPRECATED !!! public Complex log10 () { Complex result; // if (debug) enter("log10", this); double scalar = 1.0/Math.log(10.0); // result = this.log().scale(scalar); result = cart( scalar * Math.log(this.abs()), scalar * this.arg() ); // if (debug) leave("log10", result); return result; }//end log10() /* */ /** * Returns the sine of a Complex number. * *

*

    *     sin(z)  =  ( exp(i*z) - exp(-i*z) ) / (2*i)
    * 
*

* @return The Complex sine *

* @see Complex#asin() * @see Complex#sinh() * @see Complex#cosec() * @see Complex#cos() * @see Complex#tan() **/ public Complex sin () { Complex result; // sin(z) = ( exp(i*z) - exp(-i*z) ) / (2*i) double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _1: _1.sub(_2) ... _re1 = _re1 - _re2; // !!! _im1 = _im1 - _im2; // !!! // result: _1.div(2*i) ... result = cart( 0.5*_im1, -0.5*_re1 ); // ... result = cart(_re1, _im1); // div(result, 0.0, 2.0); return result; }//end sin() /** * Returns the cosine of a Complex number. * *

*

    *     cos(z)  =  ( exp(i*z) + exp(-i*z) ) / 2
    * 
*

* @return The Complex cosine *

* @see Complex#acos() * @see Complex#cosh() * @see Complex#sec() * @see Complex#sin() * @see Complex#tan() **/ public Complex cos () { Complex result; // cos(z) = ( exp(i*z) + exp(-i*z) ) / 2 double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _1: _1.add(_2) ... _re1 = _re1 + _re2; // !!! _im1 = _im1 + _im2; // !!! // result: _1.scale(0.5) ... result = cart( 0.5 * _re1, 0.5 * _im1 ); return result; }//end cos() /** * Returns the tangent of a Complex number. * *

*

    *     tan(z)  =  sin(z) / cos(z)
    * 
*

* Domain Restrictions:

*

* @return The Complex tangent *

* @see Complex#atan() * @see Complex#tanh() * @see Complex#cot() * @see Complex#sin() * @see Complex#cos() **/ public Complex tan () { Complex result; // tan(z) = sin(z) / cos(z) double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; double _re3, _im3; double cs_re, cs_im; // sin() ... // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _3: _1.sub(_2) ... _re3 = _re1 - _re2; _im3 = _im1 - _im2; // result: _3.div(2*i) ... result = cart( 0.5*_im3, -0.5*_re3 ); // result = cart(_re3, _im3); // div(result, 0.0, 2.0); // cos() ... // _3: _1.add(_2) ... _re3 = _re1 + _re2; _im3 = _im1 + _im2; // cs: _3.scale(0.5) ... cs_re = 0.5 * _re3; cs_im = 0.5 * _im3; // result: result.div(cs) ... div(result, cs_re, cs_im); return result; }//end tan() /** * Returns the cosecant of a Complex number. * *

*

    *     cosec(z)  =  1 / sin(z)
    * 
*

* Domain Restrictions:

*

* @return The Complex cosecant *

* @see Complex#sin() * @see Complex#sec() * @see Complex#cot() **/ public Complex cosec () { Complex result; // cosec(z) = 1 / sin(z) double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _1: _1.sub(_2) ... _re1 = _re1 - _re2; // !!! _im1 = _im1 - _im2; // !!! // _result: _1.div(2*i) ... result = cart( 0.5*_im1, -0.5*_re1 ); // result = cart(_re1, _im1); // div(result, 0.0, 2.0); // result: one.div(_result) ... inv(result); return result; }//end cosec() /** * Returns the secant of a Complex number. * *

*

    *     sec(z)  =  1 / cos(z)
    * 
*

* Domain Restrictions:

*

* @return The Complex secant *

* @see Complex#cos() * @see Complex#cosec() * @see Complex#cot() **/ public Complex sec () { Complex result; // sec(z) = 1 / cos(z) double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _1: _1.add(_2) ... _re1 = _re1 + _re2; _im1 = _im1 + _im2; // result: _1.scale(0.5) ... result = cart(0.5*_re1, 0.5*_im1); // result: one.div(result) ... inv(result); return result; }//end sec() /** * Returns the cotangent of a Complex number. * *

*

    *     cot(z)  =  1 / tan(z)
    * 
*

* Domain Restrictions:

*

* @return The Complex cotangent *

* @see Complex#tan() * @see Complex#cosec() * @see Complex#sec() **/ public Complex cot () { Complex result; // cot(z) = 1 / tan(z) = cos(z) / sin(z) double scalar; double iz_re, iz_im; double _re1, _im1; double _re2, _im2; double _re3, _im3; double sn_re, sn_im; // cos() ... // iz: i.mul(z) ... iz_re = -im; iz_im = re; // _1: iz.exp() ... scalar = Math.exp(iz_re); _re1 = scalar * Math.cos(iz_im); _im1 = scalar * Math.sin(iz_im); // _2: iz.neg().exp() ... scalar = Math.exp(-iz_re); _re2 = scalar * Math.cos(-iz_im); _im2 = scalar * Math.sin(-iz_im); // _3: _1.add(_2) ... _re3 = _re1 + _re2; _im3 = _im1 + _im2; // result: _3.scale(0.5) ... result = cart( 0.5*_re3, 0.5*_im3 ); // sin() ... // _3: _1.sub(_2) ... _re3 = _re1 - _re2; _im3 = _im1 - _im2; // sn: _3.div(2*i) ... sn_re = 0.5 * _im3; // !!! sn_im = - 0.5 * _re3; // !!! // result: result.div(sn) ... div(result, sn_re, sn_im); return result; }//end cot() /** * Returns the hyperbolic sine of a Complex number. * *

*

    *     sinh(z)  =  ( exp(z) - exp(-z) ) / 2
    * 
*

* @return The Complex hyperbolic sine *

* @see Complex#sin() * @see Complex#asinh() **/ public Complex sinh () { Complex result; // sinh(z) = ( exp(z) - exp(-z) ) / 2 double scalar; double _re1, _im1; double _re2, _im2; // _1: z.exp() ... scalar = Math.exp(re); _re1 = scalar * Math.cos(im); _im1 = scalar * Math.sin(im); // _2: z.neg().exp() ... scalar = Math.exp(-re); _re2 = scalar * Math.cos(-im); _im2 = scalar * Math.sin(-im); // _1: _1.sub(_2) ... _re1 = _re1 - _re2; // !!! _im1 = _im1 - _im2; // !!! // result: _1.scale(0.5) ... result = cart( 0.5 * _re1, 0.5 * _im1 ); return result; }//end sinh() /** * Returns the hyperbolic cosine of a Complex number. * *

*

    *     cosh(z)  =  ( exp(z) + exp(-z) ) / 2
    * 
*

* @return The Complex hyperbolic cosine *

* @see Complex#cos() * @see Complex#acosh() **/ public Complex cosh () { Complex result; // cosh(z) = ( exp(z) + exp(-z) ) / 2 double scalar; double _re1, _im1; double _re2, _im2; // _1: z.exp() ... scalar = Math.exp(re); _re1 = scalar * Math.cos(im); _im1 = scalar * Math.sin(im); // _2: z.neg().exp() ... scalar = Math.exp(-re); _re2 = scalar * Math.cos(-im); _im2 = scalar * Math.sin(-im); // _1: _1.add(_2) ... _re1 = _re1 + _re2; // !!! _im1 = _im1 + _im2; // !!! // result: _1.scale(0.5) ... result = cart( 0.5 * _re1, 0.5 * _im1 ); return result; }//end cosh() /** * Returns the hyperbolic tangent of a Complex number. * *

*

    *     tanh(z)  =  sinh(z) / cosh(z)
    * 
*

* @return The Complex hyperbolic tangent *

* @see Complex#tan() * @see Complex#atanh() **/ public Complex tanh () { Complex result; // tanh(z) = sinh(z) / cosh(z) double scalar; double _re1, _im1; double _re2, _im2; double _re3, _im3; double ch_re, ch_im; // sinh() ... // _1: z.exp() ... scalar = Math.exp(re); _re1 = scalar * Math.cos(im); _im1 = scalar * Math.sin(im); // _2: z.neg().exp() ... scalar = Math.exp(-re); _re2 = scalar * Math.cos(-im); _im2 = scalar * Math.sin(-im); // _3: _1.sub(_2) ... _re3 = _re1 - _re2; _im3 = _im1 - _im2; // result: _3.scale(0.5) ... result = cart(0.5*_re3, 0.5*_im3); // cosh() ... // _3: _1.add(_2) ... _re3 = _re1 + _re2; _im3 = _im1 + _im2; // ch: _3.scale(0.5) ... ch_re = 0.5 * _re3; ch_im = 0.5 * _im3; // result: result.div(ch) ... div(result, ch_re, ch_im); return result; }//end tanh() /** * Returns the principal arc sine of a Complex number. * *

*

    *     asin(z)  =  -i * log(i*z + sqrt(1 - z*z))
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of asin(z), the others are * of the form: *

*

    *     k*PI + (-1)k  * A
    * 
*

* where k is any integer. *

* @return Principal Complex arc sine *

* @see Complex#sin() * @see Complex#sinh() **/ public Complex asin () { Complex result; // asin(z) = -i * log(i*z + sqrt(1 - z*z)) double _re1, _im1; // _1: one.sub(z.mul(z)) ... _re1 = 1.0 - ( (re*re) - (im*im) ); _im1 = 0.0 - ( (re*im) + (im*re) ); // result: _1.sqrt() ... result = cart(_re1, _im1); sqrt(result); // _1: z.mul(i) ... _re1 = - im; _im1 = + re; // result: _1.add(result) ... result.re = _re1 + result.re; result.im = _im1 + result.im; // _1: result.log() ... _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: i.neg().mul(_1) ... result.re = _im1; result.im = - _re1; return result; }//end asin() /** * Returns the principal arc cosine of a Complex number. * *

*

    *     acos(z)  =  -i * log( z + i * sqrt(1 - z*z) )
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of acos(z), the others are * of the form: *

*

    *     2*k*PI +/- A
    * 
*

* where k is any integer. *

* @return Principal Complex arc cosine *

* @see Complex#cos() * @see Complex#cosh() **/ public Complex acos () { Complex result; // acos(z) = -i * log( z + i * sqrt(1 - z*z) ) double _re1, _im1; // _1: one.sub(z.mul(z)) ... _re1 = 1.0 - ( (re*re) - (im*im) ); _im1 = 0.0 - ( (re*im) + (im*re) ); // result: _1.sqrt() ... result = cart(_re1, _im1); sqrt(result); // _1: i.mul(result) ... _re1 = - result.im; _im1 = + result.re; // result: z.add(_1) ... result.re = re + _re1; result.im = im + _im1; // _1: result.log() _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: i.neg().mul(_1) ... result.re = _im1; result.im = - _re1; return result; }//end acos() /** * Returns the principal arc tangent of a Complex number. * *

*

    *     atan(z)  =  -i/2 * log( (i-z)/(i+z) )
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of atan(z), the others are * of the form: *

*

    *     A + k*PI
    * 
*

* where k is any integer. *

* Domain Restrictions:

*

* @return Principal Complex arc tangent *

* @see Complex#tan() * @see Complex#tanh() **/ public Complex atan () { Complex result; // atan(z) = -i/2 * log( (i-z)/(i+z) ) double _re1, _im1; // result: i.sub(z) ... result = cart(- re, 1.0 - im); // _1: i.add(z) ... _re1 = + re; _im1 = 1.0 + im; // result: result.div(_1) ... div(result, _re1, _im1); // _1: result.log() ... _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: half_i.neg().mul(_2) ... result.re = 0.5*_im1; result.im = -0.5*_re1; return result; }//end atan() /** * Returns the principal inverse hyperbolic sine of a * Complex number. * *

*

    *     asinh(z)  =  log(z + sqrt(z*z + 1))
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of asinh(z), the others are * of the form: *

*

    *     k*PI*i + (-1)k  * A
    * 
*

* where k is any integer. *

* @return Principal Complex inverse hyperbolic sine *

* @see Complex#sinh() **/ public Complex asinh () { Complex result; // asinh(z) = log(z + sqrt(z*z + 1)) double _re1, _im1; // _1: z.mul(z).add(one) ... _re1 = ( (re*re) - (im*im) ) + 1.0; _im1 = ( (re*im) + (im*re) ) + 0.0; // result: _1.sqrt() ... result = cart(_re1, _im1); sqrt(result); // result: z.add(result) ... result.re = re + result.re; // ! result.im = im + result.im; // ! // _1: result.log() ... _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: _1 ... result.re = _re1; result.im = _im1; /* * Many thanks to the mathematicians of aus.mathematics and sci.math, * and to Zdislav V. Kovarik of the Department of Mathematics and * Statistics, McMaster University and John McGowan * in particular, for their advice on the current * naming conventions for "area/argumentus sinus hyperbolicus". */ return result; }//end asinh() /** * Returns the principal inverse hyperbolic cosine of a * Complex number. * *

*

    *     acosh(z)  =  log(z + sqrt(z*z - 1))
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of acosh(z), the others are * of the form: *

*

    *     2*k*PI*i +/- A
    * 
*

* where k is any integer. *

* @return Principal Complex inverse hyperbolic cosine *

* @see Complex#cosh() **/ public Complex acosh () { Complex result; // acosh(z) = log(z + sqrt(z*z - 1)) double _re1, _im1; // _1: z.mul(z).sub(one) ... _re1 = ( (re*re) - (im*im) ) - 1.0; _im1 = ( (re*im) + (im*re) ) - 0.0; // result: _1.sqrt() ... result = cart(_re1, _im1); sqrt(result); // result: z.add(result) ... result.re = re + result.re; // ! result.im = im + result.im; // ! // _1: result.log() ... _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: _1 ... result.re = _re1; result.im = _im1; return result; }//end acosh() /** * Returns the principal inverse hyperbolic tangent of a * Complex number. * *

*

    *     atanh(z)  =  1/2 * log( (1+z)/(1-z) )
    * 
*

* There are infinitely many solutions, besides the principal solution. * If A is the principal solution of atanh(z), the others are * of the form: *

*

    *     A + k*PI*i
    * 
*

* where k is any integer. *

* Domain Restrictions:

*

* @return Principal Complex inverse hyperbolic tangent *

* @see Complex#tanh() **/ public Complex atanh () { Complex result; // atanh(z) = 1/2 * log( (1+z)/(1-z) ) double _re1, _im1; // result: one.add(z) ... result = cart(1.0 + re, + im); // _1: one.sub(z) ... _re1 = 1.0 - re; _im1 = - im; // result: result.div(_1) ... div(result, _re1, _im1); // _1: result.log() ... _re1 = Math.log(result.abs()); _im1 = result.arg(); // result: _1.scale(0.5) ... result.re = 0.5 * _re1; result.im = 0.5 * _im1; return result; }//end atanh() /** * Converts a Complex into a {@link java.lang.String String} of the form * (a + bi). * *

* This enables a Complex to be easily printed. For example, if * z was 2 - 5i, then *

    *     System.out.println("z = " + z);
    * 
* would print something like *
    *     z = (2.0 - 5.0i)
    * 
* *

* @return {@link java.lang.String String} containing the cartesian coordinate representation *

* @see Complex#cart(double, double) **/ public String toString () { StringBuffer result = new StringBuffer("("); result.append(re); if (im < 0.0) { // ...remembering NaN & Infinity result.append(" - ").append(-im); } else if (1.0 / im == Double.NEGATIVE_INFINITY) { result.append(" - ").append(0.0); } else { result.append(" + ").append(+im); }//endif result.append("i)"); return result.toString(); }//end toString() /* I know a young man called Daniel, When you meet him, you'll like him, and you'll Find him so true, so human and new, You'll want to live life with no manual. */ }//end Complex /* Jim Shapiro Priyantha Jayanetti --------------------------- email: pidge@eece.maine.edu Dept. of Electrical & Computer Engineering University of Maine, Orono Mr. Daniel Hirsch /* C A U T I O N E X P L O S I V E B O L T S -- REMOVE BEFORE ENGAGING REPLY // // Kelly and Sandy Anderson // (alternatively kelsan_odoodle at ya who period, see oh em) // Alexander (Sandy) 1B5A DF3D A3D9 B932 39EB 3F1B 981F 4110 27E1 64A4 // Kelly 673F 6751 6DBA 196F E8A8 6D87 4AEC F35E E9AD 099B // Homepages http://www.explosive-alma-services-bolts.co.uk/ */