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/06 18:28:56 UTC

[commons-numbers] 02/19: Implement acosh using acos.

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 f8089850302b35ce9d61f90a215bcee57b3120ec
Author: aherbert <ah...@apache.org>
AuthorDate: Fri Dec 6 11:23:20 2019 +0000

    Implement acosh using acos.
---
 .../apache/commons/numbers/complex/Complex.java    | 55 +++++++---------------
 1 file changed, 18 insertions(+), 37 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 55cbab4..443b14a 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
@@ -1134,51 +1134,32 @@ public final class Complex implements Serializable  {
      * Compute the
      * <a href="http://mathworld.wolfram.com/InverseHyperbolicCosine.html">
      * inverse hyperbolic cosine</a> of this complex number.
-     * Implements the formula:
      * <pre>
-     *   acosh(z) = log(z+sqrt(z^2-1))
+     *   acosh(z) = ln(z + sqrt(z + 1) * sqrt(z - 1))
+     * </pre>
+     *
+     * <p>This function is computed using the trigonomic identity:</p>
+     * <pre>
+     *   acosh(z) = +-i acos(z)
      * </pre>
      *
+     * <p>The sign of the multiplier is chosen to give {@code z.acosh().real() >= 0}
+     * and compatibility with the C.99 standard.</p>
+     *
      * @return the inverse hyperbolic cosine of this complex number
      */
     public Complex acosh() {
-        if (Double.isFinite(real)) {
-            if (Double.isFinite(imaginary)) {
-                // Special case for zero
-                if (real == 0 && imaginary == 0) {
-                    return new Complex(real, Math.copySign(PI_OVER_2, imaginary));
-                }
-                // ISO C99: Preserve the equality
-                // acosh(conj(z)) = conj(acosh(z))
-                final UnaryOperator<Complex> g = mapImaginaryToPositiveDomain();
-                final Complex z = g.apply(this);
-                final Complex result = z.square().subtract(1).sqrt().add(z).log();
-                return g.apply(result);
-            }
-            if (Double.isInfinite(imaginary)) {
-                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(PI_OVER_2, imaginary));
-            }
-            // imaginary is NaN
+        // Define in terms of acos
+        // acosh(z) = +-i acos(z)
+        // Handle special case:
+        // acos(+-0 + iNaN) = π/2 + iNaN
+        // acosh(x + iNaN) = NaN + iNaN for all finite x (including zero)
+        if (Double.isNaN(imaginary) && Double.isFinite(real)) {
             return NAN;
         }
-        if (Double.isInfinite(real)) {
-            if (Double.isFinite(imaginary)) {
-                final double im = real == Double.NEGATIVE_INFINITY ? Math.PI : 0;
-                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(im, imaginary));
-            }
-            if (Double.isInfinite(imaginary)) {
-                final double im = real == Double.NEGATIVE_INFINITY ? PI_3_OVER_4 : PI_OVER_4;
-                return new Complex(Double.POSITIVE_INFINITY, Math.copySign(im, imaginary));
-            }
-            // imaginary is NaN
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-        }
-        // real is NaN
-        if (Double.isInfinite(imaginary)) {
-            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
-        }
-        // optionally raises the ‘‘invalid’’ floating-point exception, for finite y.
-        return NAN;
+        final Complex result = acos();
+        // Set the sign appropriately for C99 equalities.
+        return (negative(result.imaginary)) ? result.multiplyByI() : result.multiplyByNegI();
     }
 
     /**