You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2019/12/04 21:53:55 UTC

[commons-numbers] 05/06: [NUMBERS-78] Increase edge case coverage of atanh.

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git

commit d258522e2ec93b06f120fe66e3b8837afb8389b2
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Wed Dec 4 21:43:32 2019 +0000

    [NUMBERS-78] Increase edge case coverage of atanh.
    
    Requires implementation of subtractFromReal to negate the sign of the
    imaginary zero when subtracting from 0 imaginary.
---
 .../org/apache/commons/numbers/complex/Complex.java    | 18 +++++++++++++++++-
 .../apache/commons/numbers/complex/ComplexTest.java    |  9 +++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
index fc80ecb..b14ff97 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
@@ -858,6 +858,22 @@ public final class Complex implements Serializable  {
 
     /**
      * Returns a {@code Complex} whose value is
+     * {@code (minuend - this)}.
+     * Uses the definitional formula
+     * <p>
+     *  {@code a - (c + di) = (a-c) -di}
+     * </p>
+     *
+     * @param  minuend value that this {@code Complex} is to be subtracted from.
+     * @return {@code minuend - this}.
+     */
+    private Complex subtractFromReal(double minuend) {
+        return new Complex(minuend - real,
+                           -imaginary);
+    }
+
+    /**
+     * Returns a {@code Complex} whose value is
      * {@code (this - subtrahend)}.
      *
      * @param  subtrahend value to be subtracted from this {@code Complex}.
@@ -1080,7 +1096,7 @@ public final class Complex implements Serializable  {
                 // ISO C99: Preserve the equality
                 // atanh(conj(z)) = conj(atanh(z))
                 final Complex z = negative(imaginary) ? conjugate() : this;
-                final Complex result = z.add(ONE).divide(ONE.subtract(z)).log().multiply(0.5);
+                final Complex result = z.add(1).divide(z.subtractFromReal(1)).log().multiply(0.5);
                 return z == this ? result : result.conjugate();
             }
             if (Double.isInfinite(imaginary)) {
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
index 78c61d7..977553b 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
@@ -1299,4 +1299,13 @@ public class ComplexTest {
         TestUtils.assertEquals(Complex.ONE, Complex.ofCartesian(0, 25).tan(), 0);
         TestUtils.assertEquals(Complex.ofCartesian(0, -1), Complex.ofCartesian(0, -25).tan(), 0);
     }
+
+    @Test
+    public void testAtanhEdgeConditions() {
+        // Hits the edge case when imaginary == 0 but real != 0 or 1
+        final Complex c = Complex.ofCartesian(2, 0).atanh();
+        // Answer from g++
+        Assertions.assertEquals(0.54930614433405489, c.getReal());
+        Assertions.assertEquals(1.5707963267948966, c.getImaginary());
+    }
 }