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 ac893bf6b075c083fe306d7fb637de6e95edd0f2
Author: aherbert <[email protected]>
AuthorDate: Thu Dec 12 12:14:55 2019 +0000

    Optimise scaling during overflow of log()
---
 .../org/apache/commons/numbers/complex/Complex.java   | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 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 78e6241..1973990 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
@@ -65,6 +65,10 @@ public final class Complex implements Serializable  {
     private static final int TWO_ELEMENTS = 2;
     /** Mask an integer number to even by discarding the lowest bit. */
     private static final int MASK_INT_TO_EVEN = ~0x1;
+    /** Natural logarithm of 2 (ln(2)). */
+    private static final double LN_2 = Math.log(2);
+    /** Base 10 logarithm of 2 (log10(2)). */
+    private static final double LOG10_2 = Math.log10(2);
 
     /** Serializable version identifier. */
     private static final long serialVersionUID = 20180201L;
@@ -1344,7 +1348,7 @@ public final class Complex implements Serializable  {
                 final Complex result = divide(1 + a, b, 1 - a, -b);
                 // Compute the log:
                 // (re + im i) = (1/2) * ln((1 + z) / (1 - z))
-                return result.log(Math::log, (re, im) ->
+                return result.log(Math::log, LN_2, (re, im) ->
                    // Divide log() by 2 and map back to the correct sign
                    constructor.create(0.5 * changeSign(re, real),
                                       0.5 * changeSign(im, imaginary))
@@ -1596,7 +1600,7 @@ public final class Complex implements Serializable  {
      * @see #arg()
      */
     public Complex log() {
-        return log(Math::log, Complex::ofCartesian);
+        return log(Math::log, LN_2, Complex::ofCartesian);
     }
 
     /**
@@ -1614,7 +1618,7 @@ public final class Complex implements Serializable  {
      * @see #arg()
      */
     public Complex log10() {
-        return log(Math::log10, Complex::ofCartesian);
+        return log(Math::log10, LOG10_2, Complex::ofCartesian);
     }
 
     /**
@@ -1624,13 +1628,18 @@ public final class Complex implements Serializable  {
      *   log(a +  bi) = log(|a + b i|) + i arg(a + b i)
      * </pre>
      *
+     * <p>Warning: The argument {@code logOf2} must be equal to {@code log(2)} 
using the
+     * provided log function otherwise scaling using powers of 2 in the case 
of overflow
+     * will be incorrect. This is provided as an internal optimisation.
+     *
      * @param log Log function.
+     * @param logOf2 The log function applied to 2.
      * @param constructor Constructor for the returned complex.
      * @return the logarithm of {@code this}.
      * @see #abs()
      * @see #arg()
      */
-    private Complex log(UnaryOperation log, ComplexConstructor constructor) {
+    private Complex log(UnaryOperation log, double logOf2, ComplexConstructor 
constructor) {
         // All ISO C99 edge cases satisfied by the Math library.
         // Make computation overflow safe.
         final double abs = abs();
@@ -1648,7 +1657,7 @@ public final class Complex implements Serializable  {
             // Implement scaling using 2^-exponent
             final double absOs = Math.hypot(Math.scalb(real, -exponent), 
Math.scalb(imaginary, -exponent));
             // log(2^exponent) = ln2(2^exponent) * log(2)
-            return constructor.create(log.apply(absOs) + exponent * 
log.apply(2), arg());
+            return constructor.create(log.apply(absOs) + exponent * logOf2, 
arg());
         }
         return constructor.create(log.apply(abs), arg());
     }

Reply via email to