summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <hboehm@google.com>2018-01-09 17:06:43 -0800
committerHans Boehm <hboehm@google.com>2018-01-10 10:39:32 -0800
commit568c8e610bdcd0ef141b2e00ff888553311e3a6c (patch)
treefc0d0fd7c34a014d690a7bee8b4b315ebfbab770
parent0c9acfc0d17e2e3a738a7e5e4be099352abd743e (diff)
downloadcrcalc-568c8e610bdcd0ef141b2e00ff888553311e3a6c.tar.gz
Fix a couple of square root related performance problems
Bug: 71686706 Always set appr_valid when we set the approximation. The sqrt_CR constructor used by the pi computation failed to do that. Have square root evaluate the argument to full precision before the recursion. That way we evaluate the argument only once and compute the lesser approximations via simple shifts. Fix the comment summarizing the Newton iteration computation. Rename max_prec_needed, since the name confused me while trying to understand this code again. Test: Calculator tests + CR tests Change-Id: I6d704f24579bae5a5edb4c42487acf1be8fdcee6
-rw-r--r--src/com/hp/creals/CR.java14
1 files changed, 8 insertions, 6 deletions
diff --git a/src/com/hp/creals/CR.java b/src/com/hp/creals/CR.java
index d051050..9e10b51 100644
--- a/src/com/hp/creals/CR.java
+++ b/src/com/hp/creals/CR.java
@@ -1494,15 +1494,16 @@ class sqrt_CR extends CR {
op = x;
min_prec = min_p;
max_appr = max_a;
+ appr_valid = true;
}
final int fp_prec = 50; // Conservative estimate of number of
// significant bits in double precision
// computation.
final int fp_op_prec = 60;
protected BigInteger approximate(int p) {
- int max_prec_needed = 2*p - 1;
- int msd = op.msd(max_prec_needed);
- if (msd <= max_prec_needed) return big0;
+ int max_op_prec_needed = 2*p - 1;
+ int msd = op.msd(max_op_prec_needed);
+ if (msd <= max_op_prec_needed) return big0;
int result_msd = msd/2; // +- 1
int result_digits = result_msd - p; // +- 2
if (result_digits > fp_prec) {
@@ -1510,11 +1511,12 @@ class sqrt_CR extends CR {
int appr_digits = result_digits/2 + 6;
// This should be conservative. Is fewer enough?
int appr_prec = result_msd - appr_digits;
- BigInteger last_appr = get_appr(appr_prec);
int prod_prec = 2*appr_prec;
+ // First compute the argument to maximal precision, so we don't end up
+ // reevaluating it incrementally.
BigInteger op_appr = op.get_appr(prod_prec);
- // Slightly fewer might be enough;
- // Compute (last_appr * last_appr + op_appr)/(last_appr/2)
+ BigInteger last_appr = get_appr(appr_prec);
+ // Compute (last_appr * last_appr + op_appr) / last_appr / 2
// while adjusting the scaling to make everything work
BigInteger prod_prec_scaled_numerator =
last_appr.multiply(last_appr).add(op_appr);