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/05 02:31:52 UTC

[commons-numbers] branch master updated (4cb87cf -> e0d38c8)

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

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


    from 4cb87cf  Removed "ComplexParsingException".
     new 8950a68  Remove odd/even edge cases.
     new 7ec50bb  Map the Complex to a positive domain to preserve oddness.
     new e0d38c8  Added notes about testing odd/even functions.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/commons/numbers/complex/Complex.java    | 51 ++++++++++++++++++++--
 .../commons/numbers/complex/CStandardTest.java     | 25 ++++++-----
 2 files changed, 61 insertions(+), 15 deletions(-)


[commons-numbers] 01/03: Remove odd/even edge cases.

Posted by ah...@apache.org.
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 8950a68339b4d96172a53a736ba422cff5a09e98
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Thu Dec 5 01:43:09 2019 +0000

    Remove odd/even edge cases.
    
    The C99 reference states that the sign of the parts is undefined for
    some edge cases. These should be tested separately.
    
    Fix testCosh for cis check using the even property of the function and
    the conjugate equality.
---
 .../commons/numbers/complex/CStandardTest.java      | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
index 4bbb80b..141448f 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
@@ -200,8 +200,9 @@ public class CStandardTest {
      */
     private static void assertOddOrEven(UnaryOperator<Complex> operation, boolean odd) {
         // Edge cases
-        final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1,
-                                Double.POSITIVE_INFINITY, Double.NaN};
+        //final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1,
+        //                        Double.POSITIVE_INFINITY, Double.NaN};
+        final double[] parts = {-2, -1, -0.0, 0.0, 1, 2};
         for (final double x : parts) {
             for (final double y : parts) {
                 assertOddOrEven(x, y, operation, odd);
@@ -244,6 +245,10 @@ public class CStandardTest {
             c2 = c2.negate();
         }
 
+        // Note: It is not possible to satisfy the conjugate equality
+        // and be an even function with regard to zero.
+        
+        
         // Test for binary equality
         if (!equals(c1.getReal(), c2.getReal()) ||
             !equals(c1.getImaginary(), c2.getImaginary())) {
@@ -616,7 +621,7 @@ public class CStandardTest {
     @Test
     public void testAsinh() {
         assertConjugateEquality(Complex::asinh);
-        //assertOddOrEven(Complex::asinh, ODD);
+        assertOddOrEven(Complex::asinh, ODD);
         assertComplex(Complex.ZERO, Complex::asinh, Complex.ZERO);
         assertComplex(negZeroZero, Complex::asinh, negZeroZero);
         assertComplex(zeroNaN, Complex::asinh, NAN);
@@ -642,7 +647,7 @@ public class CStandardTest {
     @Test
     public void testAtanh() {
         assertConjugateEquality(Complex::atanh);
-        //assertOddOrEven(Complex::atanh, ODD);
+        assertOddOrEven(Complex::atanh, ODD);
         assertComplex(Complex.ZERO, Complex::atanh, Complex.ZERO);
         assertComplex(negZeroZero, Complex::atanh, negZeroZero);
         assertComplex(zeroNaN, Complex::atanh, zeroNaN);
@@ -669,7 +674,7 @@ public class CStandardTest {
     @Test
     public void testCosh() {
         assertConjugateEquality(Complex::cosh);
-        //assertOddOrEven(Complex::cosh, EVEN);
+        assertOddOrEven(Complex::cosh, EVEN);
         assertComplex(Complex.ZERO, Complex::cosh, Complex.ONE);
         assertComplex(negZeroZero, Complex::cosh, oneNegZero);
         assertComplex(zeroInf, Complex::cosh, nanZero);
@@ -688,9 +693,9 @@ public class CStandardTest {
         for (int i = 1; i < 10; i++) {
             final double y = i * 0.5;
             assertComplex(complex(inf, y), Complex::cosh, Complex.ofCis(y).multiply(inf));
+            assertComplex(complex(-inf, -y), Complex::cosh, Complex.ofCis(y).multiply(inf));
             assertComplex(complex(inf, -y), Complex::cosh, Complex.ofCis(-y).multiply(inf));
-            assertComplex(complex(-inf, y), Complex::cosh, Complex.ofCis(y).multiply(-inf));
-            assertComplex(complex(-inf, -y), Complex::cosh, Complex.ofCis(-y).multiply(-inf));
+            assertComplex(complex(-inf, y), Complex::cosh, Complex.ofCis(-y).multiply(inf));
         }
         assertComplex(negInfInf, Complex::cosh, infNaN);
         assertComplex(infInf, Complex::cosh, infNaN);
@@ -708,7 +713,7 @@ public class CStandardTest {
     @Test
     public void testSinh() {
         assertConjugateEquality(Complex::sinh);
-        //assertOddOrEven(Complex::sinh, ODD);
+        assertOddOrEven(Complex::sinh, ODD);
         assertComplex(Complex.ZERO, Complex::sinh, Complex.ZERO);
         assertComplex(negZeroZero, Complex::sinh, negZeroZero);
         assertComplex(zeroInf, Complex::sinh, zeroNaN);


[commons-numbers] 03/03: Added notes about testing odd/even functions.

Posted by ah...@apache.org.
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 e0d38c83f2b3dbcad4da0a659051ac506eba9edb
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Thu Dec 5 02:30:12 2019 +0000

    Added notes about testing odd/even functions.
---
 .../apache/commons/numbers/complex/CStandardTest.java    | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
index 141448f..5d0b51e 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/CStandardTest.java
@@ -199,9 +199,13 @@ public class CStandardTest {
      * @param odd true if odd
      */
     private static void assertOddOrEven(UnaryOperator<Complex> operation, boolean odd) {
-        // Edge cases
-        //final double[] parts = {Double.NEGATIVE_INFINITY, -1, -0.0, 0.0, 1,
-        //                        Double.POSITIVE_INFINITY, Double.NaN};
+        // Note: It may not be possible to satisfy the conjugate equality
+        // and be an odd/even function with regard to zero.
+        // The C99 standard allows for these cases to have unspecified sign.
+        // This test ignores parts that can result in unspecified signed results.
+        // The valid edge cases should be tested for each function separately.
+
+        // Edge cases around zero.
         final double[] parts = {-2, -1, -0.0, 0.0, 1, 2};
         for (final double x : parts) {
             for (final double y : parts) {
@@ -245,10 +249,6 @@ public class CStandardTest {
             c2 = c2.negate();
         }
 
-        // Note: It is not possible to satisfy the conjugate equality
-        // and be an even function with regard to zero.
-        
-        
         // Test for binary equality
         if (!equals(c1.getReal(), c2.getReal()) ||
             !equals(c1.getImaginary(), c2.getImaginary())) {
@@ -613,8 +613,6 @@ public class CStandardTest {
         assertComplex(NAN, Complex::acosh, NAN);
     }
 
-    // TODO: fix the 'IS ODD/ EVEN' specification
-
     /**
      * ISO C Standard G.6.2.2.
      */


[commons-numbers] 02/03: Map the Complex to a positive domain to preserve oddness.

Posted by ah...@apache.org.
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 7ec50bb2a9c37c9b136f48b0096fe3380fa6d610
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Thu Dec 5 02:27:35 2019 +0000

    Map the Complex to a positive domain to preserve oddness.
    
    This applies to asinh and atanh.
---
 .../apache/commons/numbers/complex/Complex.java    | 51 ++++++++++++++++++++--
 1 file changed, 47 insertions(+), 4 deletions(-)

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 ab48a20..cc3ef4c 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
@@ -20,6 +20,9 @@ package org.apache.commons.numbers.complex;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
 import org.apache.commons.numbers.core.Precision;
 
 /**
@@ -1040,9 +1043,12 @@ public final class Complex implements Serializable  {
                 }
                 // ISO C99: Preserve the equality
                 // asinh(conj(z)) = conj(asinh(z))
-                final Complex z = negative(imaginary) ? conjugate() : this;
+                // and the odd function: f(z) = -f(-z)
+                // by always computing on a positive valued Complex number.
+                final Function<Complex, Complex> fun = createPositiveDomainFunction();
+                final Complex z = fun.apply(this);
                 final Complex result = z.square().add(1).sqrt().add(z).log();
-                return z == this ? result : result.conjugate();
+                return fun.apply(result);
             }
             if (Double.isInfinite(imaginary)) {
                 return new Complex(Math.copySign(Double.POSITIVE_INFINITY, real), Math.copySign(PI_OVER_2, imaginary));
@@ -1097,9 +1103,12 @@ public final class Complex implements Serializable  {
                 }
                 // ISO C99: Preserve the equality
                 // atanh(conj(z)) = conj(atanh(z))
-                final Complex z = negative(imaginary) ? conjugate() : this;
+                // and the odd function: f(z) = -f(-z)
+                // by always computing on a positive valued Complex number.
+                final Function<Complex, Complex> fun = createPositiveDomainFunction();
+                final Complex z = fun.apply(this);
                 final Complex result = z.add(1).divide(z.subtractFromReal(1)).log().multiply(0.5);
-                return z == this ? result : result.conjugate();
+                return fun.apply(result);
             }
             if (Double.isInfinite(imaginary)) {
                 return new Complex(Math.copySign(0, real), Math.copySign(PI_OVER_2, imaginary));
@@ -1124,6 +1133,40 @@ public final class Complex implements Serializable  {
     }
 
     /**
+     * Creates a function to transform this Complex into a Complex with positive real and imaginary
+     * components. This is used to maintain the conjugate equality and the oddness of a function
+     * f(z) by always computing the result on positive valued input. Given:
+     *
+     * <pre>
+     * conj(f(z)) = f(conj(z))
+     * f(z) = -f(-z)
+     * </pre>
+     *
+     * <p>The Complex can be tranformed to the positve domain using the a combination of
+     * {@link #negate()} and/or {@link #conjugate()} functions, the function f(z) computed and
+     * the result transformed back using the same mapping function to the original domain.</p>
+     *
+     * <p>If the Complex is already in the correct domain then this returns an identify
+     * function.</p>
+     *
+     * @return the function
+     */
+    private Function<Complex, Complex> createPositiveDomainFunction() {
+        Function<Complex, Complex> fun;
+        if (negative(real)) {
+            fun = Complex::negate;
+            if (!negative(imaginary)) {
+                fun = fun.andThen(Complex::conjugate);
+            }
+        } else if (negative(imaginary)) {
+            fun = Complex::conjugate;
+        } else {
+            fun = UnaryOperator.identity();
+        }
+        return fun;
+    }
+
+    /**
      * Compute the
      * <a href="http://mathworld.wolfram.com/InverseHyperbolicCosine.html">
      * inverse hyperbolic cosine</a> of this complex number.