diff options
Diffstat (limited to 'libtommath/bn_mp_sqrt.c')
-rw-r--r-- | libtommath/bn_mp_sqrt.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c index 3aa0f38..0bba337 100644 --- a/libtommath/bn_mp_sqrt.c +++ b/libtommath/bn_mp_sqrt.c @@ -27,7 +27,7 @@ int mp_sqrt(mp_int *arg, mp_int *ret) mp_int t1,t2; int i, j, k; #ifndef NO_FLOATING_POINT - double d; + volatile double d; mp_digit dig; #endif @@ -64,12 +64,29 @@ int mp_sqrt(mp_int *arg, mp_int *ret) for (k = arg->used-1; k >= j; --k) { d = ldexp(d, DIGIT_BIT) + (double) (arg->dp[k]); } + + /* + * At this point, d is the nearest floating point number to the most + * significant 1 or 2 mp_digits of arg. Extract its square root. + */ + d = sqrt(d); + + /* dig is the most significant mp_digit of the square root */ + dig = (mp_digit) ldexp(d, -DIGIT_BIT); + + /* + * If the most significant digit is nonzero, find the next digit down + * by subtracting DIGIT_BIT times thie most significant digit. + * Subtract one from the result so that our initial estimate is always + * low. + */ + if (dig) { t1.used = i+2; d -= ldexp((double) dig, DIGIT_BIT); - if (d != 0.0) { + if (d >= 1.0) { t1.dp[i+1] = dig; t1.dp[i] = ((mp_digit) d) - 1; } else { @@ -126,5 +143,5 @@ E2: mp_clear(&t1); /* $Source: /root/tcl/repos-to-convert/tcl/libtommath/bn_mp_sqrt.c,v $ */ /* Based on Tom's 1.3 */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/01 05:48:23 $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2008/10/05 21:27:07 $ */ |