You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ps...@apache.org on 2005/11/23 18:44:04 UTC

svn commit: r348502 - in /jakarta/commons/proper/math/branches/MATH_1_1: ./ src/java/org/apache/commons/math/complex/ src/test/org/apache/commons/math/ src/test/org/apache/commons/math/complex/ xdocs/ xdocs/userguide/

Author: psteitz
Date: Wed Nov 23 09:43:57 2005
New Revision: 348502

URL: http://svn.apache.org/viewcvs?rev=348502&view=rev
Log:
* Added polar2Complex method to ComplexUtils to create Complex numbers from
  polar representations.
* Improved documentation and test cases related to handling of infinite and NaN
  values in Complex, ComplexUtils classes. BZ #37086.

Modified:
    jakarta/commons/proper/math/branches/MATH_1_1/project.xml
    jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/Complex.java
    jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/ComplexUtils.java
    jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/TestUtils.java
    jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/complex/ComplexUtilsTest.java
    jakarta/commons/proper/math/branches/MATH_1_1/xdocs/changes.xml
    jakarta/commons/proper/math/branches/MATH_1_1/xdocs/userguide/complex.xml

Modified: jakarta/commons/proper/math/branches/MATH_1_1/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/project.xml?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/project.xml (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/project.xml Wed Nov 23 09:43:57 2005
@@ -205,8 +205,8 @@
   <reports>
     <report>maven-changes-plugin</report>
     <report>maven-checkstyle-plugin</report>
-    <report>maven-clover-plugin</report>
     <!--
+    <report>maven-clover-plugin</report>
     <report>maven-changelog-plugin</report>
     <report>maven-developer-activity-plugin</report>
     <report>maven-file-activity-plugin</report>

Modified: jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/Complex.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/Complex.java?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/Complex.java (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/Complex.java Wed Nov 23 09:43:57 2005
@@ -23,11 +23,11 @@
  * Representation of a Complex number - a number which has both a 
  * real and imaginary part.
  * <p>
- * Implementation of arithmetic operations handles <code>NaN</code> and
+ * Implementations of arithmetic operations handle <code>NaN</code> and
  * infinite values according to the rules for {@link java.lang.Double}
  * arithmetic, applying definitional formulas and returning <code>NaN</code> or
  * infinite values in real or imaginary parts as these arise in computation. 
- * See the javadoc for individual methods for details.
+ * See individual method javadocs for details.
  * <p>
  * {@link #equals} identifies all values with <code>NaN</code> in either real 
  * or imaginary part - e.g., <pre>
@@ -76,7 +76,7 @@
      * <p>
      * Returns <code>NaN</code> if either real or imaginary part is
      * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
-     * neither part is <code>NaN</code>, but at least on part takes an infinite
+     * neither part is <code>NaN</code>, but at least one part takes an infinite
      * value.
      *
      * @return the absolute value.
@@ -110,11 +110,15 @@
      * <p>
      * Uses the definitional formula 
      * <pre>
-     * (a + bi) + (c + di) = (a+c) + (b + d)i
+     * (a + bi) + (c + di) = (a+c) + (b+d)i
      * </pre>
      * <p>
-     * Inifinite and NaN values are returned in the parts according to the
-     * rules for {@link java.lang.Double} arithmetic. 
+     * If either this or <code>rhs</code> has a NaN value in either part,
+     * {@link #NaN} is returned; otherwise Inifinite and NaN values are
+     * returned in the parts of the result according to the rules for
+     * {@link java.lang.Double} arithmetic. 
+     * <p>
+     * Throws <code>NullPointerException</code> if <code>rhs</code> is null.
      *
      * @param rhs the other complex number.
      * @return the complex number sum.
@@ -128,13 +132,13 @@
      * Return the conjugate of this complex number. The conjugate of
      * "A + Bi" is "A - Bi". 
      * <p>
-     * Complex.NaN is returned if either the real or imaginary
-     * part of this Complex number equals Double.NaN.
+     * {@link #NaN} is returned if either the real or imaginary
+     * part of this Complex number equals <code>Double.NaN</code>.
      * <p>
      * If the imaginary part is infinite, and the real part is not NaN, 
      * the returned value has infinite imaginary part of the opposite
      * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
-     * is <code>1 + NEGATIVE_INFINITY i</code>
+     * is <code>1 - NEGATIVE_INFINITY i</code>
      *
      * @return the conjugate of this Complex object
      */
@@ -152,7 +156,7 @@
      * <pre><code>
      *    a + bi          ac + bd + (bc - ad)i
      *    ----------- = -------------------------
-     *    c + di                c*c + d*d
+     *    c + di               c<sup>2</sup> + d<sup>2</sup>
      * </code></pre>
      * but uses 
      * <a href="http://doi.acm.org/10.1145/1039813.1039814">
@@ -172,9 +176,10 @@
      *  <code>rhs</code> is infinite (one or both parts infinite), 
      * {@link #ZERO} is returned.</li>
      * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
-     * returned in parts if the {@link java.lang.Double} rules applied to the
-     * definitional formula force NaN results.</li>
+     * returned in the parts of the result if the {@link java.lang.Double}
+     * rules applied to the definitional formula force NaN results.</li>
      * </ul>
+     * Throws <code>NullPointerException</code> if <code>rhs</code> is null.
      * 
      * @param rhs the other complex number
      * @return the complex number quotient
@@ -222,7 +227,7 @@
      * <p>
      * All <code>NaN</code> values are considered to be equal - i.e, if either
      * (or both) real and imaginary parts of the complex number are equal
-     * to Double.NaN, the complex number is equal to 
+     * to <code>Double.NaN</code>, the complex number is equal to 
      * <code>Complex.NaN</code>.
      *
      * @param other Object to test for equality to this
@@ -336,6 +341,8 @@
      *  (-INF + -INFi)(1 + NaNi) = NaN + NaNi
      *  </code></pre>
      * 
+     * Throws <code>NullPointerException</code> if <code>rhs</code> is null.
+     * 
      * @param rhs the other complex number.
      * @return the complex number product.
      */
@@ -349,6 +356,9 @@
     
     /**
      * Return the additive inverse of this complex number.
+     * <p>
+     * Returns <code>Complex.NaN</code> if either real or imaginary
+     * part of this Complex number equals <code>Double.NaN</code>.
      *
      * @return the negation of this complex number.
      */
@@ -363,7 +373,19 @@
     /**
      * Return the difference between this complex number and the given complex
      * number.
-     *
+      * <p>
+     * Uses the definitional formula 
+     * <pre>
+     * (a + bi) - (c + di) = (a-c) + (b-d)i
+     * </pre>
+     * <p>
+     * If either this or <code>rhs</code> has a NaN value in either part,
+     * {@link #NaN} is returned; otherwise inifinite and NaN values are
+     * returned in the parts of the result according to the rules for
+     * {@link java.lang.Double} arithmetic. 
+     * <p>
+     * Throws <code>NullPointerException</code> if <code>rhs</code> is null.
+     * 
      * @param rhs the other complex number.
      * @return the complex number difference.
      */

Modified: jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/ComplexUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/ComplexUtils.java?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/ComplexUtils.java (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/src/java/org/apache/commons/math/complex/ComplexUtils.java Wed Nov 23 09:43:57 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 The Apache Software Foundation.
+ * Copyright 2003-2005 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,14 +19,20 @@
 import org.apache.commons.math.util.MathUtils;
 
 /**
- * Implementations of various transcendental functions for
- * {@link org.apache.commons.math.complex.Complex} arguments.
- *
+ * Static implementations of common 
+ * {@link org.apache.commons.math.complex.Complex}-valued functions.  Included
+ * are trigonometric, exponential, log, power and square root functions.
+ *<p>
  * Reference:
  * <ul>
  * <li><a href="http://myweb.lmu.edu/dmsmith/ZMLIB.pdf">
  * Multiple Precision Complex Arithmetic and Functions</a></li>
  * </ul>
+ * See individual method javadocs for the computational formulas used.
+ * In general, NaN values in either real or imaginary parts of input arguments
+ * result in {@link Complex#NaN} returned.  Otherwise, infinite or NaN values
+ * are returned as they arise in computing the real functions specified in the
+ * computational formulas.  Null arguments result in NullPointerExceptions.
  *
  * @version $Revision$ $Date$
  */
@@ -42,6 +48,15 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/InverseCosine.html">
      * inverse cosine</a> for the given complex argument.
+     * <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.
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose inverse cosine is to be returned.
      * @return the inverse cosine of <code>z</code>.
      */
@@ -57,6 +72,15 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/InverseSine.html">
      * inverse sine</a> for the given complex argument.
+     * <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.
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose inverse sine is to be returned.
      * @return the inverse sine of <code>z</code>.
      */
@@ -72,6 +96,15 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/InverseTangent.html">
      * inverse tangent</a> for the given complex argument.
+     * <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.
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose inverse tangent is to be returned.
      * @return the inverse tangent of <code>z</code>.
      */
@@ -80,7 +113,6 @@
             return Complex.NaN;
         }
         
-        
         return Complex.I.multiply(
             log(Complex.I.add(z).divide(Complex.I.subtract(z))))
             .divide(new Complex(2.0, 0.0));
@@ -89,6 +121,26 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/Cosine.html">cosine</a>
      * for the given complex argument.
+     * <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>
+     * 
+     * Throws <code>NullPointerException</code> if z is null. 
+     * 
      * @param z the value whose cosine is to be returned.
      * @return the cosine of <code>z</code>.
      */
@@ -107,6 +159,26 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/HyperbolicCosine.html">
      * hyperbolic cosine</a> for the given complex argument.
+     * <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>
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose hyperbolic cosine is to be returned.
      * @return the hyperbolic cosine of <code>z</code>.
      */
@@ -126,6 +198,27 @@
      * Compute the
      * <a href="http://mathworld.wolfram.com/ExponentialFunction.html">
      * exponential function</a> for the given complex argument.
+     * <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>
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value.
      * @return <i>e</i><sup><code>z</code></sup>.
      */
@@ -136,14 +229,34 @@
         
         double b = z.getImaginary();
         double expA = Math.exp(z.getReal());
-        double sinB = Math.sin(b);
-        double cosB = Math.cos(b);
-        return new Complex(expA * cosB, expA * sinB);
+        return new Complex(expA *  Math.cos(b), expA * Math.sin(b));
     }
     
     /**
      * Compute the <a href="http://mathworld.wolfram.com/NaturalLogarithm.html">
      * natural logarithm</a> for the given complex argument.
+     * <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 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
+     * </code></pre>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value.
      * @return ln <code>z</code>.
      */
@@ -156,12 +269,56 @@
             Math.atan2(z.getImaginary(), z.getReal()));        
     }
     
+    /**
+     * Creates a complex number from the given polar representation.
+     * <p>
+     * The value returned is <code>r&middot;e<sup>i&middot;theta</sup></code>, computed as
+     * <code>r&middot;cos(theta) + r&middot;sin(theta)i</code>
+     * <p>
+     * If either <code>r</code> or <code>theta</code> is NaN, or 
+     * <code>theta</code> is infinite, {@link Complex#NaN} is returned.
+     * <p>
+     * If <code>r</code> is infinite and <code>theta</code> is finite, 
+     * infinite or NaN values may be returned in parts of the result, following
+     * the rules for double arithmetic.<pre>
+     * Examples: 
+     * <code>
+     * polar2Complex(INFINITY, &pi;/4) = INFINITY + INFINITY i
+     * polar2Complex(INFINITY, 0) = INFINITY + NaN i
+     * polar2Complex(INFINITY, -&pi;/4) = INFINITY - INFINITY i
+     * polar2Complex(INFINITY, 5&pi;/4) = -INFINITY - INFINITY i </code></pre>
+     * 
+     * Throws <code>IllegalArgumentException</code> if <code>r < 0</code>
+     * 
+     * @param r the modulus of the complex number to create
+     * @param theta  the argument of the complex number to create
+     * @return <code>r&middot;e<sup>i&middot;theta</sup></code>
+     * @throws IllegalArgumentException  if r is negative
+     */
+    public static Complex polar2Complex(double r, double theta) {
+        if (r < 0) {
+            throw new IllegalArgumentException
+                ("Complex modulus must not be negative");
+        }
+        return new Complex(r * Math.cos(theta), r * Math.sin(theta));
+    }
     
     /**
      * Returns of value of <code>y</code> 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.
+     * <p>
+     * Throws <code>NullPointerException</code> if either x or y is null.
+     * 
      * @param y the base.
      * @param x the exponent.
-     * @return <code>y</code><sup><code>z</code></sup>.
+     * @return <code>y</code><sup><code>x</code></sup>
      */
     public static Complex pow(Complex y, Complex x) {
         return exp(x.multiply(log(y)));
@@ -170,6 +327,26 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/Sine.html">sine</a>
      * for the given complex argument.
+     * <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>
+     * 
+     * Throws <code>NullPointerException</code> if z is null. 
+     * 
      * @param z the value whose sine is to be returned.
      * @return the sine of <code>z</code>.
      */
@@ -188,6 +365,26 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/HyperbolicSine.html">
      * hyperbolic sine</a> for the given complex argument.
+     * <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>
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose hyperbolic sine is to be returned.
      * @return the hyperbolic sine of <code>z</code>.
      */
@@ -204,8 +401,36 @@
     }
     
     /**
-     * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">squre
+     * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">square
      * root</a> for the given complex argument.
+     * <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>
+     * 
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose square root is to be returned.
      * @return the square root of <code>z</code>.
      */
@@ -221,14 +446,26 @@
         if (a >= 0.0) {
             return new Complex(t, b / (2.0 * t));
         } else {
-            return new Complex(Math.abs(z.getImaginary()) / (2.0 * t),
+            return new Complex(Math.abs(b) / (2.0 * t),
                 MathUtils.indicator(b) * t);
         }
     }
     
     /**
-     * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">squre
-     * root of 1 - <code>z</code><sup>2</sup> for the given complex argument.
+     * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">square
+     * root</a> of 1 - <code>z</code><sup>2</sup> for the given complex argument.
+     * <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. 
+     * <p>
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value.
      * @return the square root of 1 - <code>z</code><sup>2</sup>.
      */
@@ -239,6 +476,26 @@
     /**
      * Compute the <a href="http://mathworld.wolfram.com/Tangent.html">
      * tangent</a> for the given complex argument.
+     * <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 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</code></pre>
+     * 
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose tangent is to be returned.
      * @return the tangent of <code>z</code>.
      */
@@ -258,6 +515,26 @@
      * Compute the
      * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html">
      * hyperbolic tangent</a> for the given complex argument.
+    * <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>
+     * tan(1 &plusmn; INFINITY i) = NaN + NaN i
+     * tan(&plusmn;INFINITY + i) = NaN + 0 i
+     * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
+     * 
+     * Throws <code>NullPointerException</code> if z is null.
+     * 
      * @param z the value whose hyperbolic tangent is to be returned.
      * @return the hyperbolic tangent of <code>z</code>.
      */

Modified: jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/TestUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/TestUtils.java?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/TestUtils.java (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/TestUtils.java Wed Nov 23 09:43:57 2005
@@ -42,6 +42,10 @@
         assertEquals(null, expected, actual, delta);
     }
 
+    /**
+     * Verifies that expected and actual are within delta, or are both NaN or
+     * infinities of the same sign.
+     */
     public static void assertEquals(String msg, double expected, double actual, double delta) {
         // check for NaN
         if(Double.isNaN(expected)){
@@ -52,8 +56,26 @@
         }
     }
     
+    /*
+     * Verifies that the two arguments are exactly the same, either
+     * both NaN or infinities of same sign, or identical floating point values.
+     */
+    public static void assertSame(double expected, double actual) {
+     assertEquals(expected, actual, 0);
+    }
+    
+    /**
+     * Verifies that real and imaginary parts of the two complex arguments
+     * are exactly the same.  Also ensures that NaN / infinite components match.
+     */
+    public static void assertSame(Complex expected, Complex actual) {
+        assertSame(expected.getReal(), actual.getReal());
+        assertSame(expected.getImaginary(), actual.getImaginary());
+    }
+    
     /**
-     * 
+     * Verifies that real and imaginary parts of the two complex arguments
+     * differ by at most delta.  Also ensures that NaN / infinite components match.
      */
     public static void assertEquals(Complex expected, Complex actual, double delta) {
         assertEquals(expected.getReal(), actual.getReal(), delta);

Modified: jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/complex/ComplexUtilsTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/complex/ComplexUtilsTest.java?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/complex/ComplexUtilsTest.java (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/src/test/org/apache/commons/math/complex/ComplexUtilsTest.java Wed Nov 23 09:43:57 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 The Apache Software Foundation.
+ * Copyright 2003-2005 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,16 +25,63 @@
  */
 public class ComplexUtilsTest extends TestCase {
     
+    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 negInfOne = new Complex(negInf, 1);
+    private Complex negInfInf = new Complex(negInf, inf);
+    private Complex infNegInf = new Complex(inf, negInf);
+    private Complex infInf = new Complex(inf, inf);
+    private Complex negInfNegInf = new Complex(negInf, negInf);
+    private Complex oneNaN = new Complex(1, nan);
+    private Complex infNaN = new Complex(inf, nan);
+    private Complex negInfNaN = new Complex(negInf, nan);
+    private Complex nanInf = new Complex(nan, inf);
+    private Complex nanNegInf = new Complex(nan, negInf);
+    private Complex zeroNaN = new Complex(0, nan);
+    private Complex nanZero = new Complex(nan, 0);
+    private Complex infZero = new Complex(inf, 0);
+    private Complex zeroInf = new Complex(0, inf);
+    
+    private ComplexFormat fmt = new ComplexFormat();
+    
     public void testAcos() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(0.936812, -2.30551);
         TestUtils.assertEquals(expected, ComplexUtils.acos(z), 1.0e-5);
+        TestUtils.assertEquals(new Complex(Math.acos(0), 0), 
+                ComplexUtils.acos(Complex.ZERO), 1.0e-12);
+    }
+    
+    public void testAcosInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.acos(negInfNegInf));
     }
     
     public void testAcosNaN() {
         assertTrue(ComplexUtils.acos(Complex.NaN).isNaN());
     }
     
+    public void testAcosNull() {
+        try {
+            Complex z = ComplexUtils.acos(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
     public void testAsin() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(0.633984, 2.30551);
@@ -45,14 +92,55 @@
         assertTrue(ComplexUtils.asin(Complex.NaN).isNaN());
     }
     
+    public void testAsinInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.asin(negInfNegInf));
+    }
+    
+    public void testAsinNull() {
+        try {
+            Complex z = ComplexUtils.asin(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
     public void testAtan() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(1.44831, 0.158997);
         TestUtils.assertEquals(expected, ComplexUtils.atan(z), 1.0e-5);
     }
     
+    public void testAtanInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.atan(negInfNegInf));
+    } 
+    
     public void testAtanNaN() {
         assertTrue(ComplexUtils.atan(Complex.NaN).isNaN());
+        assertTrue(ComplexUtils.atan(Complex.I).isNaN());
+    }
+    
+    public void testAtanNull() {
+        try {
+            Complex z = ComplexUtils.atan(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
     }
     
     public void testCos() {
@@ -61,6 +149,30 @@
         TestUtils.assertEquals(expected, ComplexUtils.cos(z), 1.0e-5);
     }
     
+    public void testCosNaN() {
+        assertTrue(ComplexUtils.cos(Complex.NaN).isNaN());
+    }
+    
+    public void testCosInf() {
+        TestUtils.assertSame(infNegInf, ComplexUtils.cos(oneInf));
+        TestUtils.assertSame(infInf, ComplexUtils.cos(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cos(negInfNegInf));
+    } 
+    
+    public void testCosNull() {
+        try {
+            Complex z = ComplexUtils.cos(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
     public void testCosh() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(-6.58066, -7.58155);
@@ -71,8 +183,24 @@
         assertTrue(ComplexUtils.cosh(Complex.NaN).isNaN());
     }
     
-    public void testCosNaN() {
-        assertTrue(ComplexUtils.cos(Complex.NaN).isNaN());
+    public void testCoshInf() {  
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(oneNegInf));
+        TestUtils.assertSame(infInf, ComplexUtils.cosh(infOne));
+        TestUtils.assertSame(infNegInf, ComplexUtils.cosh(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.cosh(negInfNegInf));
+    } 
+    
+    public void testCoshNull() {
+        try {
+            Complex z = ComplexUtils.cosh(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
     }
     
     public void testExp() {
@@ -85,6 +213,26 @@
         assertTrue(ComplexUtils.exp(Complex.NaN).isNaN());
     }
     
+    public void testExpInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(oneNegInf));
+        TestUtils.assertSame(infInf, ComplexUtils.exp(infOne));
+        TestUtils.assertSame(Complex.ZERO, ComplexUtils.exp(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.exp(negInfNegInf));
+    }
+    
+    public void testExpNull() {
+        try {
+            Complex z = ComplexUtils.exp(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
     public void testLog() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(1.60944, 0.927295);
@@ -95,6 +243,97 @@
         assertTrue(ComplexUtils.log(Complex.NaN).isNaN());
     }
     
+    public void testLogInf() {
+        TestUtils.assertEquals(new Complex(inf, pi / 2),
+                ComplexUtils.log(oneInf), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, -pi / 2),
+                ComplexUtils.log(oneNegInf), 10e-12);
+        TestUtils.assertEquals(infZero, ComplexUtils.log(infOne), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, pi),
+                ComplexUtils.log(negInfOne), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, pi / 4),
+                ComplexUtils.log(infInf), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, -pi / 4),
+                ComplexUtils.log(infNegInf), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, 3d * pi / 4),
+                ComplexUtils.log(negInfInf), 10e-12);
+        TestUtils.assertEquals(new Complex(inf, - 3d * pi / 4),
+                ComplexUtils.log(negInfNegInf), 10e-12);
+    }
+    
+    public void testlogNull() {
+        try {
+            Complex z = ComplexUtils.log(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
+    public void testPolar2Complex() {
+        TestUtils.assertEquals(Complex.ONE, 
+                ComplexUtils.polar2Complex(1, 0), 10e-12);
+        TestUtils.assertEquals(Complex.ZERO, 
+                ComplexUtils.polar2Complex(0, 1), 10e-12);
+        TestUtils.assertEquals(Complex.ZERO, 
+                ComplexUtils.polar2Complex(0, -1), 10e-12);
+        TestUtils.assertEquals(Complex.I, 
+                ComplexUtils.polar2Complex(1, pi/2), 10e-12);
+        TestUtils.assertEquals(Complex.I.negate(), 
+                ComplexUtils.polar2Complex(1, -pi/2), 10e-12);
+        double r = 0;
+        for (int i = 0; i < 5; i++) {
+          r += i;
+          double theta = 0;
+          for (int j =0; j < 20; j++) {
+              theta += pi / 6;
+              TestUtils.assertEquals(altPolar(r, theta), 
+                      ComplexUtils.polar2Complex(r, theta), 10e-12);
+          }
+          theta = -2 * pi;
+          for (int j =0; j < 20; j++) {
+              theta -= pi / 6;
+              TestUtils.assertEquals(altPolar(r, theta), 
+                      ComplexUtils.polar2Complex(r, theta), 10e-12);
+          }
+        }   
+    }
+    
+    protected Complex altPolar(double r, double theta) {
+        return ComplexUtils.exp(Complex.I.multiply
+                (new Complex(theta, 0))).multiply(new Complex(r, 0));
+    }
+    
+    public void testPolar2ComplexIllegalModulus() {
+        try {
+            Complex z = ComplexUtils.polar2Complex(-1, 0);
+            fail("Expecting IllegalArgumentException");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }       
+    }
+    
+    public void testPolar2ComplexNaN() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.polar2Complex(nan, 1));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.polar2Complex(1, nan));
+        TestUtils.assertSame(Complex.NaN, 
+                ComplexUtils.polar2Complex(nan, nan));     
+    }
+    
+    public void testPolar2ComplexInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.polar2Complex(1, inf));
+        TestUtils.assertSame(Complex.NaN,
+                ComplexUtils.polar2Complex(1, negInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.polar2Complex(inf, inf));
+        TestUtils.assertSame(Complex.NaN,
+                ComplexUtils.polar2Complex(inf, negInf));
+        TestUtils.assertSame(infInf, ComplexUtils.polar2Complex(inf, pi/4));
+        TestUtils.assertSame(infNaN, ComplexUtils.polar2Complex(inf, 0));
+        TestUtils.assertSame(infNegInf, ComplexUtils.polar2Complex(inf, -pi/4));
+        TestUtils.assertSame(negInfInf, ComplexUtils.polar2Complex(inf, 3*pi/4));
+        TestUtils.assertSame(negInfNegInf, ComplexUtils.polar2Complex(inf, 5*pi/4));
+    }
+    
     public void testPow() {
         Complex x = new Complex(3, 4);
         Complex y = new Complex(5, 6);
@@ -112,12 +351,76 @@
         assertTrue(ComplexUtils.pow(x, Complex.NaN).isNaN());
     }
     
+   public void testPowInf() {
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, oneInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, oneNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, infOne));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, infInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, infNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, negInfInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(Complex.ONE, negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infOne, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfOne, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infInf, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infNegInf, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfInf, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfNegInf, Complex.ONE));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfNegInf, infNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfNegInf, negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(negInfNegInf, infInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infInf, infNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infInf, negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infInf, infInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infNegInf, infNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infNegInf, negInfNegInf));
+       TestUtils.assertSame(Complex.NaN,ComplexUtils.pow(infNegInf, infInf));   
+   }
+    
+    public void testpowNull() {
+        try {
+            Complex z = ComplexUtils.pow(null, Complex.ONE); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+        try {
+            Complex z = ComplexUtils.pow(Complex.ONE, 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, ComplexUtils.sin(z), 1.0e-5);
     }
     
+    public void testSinInf() {
+        TestUtils.assertSame(infInf, ComplexUtils.sin(oneInf));
+        TestUtils.assertSame(infNegInf, ComplexUtils.sin(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sin(negInfNegInf));
+    }
+    
+    public void testSinNaN() {
+        assertTrue(ComplexUtils.sin(Complex.NaN).isNaN());
+    }
+    
+    public void testSinNull() {
+        try {
+            Complex z = ComplexUtils.sin(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+     
     public void testSinh() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(-6.54812, -7.61923);
@@ -128,8 +431,24 @@
         assertTrue(ComplexUtils.sinh(Complex.NaN).isNaN());
     }
     
-    public void testSinNaN() {
-        assertTrue(ComplexUtils.sin(Complex.NaN).isNaN());
+    public void testSinhInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(oneNegInf));
+        TestUtils.assertSame(infInf, ComplexUtils.sinh(infOne));
+        TestUtils.assertSame(negInfInf, ComplexUtils.sinh(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.sinh(negInfNegInf));
+    }
+    
+    public void testsinhNull() {
+        try {
+            Complex z = ComplexUtils.sinh(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
     }
     
     public void testSqrtRealPositive() {
@@ -161,6 +480,44 @@
         Complex expected = new Complex(1.0, -2.0);
         TestUtils.assertEquals(expected, ComplexUtils.sqrt(z), 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, ComplexUtils.sqrt(z), 10e-12);
+            }
+        }       
+    }
+    
+    public void testSqrtNaN() {
+        assertTrue(ComplexUtils.sqrt(Complex.NaN).isNaN());
+    }
+      
+    public void testSqrtInf() {
+        TestUtils.assertSame(infNaN, ComplexUtils.sqrt(oneInf));
+        TestUtils.assertSame(infNaN, ComplexUtils.sqrt(oneNegInf));
+        TestUtils.assertSame(infZero, ComplexUtils.sqrt(infOne));
+        TestUtils.assertSame(zeroInf, ComplexUtils.sqrt(negInfOne));
+        TestUtils.assertSame(infNaN, ComplexUtils.sqrt(infInf));
+        TestUtils.assertSame(infNaN, ComplexUtils.sqrt(infNegInf));
+        TestUtils.assertSame(nanInf, ComplexUtils.sqrt(negInfInf));
+        TestUtils.assertSame(nanNegInf, ComplexUtils.sqrt(negInfNegInf));
+    }
+    
+    public void testSqrtNull() {
+        try {
+            Complex z = ComplexUtils.sqrt(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
 
     public void testSqrt1z() {
         Complex z = new Complex(3, 4);
@@ -172,8 +529,13 @@
         assertTrue(ComplexUtils.sqrt1z(Complex.NaN).isNaN());
     }
     
-    public void testSqrtNaN() {
-        assertTrue(ComplexUtils.sqrt(Complex.NaN).isNaN());
+    public void testSqrt1zNull() {
+        try {
+            Complex z = ComplexUtils.sqrt1z(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
     }
     
     public void testTan() {
@@ -182,6 +544,30 @@
         TestUtils.assertEquals(expected, ComplexUtils.tan(z), 1.0e-5);
     }
     
+    public void testTanNaN() {
+        assertTrue(ComplexUtils.tan(Complex.NaN).isNaN());
+    }
+    
+    public void testTanInf() {
+        TestUtils.assertSame(zeroNaN, ComplexUtils.tan(oneInf));
+        TestUtils.assertSame(zeroNaN, ComplexUtils.tan(oneNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(infOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tan(negInfNegInf));
+    }
+    
+    public void testTanNull() {
+        try {
+            Complex z = ComplexUtils.tan(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
+    }
+    
     public void testTanh() {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(1.00071, 0.00490826);
@@ -192,7 +578,23 @@
         assertTrue(ComplexUtils.tanh(Complex.NaN).isNaN());
     }
     
-    public void testTanNaN() {
-        assertTrue(ComplexUtils.tan(Complex.NaN).isNaN());
+    public void testTanhInf() {
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(oneInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(oneNegInf));
+        TestUtils.assertSame(nanZero, ComplexUtils.tanh(infOne));
+        TestUtils.assertSame(nanZero, ComplexUtils.tanh(negInfOne));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(infInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(infNegInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(negInfInf));
+        TestUtils.assertSame(Complex.NaN, ComplexUtils.tanh(negInfNegInf));
+    }
+    
+    public void testTanhNull() {
+        try {
+            Complex z = ComplexUtils.tanh(null); 
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // expected
+        }
     }
 }

Modified: jakarta/commons/proper/math/branches/MATH_1_1/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/xdocs/changes.xml?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/xdocs/changes.xml (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/xdocs/changes.xml Wed Nov 23 09:43:57 2005
@@ -38,13 +38,21 @@
 Commons Math Release Notes</title>
   </properties>
   <body>
-    <release version="1.1-RC3" date="TBD"  
+    <release version="1.1-RC4" date="TBD"  
  description="This is a maintenance release containing bug fixes and enhancements.
        All API changes are binary compatible with version 1.0. The enhancements 
        include some new probability distributions, a Fraction class, new matrix
        and numerical utilities, and a PRNG pluggability framework making it
        possible to replace the JDK-supplied random number generator in
        commons-math (and elsewhere) with alternative PRNG implementations.">
+      <action dev="psteitz" type="update">
+        Added polar2Complex method to ComplexUtils to create Complex numbers
+        from polar representations.
+      </action>
+      <action dev="psteitz" type="fix" issue="37086">
+        Improved documentation and test cases related to handling of infinite
+        and NaN values in Complex, ComplexUtils classes. 
+      </action> 
       <action dev="psteitz" type="fix" issue="37019" due-to="Mauro Talevi">
         Fixed incorrect NaN handling in o.a.m.s.d.rank.Min, Max
       </action>

Modified: jakarta/commons/proper/math/branches/MATH_1_1/xdocs/userguide/complex.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/math/branches/MATH_1_1/xdocs/userguide/complex.xml?rev=348502&r1=348501&r2=348502&view=diff
==============================================================================
--- jakarta/commons/proper/math/branches/MATH_1_1/xdocs/userguide/complex.xml (original)
+++ jakarta/commons/proper/math/branches/MATH_1_1/xdocs/userguide/complex.xml Wed Nov 23 09:43:57 2005
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 
 <!--
-   Copyright 2003-2004 The Apache Software Foundation
+   Copyright 2003-2005 The Apache Software Foundation
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
 <!-- $Revision$ $Date$ -->
 <document url="stat.html">
   <properties>
-    <title>The Commons Math User Guide - Statistics</title>
+    <title>The Commons Math User Guide - Complex Numbers</title>
   </properties>
   <body>
     <section name="7 Complex Numbers">
@@ -37,6 +37,18 @@
           org.apache.commons.math.complex.Complex</a> provides a complex number
           type that forms the basis for the complex functionality found in 
           commons-math.
+         </p>  
+         <p>
+           Complex functions and arithmetic operations are implemented in
+           commons-math by applying standard computational formulas and
+           following the rules for <code>java.lang.Double</code> arithmetic in 
+           handling infinite and <code>NaN</code> values.  No attempt is made
+           to comply with ANSII/IEC C99x Annex G or any other standard for
+           Complex arithmetic.  See the class and method javadocs for the 
+           <a href="../apidocs/org/apache/commons/math/complex/Complex.html">
+           Complex</a> and
+           <a href="../apidocs/org/apache/commons/math/complex/ComplexUtils.html">
+           ComplexUtils</a> classes for details on computing formulas.
         </p>
         <p>
           To create a complex number, simply call the constructor passing in two
@@ -45,9 +57,14 @@
           <source>Complex c = new Complex(1.0, 3.0); // 1 + 3i</source>
         </p>
         <p>
-          The <code>Complex</code> class provides many unary and binary
+          Complex numbers may also be created from polar representations
+          using the <code>polar2Complex</code> method in 
+          <code>ComplexUtils</code>.
+        </p>
+        <p>
+          The <code>Complex</code> class provides basic unary and binary
           complex number operations.  These operations provide the means to add,
-          subtract, multiple and, divide complex numbers along with other
+          subtract, multiply and divide complex numbers along with other
           complex number functions similar to the real number functions found in
           <code>java.math.BigDecimal</code>:
           <source>Complex lhs = new Complex(1.0, 3.0);
@@ -62,7 +79,7 @@
       <subsection name="7.3 Complex Transcendental Functions" href="function">
         <p>
           <a href="../apidocs/org/apache/commons/math/complex/ComplexUtils.html">
-          org.apache.commons.math.complex.ComplexMath</a> provides
+          org.apache.commons.math.complex.ComplexUtils</a> provides
           implementations of serveral transcendental functions involving complex
           number arguments.  These operations provide the means to compute the
           log, sine, tangent and, other complex values similar to the real



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org