summaryrefslogtreecommitdiffstats
path: root/libtommath
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-04-11 20:09:27 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-04-11 20:09:27 (GMT)
commit7df97e929223d6b0ff18cbfaad9809c18e11c3ff (patch)
tree1f7c03de38e4e36aea930f0938e49b9145e60197 /libtommath
parent417474f1fd64cb819d61f662390ad20a4ad66706 (diff)
downloadtcl-7df97e929223d6b0ff18cbfaad9809c18e11c3ff.zip
tcl-7df97e929223d6b0ff18cbfaad9809c18e11c3ff.tar.gz
tcl-7df97e929223d6b0ff18cbfaad9809c18e11c3ff.tar.bz2
Only use special mp_sqrt() code when double format/tommath format are exactly what's expected. Otherwise, use original always-working tommath code.
Simplify overflow check in bignum expononent code, not using bignums where it's not necessary. Don't overallocate bignums when using wideint's only.
Diffstat (limited to 'libtommath')
-rw-r--r--libtommath/bn_mp_set_double.c4
-rw-r--r--libtommath/bn_mp_sqrt.c22
2 files changed, 17 insertions, 9 deletions
diff --git a/libtommath/bn_mp_set_double.c b/libtommath/bn_mp_set_double.c
index c96a3b3..12f8dad 100644
--- a/libtommath/bn_mp_set_double.c
+++ b/libtommath/bn_mp_set_double.c
@@ -15,11 +15,11 @@
#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
int mp_set_double(mp_int *a, double b)
{
- uint64_t frac;
+ unsigned long long frac;
int exp, res;
union {
double dbl;
- uint64_t bits;
+ unsigned long long bits;
} cast;
cast.dbl = b;
diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c
index bbca158..116fb14 100644
--- a/libtommath/bn_mp_sqrt.c
+++ b/libtommath/bn_mp_sqrt.c
@@ -14,6 +14,9 @@
#ifndef NO_FLOATING_POINT
#include <math.h>
+#if (DIGIT_BIT != 28) || (FLT_RADIX != 2) || (DBL_MANT_DIG != 53) || (DBL_MAX_EXP != 1024)
+#define NO_FLOATING_POINT
+#endif
#endif
/* this function is less generic than mp_n_root, simpler and faster */
@@ -21,8 +24,8 @@ int mp_sqrt(const mp_int *arg, mp_int *ret)
{
int res;
mp_int t1, t2;
- int i, j, k;
#ifndef NO_FLOATING_POINT
+ int i, j, k;
volatile double d;
mp_digit dig;
#endif
@@ -38,6 +41,8 @@ int mp_sqrt(const mp_int *arg, mp_int *ret)
return MP_OKAY;
}
+#ifndef NO_FLOATING_POINT
+
i = (arg->used / 2) - 1;
j = 2 * i;
if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) {
@@ -52,8 +57,6 @@ int mp_sqrt(const mp_int *arg, mp_int *ret)
t1.dp[k] = (mp_digit) 0;
}
-#ifndef NO_FLOATING_POINT
-
/* Estimate the square root using the hardware floating point unit. */
d = 0.0;
@@ -96,11 +99,16 @@ int mp_sqrt(const mp_int *arg, mp_int *ret)
#else
- /* Estimate the square root as having 1 in the most significant place. */
+ if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init(&t2)) != MP_OKAY) {
+ goto E2;
+ }
- t1.used = i + 2;
- t1.dp[i+1] = (mp_digit) 1;
- t1.dp[i] = (mp_digit) 0;
+ /* First approx. (not very bad for large arg) */
+ mp_rshd(&t1, t1.used/2);
#endif