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/07 02:27:45 UTC
[commons-numbers] 03/04: Fix overflow in 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 cc24bfcf91370e197d09b33c0d02edb6e633a40d
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Dec 7 01:44:45 2019 +0000
Fix overflow in sqrt()
---
.../apache/commons/numbers/complex/Complex.java | 23 ++++++++++++++++++----
1 file changed, 19 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 42a88e4..aa2bc2a 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
@@ -1676,7 +1676,7 @@ public final class Complex implements Serializable {
* <ul>
* <li>{@code |a| = }{@link Math#abs}(a)
* <li>{@code |a + b i| = }{@link Complex#abs}(a + b i)
- * <li>{@code sign(b) = }{@link Math#copySign(double,double) copySign(1.0, b)}
+ * <li>{@code sign(b) = }{@link Math#copySign(double,double) copySign}(1.0, b)
* </ul>
*
* @param real Real component.
@@ -1694,11 +1694,13 @@ public final class Complex implements Serializable {
if (real == 0 && imaginary == 0) {
return new Complex(0, imaginary);
}
- final double t = Math.sqrt((Math.abs(real) + Math.hypot(real, imaginary)) / 2);
+ final double t = Math.sqrt(average(Math.abs(real), Math.hypot(real, imaginary)));
+ // t is positive:
+ // To prevent overflow dividing by (2 * t) divide by t then by 2.
if (real >= 0) {
- return new Complex(t, imaginary / (2 * t));
+ return new Complex(t, (imaginary / t) / 2);
}
- return new Complex(Math.abs(imaginary) / (2 * t),
+ return new Complex((Math.abs(imaginary) / t) / 2,
Math.copySign(1.0, imaginary) * t);
}
// Imaginary is nan
@@ -1718,6 +1720,19 @@ public final class Complex implements Serializable {
}
/**
+ * Compute {@code (a + b) / 2} without overflow.
+ *
+ * @param a the a
+ * @param b the b
+ * @return the average
+ */
+ private static double average(double a, double b) {
+ return (b < a) ?
+ a + (b - a) / 2 :
+ b + (a - b) / 2;
+ }
+
+ /**
* Compute the
* <a href="http://mathworld.wolfram.com/Tangent.html">
* tangent</a> of this complex number.