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 2020/04/03 10:12:29 UTC
[commons-numbers] 02/02: Complex hypot: use 54 as the exponent
difference to ignore overlap
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 f12139e8f6820679ab0b30d4f43e9d8e7ffa9603
Author: aherbert <ah...@apache.org>
AuthorDate: Fri Apr 3 11:12:22 2020 +0100
Complex hypot: use 54 as the exponent difference to ignore overlap
---
.../apache/commons/numbers/complex/Complex.java | 26 ++++++++++------------
1 file changed, 12 insertions(+), 14 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 1733ca3..56b891a 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
@@ -188,8 +188,8 @@ public final class Complex implements Serializable {
*/
private static final double EXP_M = Math.exp(SAFE_EXP);
- /** 60 shifted 20-bits to align with the exponent of the upper 32-bits of a double. */
- private static final int EXP_60 = 0x3c_00000;
+ /** 54 shifted 20-bits to align with the exponent of the upper 32-bits of a double. */
+ private static final int EXP_54 = 0x36_00000;
/** Represents an exponent of 500 in unbiased form shifted 20-bits to align with the upper 32-bits of a double. */
private static final int EXP_500 = 0x5f3_00000;
/** Represents an exponent of 1024 in unbiased form (infinite or nan)
@@ -3538,16 +3538,15 @@ public final class Complex implements Serializable {
// the implementations compute a different result.
//
// 3. An alteration is done here to add an 'else if' instead of a second
- // 'if' statement. Since the exponent difference between a and b
- // is below 60, if a's exponent is above 500 then b's cannot be below
- // -500 even after scaling by -600 in the first conditional:
- // ((>500 - 60) - 600) > -500. Thus you cannot scale down and up at the same time.
+ // 'if' statement. Thus you cannot scale down and up at the same time.
//
// 4. There is no use of the absolute double value. The magnitude comparison is
// performed using the long bit representation. The computation x^2+y^2 is
// insensitive to the sign bit. Thus use of Math.abs(double) is only in edge-case
// branches.
//
+ // 5. The exponent different to ignore the smaller component has changed from 60 to 54.
+ //
// Original comments from fdlibm are in c style: /* */
// Extra comments added for reference.
//
@@ -3580,12 +3579,11 @@ public final class Complex implements Serializable {
}
// Check if the smaller part is significant.
- // Do not replace this with 27 since the product x^2 is computed in
- // extended precision for an effective mantissa of 106-bits. Potentially it could be
- // replaced with 54 where y^2 will not overlap extended precision x^2.
- if ((ha - hb) > EXP_60) {
- /* x/y > 2**60 */
- // or x is Inf or NaN.
+ // a^2 is computed in extended precision for an effective mantissa of 106-bits.
+ // An exponent difference of 54 is where b^2 will not overlap a^2.
+ if ((ha - hb) > EXP_54) {
+ /* a/b > 2**54 */
+ // or a is Inf or NaN.
// No addition of a + b for sNaN.
return Math.abs(a);
}
@@ -3604,7 +3602,7 @@ public final class Complex implements Serializable {
/* scale a and b by 2^-600 */
// Before scaling: a in [2^500, 2^1023].
// After scaling: a in [2^-100, 2^423].
- // After scaling: b in [2^-160, 2^423].
+ // After scaling: b in [2^-154, 2^423].
a *= TWO_POW_NEG_600;
b *= TWO_POW_NEG_600;
rescale = TWO_POW_600;
@@ -3622,7 +3620,7 @@ public final class Complex implements Serializable {
// Effective min exponent of a sub-normal = -1022 - 52 = -1074.
// Before scaling: b in [2^-1074, 2^-501].
// After scaling: b in [2^-474, 2^99].
- // After scaling: a in [2^-474, 2^159].
+ // After scaling: a in [2^-474, 2^153].
a *= TWO_POW_600;
b *= TWO_POW_600;
rescale = TWO_POW_NEG_600;