diff options
Diffstat (limited to 'libtommath')
-rw-r--r-- | libtommath/bn_mp_div_d.c | 25 | ||||
-rw-r--r-- | libtommath/bn_mp_get_long_long.c | 6 | ||||
-rw-r--r-- | libtommath/bn_mp_set_long_long.c | 2 | ||||
-rw-r--r-- | libtommath/bn_mp_sqrt.c | 88 | ||||
-rw-r--r-- | libtommath/tommath.h | 8 | ||||
-rw-r--r-- | libtommath/tommath_private.h | 2 | ||||
-rwxr-xr-x | libtommath/updatemakes.sh | 33 |
7 files changed, 92 insertions, 72 deletions
diff --git a/libtommath/bn_mp_div_d.c b/libtommath/bn_mp_div_d.c index db4a0a2..c408602 100644 --- a/libtommath/bn_mp_div_d.c +++ b/libtommath/bn_mp_div_d.c @@ -15,24 +15,6 @@ * Tom St Denis, tstdenis82@gmail.com, http://libtom.org */ -static int s_is_power_of_two(mp_digit b, int *p) -{ - int x; - - /* fast return if no power of two */ - if ((b == 0) || ((b & (b-1)) != 0)) { - return 0; - } - - for (x = 0; x < DIGIT_BIT; x++) { - if (b == (((mp_digit)1)<<x)) { - *p = x; - return 1; - } - } - return 0; -} - /* single digit division (based on routine from MPI) */ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) { @@ -58,7 +40,12 @@ int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) } /* power of two ? */ - if (s_is_power_of_two(b, &ix) == 1) { + if (((b & (b-1)) == 0)) { + for (ix = 1; ix < DIGIT_BIT; ix++) { + if (b == (((mp_digit)1)<<ix)) { + break; + } + } if (d != NULL) { *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1); } diff --git a/libtommath/bn_mp_get_long_long.c b/libtommath/bn_mp_get_long_long.c index 838c3c3..a363f60 100644 --- a/libtommath/bn_mp_get_long_long.c +++ b/libtommath/bn_mp_get_long_long.c @@ -16,17 +16,17 @@ */ /* get the lower unsigned long long of an mp_int, platform dependent */ -unsigned long long mp_get_long_long(const mp_int *a) +Tcl_WideUInt mp_get_long_long(const mp_int *a) { int i; - unsigned long long res; + Tcl_WideUInt res; if (a->used == 0) { return 0; } /* get number of digits of the lsb we have to read */ - i = MIN(a->used, (int)(((sizeof(unsigned long long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1; + i = MIN(a->used, (int)(((sizeof(Tcl_WideUInt) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1; /* get most significant digit of result */ res = DIGIT(a, i); diff --git a/libtommath/bn_mp_set_long_long.c b/libtommath/bn_mp_set_long_long.c index 3566b45..0b8be33 100644 --- a/libtommath/bn_mp_set_long_long.c +++ b/libtommath/bn_mp_set_long_long.c @@ -16,7 +16,7 @@ */ /* set a platform dependent unsigned long long int */ -MP_SET_XLONG(mp_set_long_long, unsigned long long) +MP_SET_XLONG(mp_set_long_long, Tcl_WideUInt) #endif /* ref: $Format:%D$ */ diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c index d70c523..49a1bd0 100644 --- a/libtommath/bn_mp_sqrt.c +++ b/libtommath/bn_mp_sqrt.c @@ -15,11 +15,20 @@ * Tom St Denis, tstdenis82@gmail.com, http://libtom.org */ +#ifndef NO_FLOATING_POINT +#include <math.h> +#endif + /* this function is less generic than mp_n_root, simpler and faster */ int mp_sqrt(const mp_int *arg, mp_int *ret) { int res; - mp_int t1, t2; + mp_int t1,t2; + int i, j, k; +#ifndef NO_FLOATING_POINT + volatile double d; + mp_digit dig; +#endif /* must be positive */ if (arg->sign == MP_NEG) { @@ -32,7 +41,9 @@ int mp_sqrt(const mp_int *arg, mp_int *ret) return MP_OKAY; } - if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { + i = (arg->used / 2) - 1; + j = 2 * i; + if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) { return res; } @@ -40,34 +51,87 @@ int mp_sqrt(const mp_int *arg, mp_int *ret) goto E2; } - /* First approx. (not very bad for large arg) */ - mp_rshd(&t1, t1.used/2); + for (k = 0; k < i; ++k) { + t1.dp[k] = (mp_digit) 0; + } + +#ifndef NO_FLOATING_POINT + + /* Estimate the square root using the hardware floating point unit. */ + + d = 0.0; + 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 >= 1.0) { + t1.dp[i+1] = dig; + t1.dp[i] = ((mp_digit) d) - 1; + } else { + t1.dp[i+1] = dig-1; + t1.dp[i] = MP_DIGIT_MAX; + } + } else { + t1.used = i+1; + t1.dp[i] = ((mp_digit) d) - 1; + } + +#else + + /* Estimate the square root as having 1 in the most significant place. */ + + t1.used = i + 2; + t1.dp[i+1] = (mp_digit) 1; + t1.dp[i] = (mp_digit) 0; + +#endif /* t1 > 0 */ - if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } - if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } - if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) { + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* And now t1 > sqrt(arg) */ do { - if ((res = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } - if ((res = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } - if ((res = mp_div_2(&t1, &t1)) != MP_OKAY) { + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* t1 >= sqrt(arg) >= t2 at this point */ - } while (mp_cmp_mag(&t1, &t2) == MP_GT); + } while (mp_cmp_mag(&t1,&t2) == MP_GT); - mp_exch(&t1, ret); + mp_exch(&t1,ret); E1: mp_clear(&t2); diff --git a/libtommath/tommath.h b/libtommath/tommath.h index 591076e..50a3a81 100644 --- a/libtommath/tommath.h +++ b/libtommath/tommath.h @@ -33,11 +33,13 @@ extern "C" { defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ defined(__LP64__) || defined(_LP64) || defined(__64BIT__) -# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT)) +# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT) || defined(_MSC_VER)) # define MP_64BIT # endif #endif +typedef unsigned long long Tcl_WideUInt; + /* some default configurations. * * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits @@ -220,7 +222,7 @@ int mp_set_int(mp_int *a, unsigned long b); int mp_set_long(mp_int *a, unsigned long b); /* set a platform dependent unsigned long long value */ -int mp_set_long_long(mp_int *a, unsigned long long b); +int mp_set_long_long(mp_int *a, Tcl_WideUInt b); /* get a 32-bit value */ unsigned long mp_get_int(const mp_int *a); @@ -229,7 +231,7 @@ unsigned long mp_get_int(const mp_int *a); unsigned long mp_get_long(const mp_int *a); /* get a platform dependent unsigned long long value */ -unsigned long long mp_get_long_long(const mp_int *a); +Tcl_WideUInt mp_get_long_long(const mp_int *a); /* initialize and set a digit */ int mp_init_set(mp_int *a, mp_digit b); diff --git a/libtommath/tommath_private.h b/libtommath/tommath_private.h index 087ddcd..be065cd 100644 --- a/libtommath/tommath_private.h +++ b/libtommath/tommath_private.h @@ -46,7 +46,7 @@ extern "C" { # define XFREE free # define XREALLOC realloc # define XCALLOC calloc -#else +#elif 0 /* prototypes for our heap functions */ extern void *XMALLOC(size_t n); extern void *XREALLOC(void *p, size_t n); diff --git a/libtommath/updatemakes.sh b/libtommath/updatemakes.sh deleted file mode 100755 index 0f9520e..0000000 --- a/libtommath/updatemakes.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -bash genlist.sh > tmplist - -perl filter.pl makefile tmplist -sed -e 's/ *$//' < tmp.delme > makefile -rm -f tmp.delme - -perl filter.pl makefile.icc tmplist -sed -e 's/ *$//' < tmp.delme > makefile.icc -rm -f tmp.delme - -perl filter.pl makefile.shared tmplist -sed -e 's/ *$//' < tmp.delme > makefile.shared -rm -f tmp.delme - -perl filter.pl makefile.cygwin_dll tmplist -sed -e 's/ *$//' < tmp.delme > makefile.cygwin_dll -rm -f tmp.delme - -perl filter.pl makefile.bcc tmplist -sed -e 's/\.o /.obj /g' -e 's/ *$//' < tmp.delme > makefile.bcc -rm -f tmp.delme - -perl filter.pl makefile.msvc tmplist -sed -e 's/\.o /.obj /g' -e 's/ *$//' < tmp.delme > makefile.msvc -rm -f tmp.delme - -rm -f tmplist - -# ref: $Format:%D$ -# git commit: $Format:%H$ -# commit time: $Format:%ai$ |