diff options
author | Hans Boehm <hboehm@google.com> | 2017-09-05 19:24:23 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-09-05 19:24:23 +0000 |
commit | 6ba4971cb9885c94e0024fd7d9b4d406573f49f9 (patch) | |
tree | 4c98fb11d925a91efa92335573752520cdd136ab | |
parent | b2b0478782580fdfa627e1c4beedd3491a234bbf (diff) | |
parent | 181d62aea745f879053166502bec005be62ce8ae (diff) | |
download | crcalc-6ba4971cb9885c94e0024fd7d9b4d406573f49f9.tar.gz |
Fix exp() on large negative arguments am: 533bb2355d am: dfed3c6d37 am: b1b34d2c8a
am: 181d62aea7
Change-Id: Id1d277a340a1049c805c1f0e74eeaafaeae52989
-rw-r--r-- | src/com/hp/creals/CR.java | 13 |
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. |