diff --git a/src/main/java/org/apache/commons/math/complex/Complex.java b/src/main/java/org/apache/commons/math/complex/Complex.java index 3822a89e6..ed76a2950 100644 --- a/src/main/java/org/apache/commons/math/complex/Complex.java +++ b/src/main/java/org/apache/commons/math/complex/Complex.java @@ -993,8 +993,8 @@ public class Complex implements FieldElement, Serializable { * * * where the (real) functions on the right-hand side are - * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, - * {@link FastMath#cosh} and {@link FastMath#sinh}. + * {@link FastMath#sin}, {@link FastMath#cos}, {@link FastMath#cosh} and + * {@link FastMath#sinh}. *
* Returns {@link Complex#NaN} if either real or imaginary part of the * input argument is {@code NaN}. @@ -1004,8 +1004,8 @@ public class Complex implements FieldElement, Serializable { *
      *  Examples:
      *  
-     *   tan(1 ± INFINITY i) = 0 + NaN i
-     *   tan(±INFINITY + i) = NaN + NaN i
+     *   tan(a ± INFINITY i) = 0 ± i
+     *   tan(±INFINITY + bi) = NaN + NaN i
      *   tan(±INFINITY ± INFINITY i) = NaN + NaN i
      *   tan(±π/2 + 0 i) = ±INFINITY + NaN i
      *  
@@ -1015,9 +1015,15 @@ public class Complex implements FieldElement, Serializable  {
      * @since 1.2
      */
     public Complex tan() {
-        if (isNaN) {
+        if (isNaN || Double.isInfinite(real)) {
             return NaN;
         }
+        if (imaginary > 20.0) {
+            return createComplex(0.0, 1.0);
+        }
+        if (imaginary < -20.0) {
+            return createComplex(0.0, -1.0);
+        }
 
         double real2 = 2.0 * real;
         double imaginary2 = 2.0 * imaginary;
@@ -1038,8 +1044,8 @@ public class Complex implements FieldElement, Serializable  {
      *  
      * 
* where the (real) functions on the right-hand side are - * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, - * {@link FastMath#cosh} and {@link FastMath#sinh}. + * {@link FastMath#sin}, {@link FastMath#cos}, {@link FastMath#cosh} and + * {@link FastMath#sinh}. *
* Returns {@link Complex#NaN} if either real or imaginary part of the * input argument is {@code NaN}. @@ -1049,8 +1055,8 @@ public class Complex implements FieldElement, Serializable { *
      *  Examples:
      *  
-     *   tanh(1 ± INFINITY i) = NaN + NaN i
-     *   tanh(±INFINITY + i) = NaN + 0 i
+     *   tanh(a ± INFINITY i) = NaN + NaN i
+     *   tanh(±INFINITY + bi) = ±1 + 0 i
      *   tanh(±INFINITY ± INFINITY i) = NaN + NaN i
      *   tanh(0 + (π/2)i) = NaN + INFINITY i
      *  
@@ -1060,10 +1066,15 @@ public class Complex implements FieldElement, Serializable  {
      * @since 1.2
      */
     public Complex tanh() {
-        if (isNaN) {
+        if (isNaN || Double.isInfinite(imaginary)) {
             return NaN;
         }
-
+        if (real > 20.0) {
+            return createComplex(1.0, 0.0);
+        }
+        if (real < -20.0) {
+            return createComplex(-1.0, 0.0);
+        }
         double real2 = 2.0 * real;
         double imaginary2 = 2.0 * imaginary;
         double d = FastMath.cosh(real2) + FastMath.cos(imaginary2);
diff --git a/src/test/java/org/apache/commons/math/complex/ComplexTest.java b/src/test/java/org/apache/commons/math/complex/ComplexTest.java
index f694310fe..c31cb90f1 100644
--- a/src/test/java/org/apache/commons/math/complex/ComplexTest.java
+++ b/src/test/java/org/apache/commons/math/complex/ComplexTest.java
@@ -996,6 +996,13 @@ public class ComplexTest {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(-0.000187346, 0.999356);
         TestUtils.assertEquals(expected, z.tan(), 1.0e-5);
+        /* Check that no overflow occurs (MATH-722) */
+        Complex actual = new Complex(3.0, 1E10).tan();
+        expected = new Complex(0, 1);
+        TestUtils.assertEquals(expected, actual, 1.0e-5);
+        actual = new Complex(3.0, -1E10).tan();
+        expected = new Complex(0, -1);
+        TestUtils.assertEquals(expected, actual, 1.0e-5);
     }
 
     @Test
@@ -1005,8 +1012,8 @@ public class ComplexTest {
 
     @Test
     public void testTanInf() {
-        TestUtils.assertSame(zeroNaN, oneInf.tan());
-        TestUtils.assertSame(zeroNaN, oneNegInf.tan());
+        TestUtils.assertSame(Complex.valueOf(0.0, 1.0), oneInf.tan());
+        TestUtils.assertSame(Complex.valueOf(0.0, -1.0), oneNegInf.tan());
         TestUtils.assertSame(Complex.NaN, infOne.tan());
         TestUtils.assertSame(Complex.NaN, negInfOne.tan());
         TestUtils.assertSame(Complex.NaN, infInf.tan());
@@ -1026,6 +1033,13 @@ public class ComplexTest {
         Complex z = new Complex(3, 4);
         Complex expected = new Complex(1.00071, 0.00490826);
         TestUtils.assertEquals(expected, z.tanh(), 1.0e-5);
+        /* Check that no overflow occurs (MATH-722) */
+        Complex actual = new Complex(1E10, 3.0).tanh();
+        expected = new Complex(1, 0);
+        TestUtils.assertEquals(expected, actual, 1.0e-5);
+        actual = new Complex(-1E10, 3.0).tanh();
+        expected = new Complex(-1, 0);
+        TestUtils.assertEquals(expected, actual, 1.0e-5);
     }
 
     @Test
@@ -1037,8 +1051,8 @@ public class ComplexTest {
     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.valueOf(1.0, 0.0), infOne.tanh());
+        TestUtils.assertSame(Complex.valueOf(-1.0, 0.0), negInfOne.tanh());
         TestUtils.assertSame(Complex.NaN, infInf.tanh());
         TestUtils.assertSame(Complex.NaN, infNegInf.tanh());
         TestUtils.assertSame(Complex.NaN, negInfInf.tanh());