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/20 17:58:00 UTC

[commons-numbers] 09/30: Compute log() within a safe region without using the sqrt.

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 67dc19de65579b1a3335919e6459b8946d1fae75
Author: aherbert <ah...@apache.org>
AuthorDate: Thu Dec 19 16:49:25 2019 +0000

    Compute log() within a safe region without using the sqrt.
---
 .../java/org/apache/commons/numbers/complex/Complex.java     | 12 ++++++++++++
 1 file changed, 12 insertions(+)

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 7577ddf..11f468f 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
@@ -2097,6 +2097,18 @@ public final class Complex implements Serializable  {
     private Complex log(UnaryOperation log, double logOf2, ComplexConstructor constructor) {
         // All ISO C99 edge cases satisfied by the Math library.
         // Make computation overflow safe.
+
+        // Note:
+        // log(|a + b i|) = log(sqrt(a^2 + b^2)) = 0.5 * log(a^2 + b^2)
+        // If real and imaginary are with a safe region then omit the sqrt().
+        final double x = Math.abs(real);
+        final double y = Math.abs(imaginary);
+
+        // Use the safe region defined for atanh to avoid over/underflow for x^2
+        if ((x > SAFE_LOWER) && (x < SAFE_UPPER) && (y > SAFE_LOWER) && (y < SAFE_UPPER)) {
+            return constructor.create(0.5 * log.apply(x * x + y * y), arg());
+        }
+
         final double abs = abs();
         if (abs == Double.POSITIVE_INFINITY && isFinite()) {
             // Edge-case where the |a + b i| overflows.