summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <hboehm@google.com>2017-09-05 19:19:44 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-09-05 19:19:44 +0000
commit181d62aea745f879053166502bec005be62ce8ae (patch)
tree4c98fb11d925a91efa92335573752520cdd136ab
parente35748b3c27814dbfc96237a6fbdd2bf447b0f0d (diff)
parentb1b34d2c8a133b30bef88134e50f9c0bf5aaa462 (diff)
downloadcrcalc-181d62aea745f879053166502bec005be62ce8ae.tar.gz
Fix exp() on large negative arguments am: 533bb2355d am: dfed3c6d37
am: b1b34d2c8a Change-Id: I0e00e8e29bd80ace7d459afa208ce56236c21296
-rw-r--r--src/com/hp/creals/CR.java13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/com/hp/creals/CR.java b/src/com/hp/creals/CR.java
index 5312b15..de89faf 100644
--- a/src/com/hp/creals/CR.java
+++ b/src/com/hp/creals/CR.java
@@ -104,6 +104,11 @@
// make them public. hboehm@google.com 5/21/2015
// Added Gauss-Legendre PI implementation. Removed two.
// hboehm@google.com 4/12/2016
+// Fix shift operation in doubleValue. That produced incorrect values for
+// large negative exponents.
+// Don't negate argument and compute inverse for exp(). That causes severe
+// performance problems for (-huge).exp()
+// hboehm@google.com 8/21/2017
package com.hp.creals;
@@ -200,6 +205,7 @@ public static class PrecisionOverflowException extends RuntimeException {
static final BigInteger big1 = BigInteger.ONE;
static final BigInteger bigm1 = BigInteger.valueOf(-1);
static final BigInteger big2 = BigInteger.valueOf(2);
+ static final BigInteger bigm2 = BigInteger.valueOf(-2);
static final BigInteger big3 = BigInteger.valueOf(3);
static final BigInteger big6 = BigInteger.valueOf(6);
static final BigInteger big8 = BigInteger.valueOf(8);
@@ -865,8 +871,9 @@ public volatile static boolean please_stop = false;
public CR exp() {
final int low_prec = -10;
BigInteger rough_appr = get_appr(low_prec);
- if (rough_appr.signum() < 0) return negate().exp().inverse();
- if (rough_appr.compareTo(big2) > 0) {
+ // Handle negative arguments directly; negating and computing inverse
+ // can be very expensive.
+ if (rough_appr.compareTo(big2) > 0 || rough_appr.compareTo(bigm2) < 0) {
CR square_root = shiftRight(1).exp();
return square_root.multiply(square_root);
} else {
@@ -1208,7 +1215,7 @@ class inv_CR extends CR {
// Representation of the exponential of a constructive real. Private.
-// Uses a Taylor series expansion. Assumes x < 1/2.
+// Uses a Taylor series expansion. Assumes |x| < 1/2.
// Note: this is known to be a bad algorithm for
// floating point. Unfortunately, other alternatives
// appear to require precomputed information.