You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ps...@apache.org on 2007/11/19 00:38:15 UTC

svn commit: r596159 - in /commons/proper/math/trunk: src/java/org/apache/commons/math/complex/Complex.java src/java/org/apache/commons/math/complex/ComplexUtils.java src/test/org/apache/commons/math/complex/ComplexTest.java xdocs/changes.xml

Author: psteitz
Date: Sun Nov 18 15:38:05 2007
New Revision: 596159

URL: http://svn.apache.org/viewvc?rev=596159&view=rev
Log:
Merged most functions from ComplexUtils into Complex class, added
static factory method to Complex.
JIRA: MATH-171
Reported and patched by Niall Pemberton

Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/complex/Complex.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/complex/ComplexUtils.java
    commons/proper/math/trunk/src/test/org/apache/commons/math/complex/ComplexTest.java
    commons/proper/math/trunk/xdocs/changes.xml

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/complex/Complex.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/complex/Complex.java?rev=596159&r1=596158&r2=596159&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/complex/Complex.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/complex/Complex.java Sun Nov 18 15:38:05 2007
@@ -124,7 +124,7 @@
      * @throws NullPointerException if <code>rhs</code> is null
      */
     public Complex add(Complex rhs) {   
-        return new Complex(real + rhs.getReal(),
+        return createComplex(real + rhs.getReal(),
             imaginary + rhs.getImaginary());
     }
     
@@ -146,7 +146,7 @@
         if (isNaN()) {
             return NaN;
         }   
-        return new Complex(real, -imaginary);
+        return createComplex(real, -imaginary);
     }
     
     /**
@@ -201,19 +201,19 @@
 
         if (Math.abs(c) < Math.abs(d)) {
             if (d == 0.0) {
-                return new Complex(real/c, imaginary/c);
+                return createComplex(real/c, imaginary/c);
             }
             double q = c / d;
             double denominator = c * q + d;
-            return new Complex((real * q + imaginary) / denominator,
+            return createComplex((real * q + imaginary) / denominator,
                 (imaginary * q - real) / denominator);
         } else {
             if (c == 0.0) {
-                return new Complex(imaginary/d, -real/c);
+                return createComplex(imaginary/d, -real/c);
             }
             double q = d / c;
             double denominator = d * q + c;
-            return new Complex((imaginary * q + real) / denominator,
+            return createComplex((imaginary * q + real) / denominator,
                 (imaginary - real * q) / denominator);
         }
     }
@@ -349,7 +349,7 @@
         if (isNaN() || rhs.isNaN()) {
             return NaN;
         }
-        return new Complex(real * rhs.real - imaginary * rhs.imaginary,
+        return createComplex(real * rhs.real - imaginary * rhs.imaginary,
                 real * rhs.imaginary + imaginary * rhs.real);
     }
     
@@ -366,7 +366,7 @@
             return NaN;
         }
         
-        return new Complex(-real, -imaginary);
+        return createComplex(-real, -imaginary);
     }
     
     /**
@@ -392,7 +392,472 @@
             return NaN;
         }
         
-        return new Complex(real - rhs.getReal(),
+        return createComplex(real - rhs.getReal(),
             imaginary - rhs.getImaginary());
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
+     * inverse cosine</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre>
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code> or infinite.
+     * 
+     * @return the inverse cosine of this complex number
+     * @since 1.2
+     */
+    public Complex acos() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+
+        return this.add(this.sqrt1z().multiply(Complex.I)).log()
+              .multiply(Complex.I.negate());
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
+     * inverse sine</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre>
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code> or infinite.
+     * 
+     * @return the inverse sine of this complex number.
+     * @since 1.2
+     */
+    public Complex asin() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+
+        return sqrt1z().add(this.multiply(Complex.I)).log()
+              .multiply(Complex.I.negate());
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
+     * inverse tangent</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre>
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code> or infinite. 
+     * 
+     * @return the inverse tangent of this complex number
+     * @since 1.2
+     */
+    public Complex atan() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        return this.add(Complex.I).divide(Complex.I.subtract(this)).log()
+            .multiply(Complex.I.divide(createComplex(2.0, 0.0)));
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
+     * cosine</a>
+     * of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * cos(1 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
+     * cos(&plusmn;INFINITY + i) = NaN + NaN i
+     * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
+     * 
+     * @return the cosine of this complex number
+     * @since 1.2
+     */
+    public Complex cos() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        return createComplex(Math.cos(real) * MathUtils.cosh(imaginary),
+            -Math.sin(real) * MathUtils.sinh(imaginary));
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
+     * hyperbolic cosine</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
+     * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
+     * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
+     * 
+     * @return the hyperbolic cosine of this complex number.
+     * @since 1.2
+     */
+    public Complex cosh() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        return createComplex(MathUtils.cosh(real) * Math.cos(imaginary),
+            MathUtils.sinh(real) * Math.sin(imaginary));
+    }
+    
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
+     * exponential function</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
+     * {@link java.lang.Math#sin}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * exp(1 &plusmn; INFINITY i) = NaN + NaN i
+     * exp(INFINITY + i) = INFINITY + INFINITY i
+     * exp(-INFINITY + i) = 0 + 0i
+     * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
+     * 
+     * @return <i>e</i><sup><code>this</code></sup>
+     * @since 1.2
+     */
+    public Complex exp() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        double expReal = Math.exp(real);
+        return createComplex(expReal *  Math.cos(imaginary), expReal * Math.sin(imaginary));
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
+     * natural logarithm</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
+     * where ln on the right hand side is {@link java.lang.Math#log},
+     * <code>|a + bi|</code> is the modulus, {@link Complex#abs},  and
+     * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code>
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite (or critical) values in real or imaginary parts of the input may
+     * result in infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
+     * log(INFINITY + i) = INFINITY + 0i
+     * log(-INFINITY + i) = INFINITY + &pi;i
+     * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
+     * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
+     * log(0 + 0i) = -INFINITY + 0i
+     * </code></pre>
+     * 
+     * @return ln of this complex number.
+     * @since 1.2
+     */
+    public Complex log() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+
+        return createComplex(Math.log(abs()),
+            Math.atan2(imaginary, real));        
+    }
+    
+    /**
+     * Returns of value of this complex number raised to the power of <code>x</code>.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre> 
+     * where <code>exp</code> and <code>log</code> are {@link #exp} and
+     * {@link #log}, respectively.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code> or infinite, or if <code>y</code>
+     * equals {@link Complex#ZERO}.
+     * 
+     * @param x the exponent.
+     * @return <code>this</code><sup><code>x</code></sup>
+     * @throws NullPointerException if x is null
+     * @since 1.2
+     */
+    public Complex pow(Complex x) {
+        if (x == null) {
+            throw new NullPointerException();
+        }
+        return this.log().multiply(x).exp();
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
+     * sine</a>
+     * of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
+     * sin(&plusmn;INFINITY + i) = NaN + NaN i
+     * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
+     * 
+     * @return the sine of this complex number.
+     * @since 1.2
+     */
+    public Complex sin() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        return createComplex(Math.sin(real) * MathUtils.cosh(imaginary),
+            Math.cos(real) * MathUtils.sinh(imaginary));
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
+     * hyperbolic sine</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
+     * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
+     * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre
+     * 
+     * @return the hyperbolic sine of this complex number
+     * @since 1.2
+     */
+    public Complex sinh() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        return createComplex(MathUtils.sinh(real) * Math.cos(imaginary),
+            MathUtils.cosh(real) * Math.sin(imaginary));
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
+     * square root</a> of this complex number.
+     * <p>
+     * Implements the following algorithm to compute <code>sqrt(a + bi)</code>: 
+     * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
+     * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
+     *  else return <code>|b|/2t + sign(b)t i </code></pre></li>
+     * </ol>
+     * where <ul>
+     * <li><code>|a| = {@link Math#abs}(a)</code></li>
+     * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
+     * <li><code>sign(b) =  {@link MathUtils#indicator}(b) </code>
+     * </ul>
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
+     * sqrt(INFINITY + i) = INFINITY + 0i
+     * sqrt(-INFINITY + i) = 0 + INFINITY i
+     * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
+     * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
+     * </code></pre>
+     * 
+     * @return the square root of this complex number
+     * @since 1.2
+     */
+    public Complex sqrt() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        if (real == 0.0 && imaginary == 0.0) {
+            return createComplex(0.0, 0.0);
+        }
+        
+        double t = Math.sqrt((Math.abs(real) + abs()) / 2.0);
+        if (real >= 0.0) {
+            return createComplex(t, imaginary / (2.0 * t));
+        } else {
+            return createComplex(Math.abs(imaginary) / (2.0 * t),
+                MathUtils.indicator(imaginary) * t);
+        }
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
+     * square root</a> of 1 - <code>this</code><sup>2</sup> for this complex
+     * number.
+     * <p>
+     * Computes the result directly as 
+     * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result. 
+     * 
+     * @return the square root of 1 - <code>this</code><sup>2</sup>
+     * @since 1.2
+     */
+    public Complex sqrt1z() {
+        return createComplex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
+    }
+    
+    /**
+     * Compute the 
+     * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
+     * tangent</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite (or critical) values in real or imaginary parts of the input may
+     * result in infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * tan(1 &plusmn; INFINITY i) = 0 + NaN i
+     * tan(&plusmn;INFINITY + i) = NaN + NaN i
+     * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
+     * tan(&plusmn;&pi;/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre>
+     * 
+     * @return the tangent of this complex number
+     * @since 1.2
+     */
+    public Complex tan() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        double real2 = 2.0 * real;
+        double imaginary2 = 2.0 * imaginary;
+        double d = Math.cos(real2) + MathUtils.cosh(imaginary2);
+        
+        return createComplex(Math.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
+    }
+    
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
+     * hyperbolic tangent</a> of this complex number.
+     * <p>
+     * Implements the formula: <pre>
+     * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
+     * where the (real) functions on the right-hand side are
+     * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
+     * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
+     * <p>
+     * Returns {@link Complex#NaN} if either real or imaginary part of the 
+     * input argument is <code>NaN</code>.
+     * <p>
+     * Infinite values in real or imaginary parts of the input may result in
+     * infinite or NaN values returned in parts of the result.<pre>
+     * Examples: 
+     * <code>
+     * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
+     * tanh(&plusmn;INFINITY + i) = NaN + 0 i
+     * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
+     * tanh(0 + (&pi;/2)i) = NaN + INFINITY i</code></pre>
+     *
+     * @return the hyperbolic tangent of this complex number
+     * @since 1.2
+     */
+    public Complex tanh() {
+        if (isNaN()) {
+            return Complex.NaN;
+        }
+        
+        double real2 = 2.0 * real;
+        double imaginary2 = 2.0 * imaginary;
+        double d = MathUtils.cosh(real2) + Math.cos(imaginary2);
+        
+        return createComplex(MathUtils.sinh(real2) / d, Math.sin(imaginary2) / d);
+    }
+
+    /**
+     * Create a complex number given the real and imaginary parts.
+     *
+     * @param real the real part
+     * @param imaginary the imaginary part
+     * @return a new complex number instance
+     * @since 1.2
+     */
+    protected Complex createComplex(double real, double imaginary) {
+        return new Complex(real, imaginary);
     }
 }

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/complex/ComplexUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/complex/ComplexUtils.java?rev=596159&r1=596158&r2=596159&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/complex/ComplexUtils.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/complex/ComplexUtils.java Sun Nov 18 15:38:05 2007
@@ -60,14 +60,10 @@
      * @param z the value whose inverse cosine is to be returned
      * @return the inverse cosine of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.acos()
      */
     public static Complex acos(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-
-        return Complex.I.negate().multiply(log(z.add(
-            Complex.I.multiply(sqrt1z(z)))));       
+        return z.acos();
     }
     
     /**
@@ -84,14 +80,10 @@
      * @param z the value whose inverse sine is to be returned.
      * @return the inverse sine of <code>z</code>.
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.asin()
      */
     public static Complex asin(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-
-        return Complex.I.negate().multiply(log(sqrt1z(z).add(
-            Complex.I.multiply(z))));       
+        return z.asin();
     }
     
     /**
@@ -108,15 +100,10 @@
      * @param z the value whose inverse tangent is to be returned
      * @return the inverse tangent of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.atan()
      */
     public static Complex atan(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        return Complex.I.multiply(
-            log(Complex.I.add(z).divide(Complex.I.subtract(z))))
-            .divide(new Complex(2.0, 0.0));
+        return z.atan();
     }
     
     /**
@@ -145,17 +132,10 @@
      * @param z the value whose cosine is to be returned
      * @return the cosine of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.cos()
      */
     public static Complex cos(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a = z.getReal();
-        double b = z.getImaginary();
-        
-        return new Complex(Math.cos(a) * MathUtils.cosh(b),
-            -Math.sin(a) * MathUtils.sinh(b));
+        return z.cos();
     }
     
     /**
@@ -184,17 +164,10 @@
      * 
      * @param z the value whose hyperbolic cosine is to be returned.
      * @return the hyperbolic cosine of <code>z</code>.
+     * @deprecated use Complex.cosh()
      */
     public static Complex cosh(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a = z.getReal();
-        double b = z.getImaginary();
-        
-        return new Complex(MathUtils.cosh(a) * Math.cos(b),
-            MathUtils.sinh(a) * Math.sin(b));
+        return z.cosh();
     }
     
     /**
@@ -224,15 +197,10 @@
      * 
      * @param z the value
      * @return <i>e</i><sup><code>z</code></sup>
+     * @deprecated use Complex.exp()
      */
     public static Complex exp(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double b = z.getImaginary();
-        double expA = Math.exp(z.getReal());
-        return new Complex(expA *  Math.cos(b), expA * Math.sin(b));
+        return z.exp();
     }
     
     /**
@@ -264,14 +232,10 @@
      * 
      * @param z the value.
      * @return ln <code>z</code>.
+     * @deprecated use Complex.log()
      */
     public static Complex log(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-
-        return new Complex(Math.log(z.abs()),
-            Math.atan2(z.getImaginary(), z.getReal()));        
+        return z.log();
     }
     
     /**
@@ -323,9 +287,10 @@
      * @param x the exponent.
      * @return <code>y</code><sup><code>x</code></sup>
      * @throws NullPointerException if either x or y is null
+     * @deprecated use Complex.pow(x)
      */
     public static Complex pow(Complex y, Complex x) {
-        return exp(x.multiply(log(y)));
+        return y.pow(x);
     }
     
     /**
@@ -355,17 +320,10 @@
      * 
      * @param z the value whose sine is to be returned.
      * @return the sine of <code>z</code>.
+     * @deprecated use Complex.sin()
      */
     public static Complex sin(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a = z.getReal();
-        double b = z.getImaginary();
-        
-        return new Complex(Math.sin(a) * MathUtils.cosh(b),
-            Math.cos(a) * MathUtils.sinh(b));
+        return z.sin();
     }
     
     /**
@@ -393,17 +351,10 @@
      * @param z the value whose hyperbolic sine is to be returned
      * @return the hyperbolic sine of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.sinh()
      */
     public static Complex sinh(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a = z.getReal();
-        double b = z.getImaginary();
-        
-        return new Complex(MathUtils.sinh(a) * Math.cos(b),
-            MathUtils.cosh(a) * Math.sin(b));
+        return z.sinh();
     }
     
     /**
@@ -439,25 +390,10 @@
      * @param z the value whose square root is to be returned
      * @return the square root of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.sqrt()
      */
     public static Complex sqrt(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a = z.getReal();
-        double b = z.getImaginary();
-        if (a == 0.0 && b == 0.0) {
-            return new Complex(0.0, 0.0);
-        }
-        
-        double t = Math.sqrt((Math.abs(a) + z.abs()) / 2.0);
-        if (a >= 0.0) {
-            return new Complex(t, b / (2.0 * t));
-        } else {
-            return new Complex(Math.abs(b) / (2.0 * t),
-                MathUtils.indicator(b) * t);
-        }
+        return z.sqrt();
     }
     
     /**
@@ -478,9 +414,10 @@
      * @param z the value
      * @return the square root of 1 - <code>z</code><sup>2</sup>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.sqrt1z()
      */
     public static Complex sqrt1z(Complex z) {
-        return sqrt(Complex.ONE.subtract(z.multiply(z)));
+        return z.sqrt1z();
     }
     
     /**
@@ -509,17 +446,10 @@
      * @param z the value whose tangent is to be returned
      * @return the tangent of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.tan()
      */
     public static Complex tan(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a2 = 2.0 * z.getReal();
-        double b2 = 2.0 * z.getImaginary();
-        double d = Math.cos(a2) + MathUtils.cosh(b2);
-        
-        return new Complex(Math.sin(a2) / d, MathUtils.sinh(b2) / d);
+        return z.tan();
     }
     
     /**
@@ -548,16 +478,9 @@
      * @param z the value whose hyperbolic tangent is to be returned
      * @return the hyperbolic tangent of <code>z</code>
      * @throws NullPointerException if <code>z</code> is null
+     * @deprecated use Complex.tanh()
      */
     public static Complex tanh(Complex z) {
-        if (z.isNaN()) {
-            return Complex.NaN;
-        }
-        
-        double a2 = 2.0 * z.getReal();
-        double b2 = 2.0 * z.getImaginary();
-        double d = MathUtils.cosh(a2) + Math.cos(b2);
-        
-        return new Complex(MathUtils.sinh(a2) / d, Math.sin(b2) / d);
+        return z.tanh();
     }
 }

Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/complex/ComplexTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/complex/ComplexTest.java?rev=596159&r1=596158&r2=596159&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/complex/ComplexTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/complex/ComplexTest.java Sun Nov 18 15:38:05 2007
@@ -17,6 +17,8 @@
 
 package org.apache.commons.math.complex;
 
+import org.apache.commons.math.TestUtils;
+
 import junit.framework.TestCase;
 
 /**
@@ -27,12 +29,25 @@
     private double inf = Double.POSITIVE_INFINITY;
     private double neginf = Double.NEGATIVE_INFINITY;
     private double nan = Double.NaN;
+    private double pi = Math.PI;
     private Complex oneInf = new Complex(1, inf);
     private Complex oneNegInf = new Complex(1, neginf);
     private Complex infOne = new Complex(inf, 1);
+    private Complex infZero = new Complex(inf, 0);
+    private Complex infNaN = new Complex(inf, nan);
+    private Complex infNegInf = new Complex(inf, neginf);
+    private Complex infInf = new Complex(inf, inf);
     private Complex negInfInf = new Complex(neginf, inf);
+    private Complex negInfZero = new Complex(neginf, 0);
+    private Complex negInfOne = new Complex(neginf, 1);
+    private Complex negInfNaN = new Complex(neginf, nan);
     private Complex negInfNegInf = new Complex(neginf, neginf);
     private Complex oneNaN = new Complex(1, nan);
+    private Complex zeroInf = new Complex(0, inf);
+    private Complex zeroNaN = new Complex(0, nan);
+    private Complex nanInf = new Complex(nan, inf);
+    private Complex nanNegInf = new Complex(nan, neginf);
+    private Complex nanZero = new Complex(nan, 0);
     
     public void testConstructor() {
         Complex z = new Complex(3.0, 4.0);
@@ -274,5 +289,400 @@
         Complex imaginaryNaN = new Complex(0.0, Double.NaN);
         assertEquals(realNaN.hashCode(), imaginaryNaN.hashCode());
         assertEquals(imaginaryNaN.hashCode(), Complex.NaN.hashCode());
+    }
+    
+    public void testAcos() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(0.936812, -2.30551);
+        TestUtils.assertEquals(expected, z.acos(), 1.0e-5);
+        TestUtils.assertEquals(new Complex(Math.acos(0), 0), 
+                Complex.ZERO.acos(), 1.0e-12);
+    }
+    
+    public void testAcosInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.acos());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.acos());
+        TestUtils.assertSame(Complex.NaN, infOne.acos());
+        TestUtils.assertSame(Complex.NaN, negInfOne.acos());
+        TestUtils.assertSame(Complex.NaN, infInf.acos());
+        TestUtils.assertSame(Complex.NaN, infNegInf.acos());
+        TestUtils.assertSame(Complex.NaN, negInfInf.acos());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.acos());
+    }
+    
+    public void testAcosNaN() {
+        assertTrue(Complex.NaN.acos().isNaN());
+    }
+    
+    public void testAsin() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(0.633984, 2.30551);
+        TestUtils.assertEquals(expected, z.asin(), 1.0e-5);
+    }
+    
+    public void testAsinNaN() {
+        assertTrue(Complex.NaN.asin().isNaN());
+    }
+    
+    public void testAsinInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.asin());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.asin());
+        TestUtils.assertSame(Complex.NaN, infOne.asin());
+        TestUtils.assertSame(Complex.NaN, negInfOne.asin());
+        TestUtils.assertSame(Complex.NaN, infInf.asin());
+        TestUtils.assertSame(Complex.NaN, infNegInf.asin());
+        TestUtils.assertSame(Complex.NaN, negInfInf.asin());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.asin());
+    }
+    
+   
+    public void testAtan() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(1.44831, 0.158997);
+        TestUtils.assertEquals(expected, z.atan(), 1.0e-5);
+    }
+    
+    public void testAtanInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.atan());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.atan());
+        TestUtils.assertSame(Complex.NaN, infOne.atan());
+        TestUtils.assertSame(Complex.NaN, negInfOne.atan());
+        TestUtils.assertSame(Complex.NaN, infInf.atan());
+        TestUtils.assertSame(Complex.NaN, infNegInf.atan());
+        TestUtils.assertSame(Complex.NaN, negInfInf.atan());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.atan());
+    } 
+    
+    public void testAtanNaN() {
+        assertTrue(Complex.NaN.atan().isNaN());
+        assertTrue(Complex.I.atan().isNaN());
+    }
+    
+    public void testCos() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(-27.03495, -3.851153);
+        TestUtils.assertEquals(expected, z.cos(), 1.0e-5);
+    }
+    
+    public void testCosNaN() {
+        assertTrue(Complex.NaN.cos().isNaN());
+    }
+    
+    public void testCosInf() {
+        TestUtils.assertSame(infNegInf, oneInf.cos());
+        TestUtils.assertSame(infInf, oneNegInf.cos());
+        TestUtils.assertSame(Complex.NaN, infOne.cos());
+        TestUtils.assertSame(Complex.NaN, negInfOne.cos());
+        TestUtils.assertSame(Complex.NaN, infInf.cos());
+        TestUtils.assertSame(Complex.NaN, infNegInf.cos());
+        TestUtils.assertSame(Complex.NaN, negInfInf.cos());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.cos());
+    } 
+    
+    public void testCosh() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(-6.58066, -7.58155);
+        TestUtils.assertEquals(expected, z.cosh(), 1.0e-5);
+    }
+    
+    public void testCoshNaN() {
+        assertTrue(Complex.NaN.cosh().isNaN());
+    }
+    
+    public void testCoshInf() {  
+        TestUtils.assertSame(Complex.NaN, oneInf.cosh());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.cosh());
+        TestUtils.assertSame(infInf, infOne.cosh());
+        TestUtils.assertSame(infNegInf, negInfOne.cosh());
+        TestUtils.assertSame(Complex.NaN, infInf.cosh());
+        TestUtils.assertSame(Complex.NaN, infNegInf.cosh());
+        TestUtils.assertSame(Complex.NaN, negInfInf.cosh());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.cosh());
+    } 
+    
+    public void testExp() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(-13.12878, -15.20078);
+        TestUtils.assertEquals(expected, z.exp(), 1.0e-5);
+        TestUtils.assertEquals(Complex.ONE, 
+                Complex.ZERO.exp(), 10e-12);
+        Complex iPi = Complex.I.multiply(new Complex(pi,0));
+        TestUtils.assertEquals(Complex.ONE.negate(), 
+                iPi.exp(), 10e-12);
+    }
+    
+    public void testExpNaN() {
+        assertTrue(Complex.NaN.exp().isNaN());
+    }
+    
+    public void testExpInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.exp());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.exp());
+        TestUtils.assertSame(infInf, infOne.exp());
+        TestUtils.assertSame(Complex.ZERO, negInfOne.exp());
+        TestUtils.assertSame(Complex.NaN, infInf.exp());
+        TestUtils.assertSame(Complex.NaN, infNegInf.exp());
+        TestUtils.assertSame(Complex.NaN, negInfInf.exp());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.exp());
+    }
+    
+    public void testLog() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(1.60944, 0.927295);
+        TestUtils.assertEquals(expected, z.log(), 1.0e-5);
+    }
+    
+    public void testLogNaN() {
+        assertTrue(Complex.NaN.log().isNaN());
+    }
+    
+    public void testLogInf() {
+        TestUtils.assertEquals(new Complex(inf, pi / 2),
+                oneInf.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, -pi / 2),
+                oneNegInf.log(), 10e-12);
+        TestUtils.assertEquals(infZero, infOne.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, pi),
+                negInfOne.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, pi / 4),
+                infInf.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, -pi / 4),
+                infNegInf.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, 3d * pi / 4),
+                negInfInf.log(), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, - 3d * pi / 4),
+                negInfNegInf.log(), 10e-12);
+    }
+    
+    public void testLogZero() {
+        TestUtils.assertSame(negInfZero, Complex.ZERO.log());
+    }
+    
+    public void testPow() {
+        Complex x = new Complex(3, 4);
+        Complex y = new Complex(5, 6);
+        Complex expected = new Complex(-1.860893, 11.83677);
+        TestUtils.assertEquals(expected, x.pow(y), 1.0e-5);
+    }
+    
+    public void testPowNaNBase() {
+        Complex x = new Complex(3, 4);
+        assertTrue(Complex.NaN.pow(x).isNaN());
+    }
+    
+    public void testPowNaNExponent() {
+        Complex x = new Complex(3, 4);
+        assertTrue(x.pow(Complex.NaN).isNaN());
+    }
+    
+   public void testPowInf() {
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(oneInf));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(oneNegInf));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(infOne));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(infInf));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(infNegInf));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(negInfInf));
+       TestUtils.assertSame(Complex.NaN,Complex.ONE.pow(negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,infOne.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,negInfOne.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,infInf.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,infNegInf.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,negInfInf.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,negInfNegInf.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,negInfNegInf.pow(infNegInf));
+       TestUtils.assertSame(Complex.NaN,negInfNegInf.pow(negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,negInfNegInf.pow(infInf));
+       TestUtils.assertSame(Complex.NaN,infInf.pow(infNegInf));
+       TestUtils.assertSame(Complex.NaN,infInf.pow(negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,infInf.pow(infInf));
+       TestUtils.assertSame(Complex.NaN,infNegInf.pow(infNegInf));
+       TestUtils.assertSame(Complex.NaN,infNegInf.pow(negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,infNegInf.pow(infInf));   
+   }
+   
+   public void testPowZero() {
+       TestUtils.assertSame(Complex.NaN, 
+               Complex.ZERO.pow(Complex.ONE));
+       TestUtils.assertSame(Complex.NaN, 
+               Complex.ZERO.pow(Complex.ZERO));
+       TestUtils.assertSame(Complex.NaN, 
+               Complex.ZERO.pow(Complex.I));
+       TestUtils.assertEquals(Complex.ONE,
+               Complex.ONE.pow(Complex.ZERO), 10e-12);
+       TestUtils.assertEquals(Complex.ONE,
+               Complex.I.pow(Complex.ZERO), 10e-12);
+       TestUtils.assertEquals(Complex.ONE,
+               new Complex(-1, 3).pow(Complex.ZERO), 10e-12);
+   }
+    
+    public void testpowNull() {
+        try {
+            Complex.ONE.pow(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
+    public void testSin() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(3.853738, -27.01681);
+        TestUtils.assertEquals(expected, z.sin(), 1.0e-5);
+    }
+    
+    public void testSinInf() {
+        TestUtils.assertSame(infInf, oneInf.sin());
+        TestUtils.assertSame(infNegInf, oneNegInf.sin());
+        TestUtils.assertSame(Complex.NaN, infOne.sin());
+        TestUtils.assertSame(Complex.NaN, negInfOne.sin());
+        TestUtils.assertSame(Complex.NaN, infInf.sin());
+        TestUtils.assertSame(Complex.NaN, infNegInf.sin());
+        TestUtils.assertSame(Complex.NaN, negInfInf.sin());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.sin());
+    }
+    
+    public void testSinNaN() {
+        assertTrue(Complex.NaN.sin().isNaN());
+    }
+    
+    public void testSinh() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(-6.54812, -7.61923);
+        TestUtils.assertEquals(expected, z.sinh(), 1.0e-5);
+    }
+    
+    public void testSinhNaN() {
+        assertTrue(Complex.NaN.sinh().isNaN());
+    }
+    
+    public void testSinhInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.sinh());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.sinh());
+        TestUtils.assertSame(infInf, infOne.sinh());
+        TestUtils.assertSame(negInfInf, negInfOne.sinh());
+        TestUtils.assertSame(Complex.NaN, infInf.sinh());
+        TestUtils.assertSame(Complex.NaN, infNegInf.sinh());
+        TestUtils.assertSame(Complex.NaN, negInfInf.sinh());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.sinh());
+    }
+    
+    public void testSqrtRealPositive() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(2, 1);
+        TestUtils.assertEquals(expected, z.sqrt(), 1.0e-5);
+    }
+    
+    public void testSqrtRealZero() {
+        Complex z = new Complex(0.0, 4);
+        Complex expected = new Complex(1.41421, 1.41421);
+        TestUtils.assertEquals(expected, z.sqrt(), 1.0e-5);
+    }
+    
+    public void testSqrtRealNegative() {
+        Complex z = new Complex(-3.0, 4);
+        Complex expected = new Complex(1, 2);
+        TestUtils.assertEquals(expected, z.sqrt(), 1.0e-5);
+    }
+    
+    public void testSqrtImaginaryZero() {
+        Complex z = new Complex(-3.0, 0.0);
+        Complex expected = new Complex(0.0, 1.73205);
+        TestUtils.assertEquals(expected, z.sqrt(), 1.0e-5);
+    }
+    
+    public void testSqrtImaginaryNegative() {
+        Complex z = new Complex(-3.0, -4.0);
+        Complex expected = new Complex(1.0, -2.0);
+        TestUtils.assertEquals(expected, z.sqrt(), 1.0e-5);
+    }
+    
+    public void testSqrtPolar() {
+        double r = 1;
+        for (int i = 0; i < 5; i++) {
+            r += i;
+            double theta = 0;
+            for (int j =0; j < 11; j++) {
+                theta += pi /12;
+                Complex z = ComplexUtils.polar2Complex(r, theta);
+                Complex sqrtz = ComplexUtils.polar2Complex(Math.sqrt(r), theta / 2);
+                TestUtils.assertEquals(sqrtz, z.sqrt(), 10e-12);
+            }
+        }       
+    }
+    
+    public void testSqrtNaN() {
+        assertTrue(Complex.NaN.sqrt().isNaN());
+    }
+      
+    public void testSqrtInf() {
+        TestUtils.assertSame(infNaN, oneInf.sqrt());
+        TestUtils.assertSame(infNaN, oneNegInf.sqrt());
+        TestUtils.assertSame(infZero, infOne.sqrt());
+        TestUtils.assertSame(zeroInf, negInfOne.sqrt());
+        TestUtils.assertSame(infNaN, infInf.sqrt());
+        TestUtils.assertSame(infNaN, infNegInf.sqrt());
+        TestUtils.assertSame(nanInf, negInfInf.sqrt());
+        TestUtils.assertSame(nanNegInf, negInfNegInf.sqrt());
+    }
+    
+    public void testSqrt1z() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(4.08033, -2.94094);
+        TestUtils.assertEquals(expected, z.sqrt1z(), 1.0e-5);
+    }
+    
+    public void testSqrt1zNaN() {
+        assertTrue(Complex.NaN.sqrt1z().isNaN());
+    }
+    
+    public void testTan() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(-0.000187346, 0.999356);
+        TestUtils.assertEquals(expected, z.tan(), 1.0e-5);
+    }
+    
+    public void testTanNaN() {
+        assertTrue(Complex.NaN.tan().isNaN());
+    }
+    
+    public void testTanInf() {
+        TestUtils.assertSame(zeroNaN, oneInf.tan());
+        TestUtils.assertSame(zeroNaN, oneNegInf.tan());
+        TestUtils.assertSame(Complex.NaN, infOne.tan());
+        TestUtils.assertSame(Complex.NaN, negInfOne.tan());
+        TestUtils.assertSame(Complex.NaN, infInf.tan());
+        TestUtils.assertSame(Complex.NaN, infNegInf.tan());
+        TestUtils.assertSame(Complex.NaN, negInfInf.tan());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.tan());
+    }
+    
+   public void testTanCritical() {
+        TestUtils.assertSame(infNaN, new Complex(pi/2, 0).tan());
+        TestUtils.assertSame(negInfNaN, new Complex(-pi/2, 0).tan());
+    }
+    
+    public void testTanh() {
+        Complex z = new Complex(3, 4);
+        Complex expected = new Complex(1.00071, 0.00490826);
+        TestUtils.assertEquals(expected, z.tanh(), 1.0e-5);
+    }
+    
+    public void testTanhNaN() {
+        assertTrue(Complex.NaN.tanh().isNaN());
+    }
+    
+    public void testTanhInf() {
+        TestUtils.assertSame(Complex.NaN, oneInf.tanh());
+        TestUtils.assertSame(Complex.NaN, oneNegInf.tanh());
+        TestUtils.assertSame(nanZero, infOne.tanh());
+        TestUtils.assertSame(nanZero, negInfOne.tanh());
+        TestUtils.assertSame(Complex.NaN, infInf.tanh());
+        TestUtils.assertSame(Complex.NaN, infNegInf.tanh());
+        TestUtils.assertSame(Complex.NaN, negInfInf.tanh());
+        TestUtils.assertSame(Complex.NaN, negInfNegInf.tanh());
+    }
+    
+    public void testTanhCritical() {
+        TestUtils.assertSame(nanInf, new Complex(0, pi/2).tanh());
     }
 }

Modified: commons/proper/math/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/xdocs/changes.xml?rev=596159&r1=596158&r2=596159&view=diff
==============================================================================
--- commons/proper/math/trunk/xdocs/changes.xml (original)
+++ commons/proper/math/trunk/xdocs/changes.xml Sun Nov 18 15:38:05 2007
@@ -40,6 +40,10 @@
   </properties>
   <body>
     <release version="1.2-SNAPSHOT" date="TBD">
+      <action dev="psteitz" type="update" issue="MATH-171" due-to="Niall Pemberton">
+        Merged most functions from ComplexUtils into Complex class, added
+        static factory method to Complex.
+      </action>
       <action dev="luc" type="fix">
         Fixed numerous warnings in test code.
       </action>