commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aherb...@apache.org
Subject [commons-numbers] 02/03: Map the Complex to a positive domain to preserve oddness.
Date Thu, 05 Dec 2019 02:31:54 GMT
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 <aherbert@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.


Mime
View raw message