diff --git a/bn_mp_expt_d.c b/bn_mp_expt_d.c index 2b0b095..ed5f28f 100644 --- a/bn_mp_expt_d.c +++ b/bn_mp_expt_d.c @@ -15,41 +15,12 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ -/* calculate c = a**b using a square-multiply algorithm */ +/* wrapper function for mp_expt_d_ex() */ int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) { - int res; - mp_int g; - - if ((res = mp_init_copy (&g, a)) != MP_OKAY) { - return res; - } - - /* set initial result */ - mp_set (c, 1); - - while (b > 0) { - /* if the bit is set multiply */ - if (b & 1) { - if ((res = mp_mul (c, &g, c)) != MP_OKAY) { - mp_clear (&g); - return res; - } - } - - /* square */ - if (b > 1 && (res = mp_sqr (&g, &g)) != MP_OKAY) { - mp_clear (&g); - return res; - } - - /* shift to next bit */ - b >>= 1; - } - - mp_clear (&g); - return MP_OKAY; + return mp_expt_d_ex(a, b, c, 0); } + #endif /* $Source$ */ diff --git a/bn_mp_expt_d_ex.c b/bn_mp_expt_d_ex.c new file mode 100644 index 0000000..f8ff172 --- /dev/null +++ b/bn_mp_expt_d_ex.c @@ -0,0 +1,81 @@ +#include +#ifdef BN_MP_EXPT_D_EX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* calculate c = a**b using a square-multiply algorithm */ +int mp_expt_d_ex (mp_int * a, mp_digit b, mp_int * c, int fast) +{ + int res; + unsigned int x; + + mp_int g; + + if ((res = mp_init_copy (&g, a)) != MP_OKAY) { + return res; + } + + /* set initial result */ + mp_set (c, 1); + + if (fast) { + while (b > 0) { + /* if the bit is set multiply */ + if (b & 1) { + if ((res = mp_mul (c, &g, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + } + + /* square */ + if (b > 1 && (res = mp_sqr (&g, &g)) != MP_OKAY) { + mp_clear (&g); + return res; + } + + /* shift to next bit */ + b >>= 1; + } + } + else { + for (x = 0; x < DIGIT_BIT; x++) { + /* square */ + if ((res = mp_sqr (c, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + + /* if the bit is set multiply */ + if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { + if ((res = mp_mul (c, &g, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + } + + /* shift to next bit */ + b <<= 1; + } + } /* if ... else */ + + mp_clear (&g); + return MP_OKAY; +} +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/makefile b/makefile index ed7bd91..e9b2eab 100644 --- a/makefile +++ b/makefile @@ -96,7 +96,7 @@ bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \ bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \ bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \ bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o bn_mp_import.o bn_mp_export.o \ -bn_mp_balance_mul.o +bn_mp_balance_mul.o bn_mp_expt_d_ex.o $(LIBNAME): $(OBJECTS) $(AR) $(ARFLAGS) $@ $(OBJECTS) diff --git a/tommath.h b/tommath.h index 8a71d3c..7b5a703 100644 --- a/tommath.h +++ b/tommath.h @@ -364,6 +364,7 @@ int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); /* c = a**b */ int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); +int mp_expt_d_ex (mp_int * a, mp_digit b, mp_int * c, int fast); /* c = a mod b, 0 <= c < b */ int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); diff --git a/tommath_class.h b/tommath_class.h index 238e72d..6569f18 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -41,6 +41,7 @@ #define BN_MP_EXCH_C #define BN_MP_EXPORT_C #define BN_MP_EXPT_D_C +#define BN_MP_EXPT_D_EX_C #define BN_MP_EXPTMOD_C #define BN_MP_EXPTMOD_FAST_C #define BN_MP_EXTEUCLID_C @@ -333,6 +334,10 @@ #endif #if defined(BN_MP_EXPT_D_C) + #define BN_MP_EXPT_D_EX_C +#endif + +#if defined(BN_MP_EXPT_D_EX_C) #define BN_MP_INIT_COPY_C #define BN_MP_SET_C #define BN_MP_MUL_C