From c1da6aa2de997d954d745ce67dee3598ed6ee71f Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 5 Aug 2003 01:24:44 +0000 Subject: [PATCH] added libtommath-0.25 --- LICENSE | 4 + bn.pdf | Bin 233666 -> 233590 bytes bn.tex | 2 +- bn_error.c | 41 + bn_fast_mp_invmod.c | 21 +- bn_fast_mp_montgomery_reduce.c | 25 +- bn_fast_s_mp_mul_digs.c | 4 +- bn_fast_s_mp_mul_high_digs.c | 6 +- bn_fast_s_mp_sqr.c | 27 +- bn_mp_2expt.c | 11 +- bn_mp_abs.c | 15 +- bn_mp_add.c | 4 +- bn_mp_add_d.c | 10 +- bn_mp_addmod.c | 4 +- bn_mp_and.c | 4 +- bn_mp_clamp.c | 9 +- bn_mp_clear.c | 8 +- bn_mp_clear_multi.c | 28 + bn_mp_cmp.c | 4 +- bn_mp_cmp_d.c | 8 +- bn_mp_cmp_mag.c | 4 +- bn_mp_cnt_lsb.c | 5 +- bn_mp_copy.c | 16 +- bn_mp_count_bits.c | 4 +- bn_mp_div.c | 4 +- bn_mp_div_2.c | 4 +- bn_mp_div_2d.c | 4 +- bn_mp_div_3.c | 19 +- bn_mp_div_d.c | 4 +- bn_mp_dr_is_modulus.c | 71 +- bn_mp_dr_reduce.c | 6 +- bn_mp_dr_setup.c | 52 +- bn_mp_exch.c | 6 +- bn_mp_expt_d.c | 4 +- bn_mp_exptmod.c | 8 +- bn_mp_exptmod_fast.c | 33 +- bn_mp_fread.c | 122 +- bn_mp_fwrite.c | 4 +- bn_mp_gcd.c | 37 +- bn_mp_grow.c | 6 +- bn_mp_init.c | 8 +- bn_mp_init_copy.c | 4 +- bn_mp_multi.c => bn_mp_init_multi.c | 18 +- bn_mp_init_size.c | 13 +- bn_mp_invmod.c | 4 +- bn_mp_jacobi.c | 20 +- bn_mp_karatsuba_mul.c | 4 +- bn_mp_karatsuba_sqr.c | 4 +- bn_mp_lcm.c | 4 +- bn_mp_lshd.c | 4 +- bn_mp_mod.c | 4 +- bn_mp_mod_2d.c | 5 +- bn_mp_mod_d.c | 4 +- bn_mp_montgomery_calc_normalization.c | 4 +- bn_mp_montgomery_reduce.c | 4 +- bn_mp_montgomery_setup.c | 4 +- bn_mp_mul.c | 9 +- bn_mp_mul_2.c | 6 +- bn_mp_mul_2d.c | 6 +- bn_mp_mul_d.c | 4 +- bn_mp_mulmod.c | 4 +- bn_mp_n_root.c | 6 +- bn_mp_neg.c | 4 +- bn_mp_or.c | 4 +- bn_mp_prime_fermat.c | 6 +- bn_mp_prime_is_divisible.c | 4 +- bn_mp_prime_is_prime.c | 4 +- bn_mp_prime_miller_rabin.c | 4 +- bn_mp_prime_next_prime.c | 12 +- bn_mp_radix_size.c | 108 +- bn_mp_radix_smap.c | 36 +- bn_mp_rand.c | 4 +- bn_mp_read_radix.c | 154 +- bn_mp_read_signed_bin.c | 4 +- bn_mp_read_unsigned_bin.c | 4 +- bn_mp_reduce.c | 4 +- bn_mp_reduce_2k.c | 112 +- bn_mp_reduce_2k_setup.c | 84 +- bn_mp_reduce_is_2k.c | 76 +- bn_mp_reduce_setup.c | 58 +- bn_mp_rshd.c | 4 +- bn_mp_set.c | 6 +- bn_mp_set_int.c | 4 +- bn_mp_shrink.c | 4 +- bn_mp_signed_bin_size.c | 4 +- bn_mp_sqr.c | 9 +- bn_mp_sqrmod.c | 5 +- bn_mp_sub.c | 4 +- bn_mp_sub_d.c | 10 +- bn_mp_submod.c | 4 +- bn_mp_to_signed_bin.c | 4 +- bn_mp_to_unsigned_bin.c | 4 +- bn_mp_toom_mul.c | 546 ++--- bn_mp_toom_sqr.c | 440 ++-- bn_mp_toradix.c | 4 +- bn_mp_unsigned_bin_size.c | 4 +- bn_mp_xor.c | 4 +- bn_mp_zero.c | 4 +- bn_prime_tab.c | 4 +- bn_reverse.c | 4 +- bn_s_mp_add.c | 4 +- bn_s_mp_exptmod.c | 21 +- bn_s_mp_mul_digs.c | 4 +- bn_s_mp_mul_high_digs.c | 4 +- bn_s_mp_sqr.c | 4 +- bn_s_mp_sub.c | 4 +- bncore.c | 4 +- changes.txt | 13 + demo/demo.c | 32 +- etc/2kprime.1 | 3 +- etc/pprime.c | 1 - logs/mult.log | 17 - makefile | 14 +- makefile.bcc | 9 +- makefile.msvc | 5 +- pics/design_process.sxd | Bin 0 -> 6950 bytes pics/makefile | 63 +- poster.pdf | Bin 40822 -> 40820 bytes pre_gen/mpi.c | 2697 +++++++++++++------------ tdcal.pdf | Bin 56674 -> 0 bytes tommath.h | 16 +- 121 files changed, 2906 insertions(+), 2554 deletions(-) create mode 100644 LICENSE create mode 100644 bn_error.c create mode 100644 bn_mp_clear_multi.c rename bn_mp_multi.c => bn_mp_init_multi.c (81%) create mode 100644 pics/design_process.sxd delete mode 100644 tdcal.pdf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5baa792 --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +LibTomMath is hereby released into the Public Domain. + +-- Tom St Denis + diff --git a/bn.pdf b/bn.pdf index a6c3d0710c9388ff60c458abd446daaadc44bde4..a0cde682e7c32caa7d1b3a80b6f6aaf8d0fc151c 100644 GIT binary patch delta 100805 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 z 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

PvfFL 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 diff --git a/bn.tex b/bn.tex index 9beddda..60f6d50 100644 --- a/bn.tex +++ b/bn.tex @@ -1,7 +1,7 @@ \documentclass[]{article} \begin{document} -\title{LibTomMath v0.24 \\ A Free Multiple Precision Integer Library \\ http://math.libtomcrypt.org } +\title{LibTomMath v0.25 \\ A Free Multiple Precision Integer Library \\ http://math.libtomcrypt.org } \author{Tom St Denis \\ tomstdenis@iahu.ca} \maketitle \newpage diff --git a/bn_error.c b/bn_error.c new file mode 100644 index 0000000..7cac649 --- /dev/null +++ b/bn_error.c @@ -0,0 +1,41 @@ +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +static const struct { + int code; + char *msg; +} msgs[] = { + { MP_OKAY, "Successful" }, + { MP_MEM, "Out of heap" }, + { MP_VAL, "Value out of range" } +}; + +/* return a char * string for a given code */ +char *mp_error_to_string(int code) +{ + int x; + + /* scan the lookup table for the given message */ + for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { + if (msgs[x].code == code) { + return msgs[x].msg; + } + } + + /* generic reply for invalid code */ + return "Invalid error code"; +} + diff --git a/bn_fast_mp_invmod.c b/bn_fast_mp_invmod.c index e32c1ae..2b86ce4 100644 --- a/bn_fast_mp_invmod.c +++ b/bn_fast_mp_invmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -26,6 +26,14 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) mp_int x, y, u, v, B, D; int res, neg; + /* 2. [modified] if a,b are both even then return an error! + * + * That is if gcd(a,b) = 2**k * q then obviously there is no inverse. + */ + if (mp_iseven (a) == 1 && mp_iseven (b) == 1) { + return MP_VAL; + } + /* init all our temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { return res; @@ -41,15 +49,6 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) goto __ERR; } - /* 2. [modified] if x,y are both even then return an error! - * - * That is if gcd(x,y) = 2 * k then obviously there is no inverse. - */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto __ERR; - } - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto __ERR; diff --git a/bn_fast_mp_montgomery_reduce.c b/bn_fast_mp_montgomery_reduce.c index 7017455..b6a8645 100644 --- a/bn_fast_mp_montgomery_reduce.c +++ b/bn_fast_mp_montgomery_reduce.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -38,6 +38,9 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } } + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ { register mp_word *_W; register mp_digit *tmpx; @@ -56,6 +59,9 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } } + /* now we proceed to zero successive digits + * from the least significant upwards + */ for (ix = 0; ix < n->used; ix++) { /* mu = ai * m' mod b * @@ -101,12 +107,20 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); } + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ { register mp_digit *tmpx; register mp_word *_W, *_W1; /* nox fix rest of carries */ + + /* alias for current word */ _W1 = W + ix; + + /* alias for next word, where the carry goes */ _W = W + ++ix; for (; ix <= n->used * 2 + 1; ix++) { @@ -119,7 +133,11 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * array of mp_word to mp_digit than calling mp_rshd * we just copy them in the right order */ + + /* alias for destination word */ tmpx = x->dp; + + /* alias for shifted double precision result */ _W = W + n->used; for (ix = 0; ix < n->used + 1; ix++) { @@ -127,7 +145,8 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits */ + * m->used+1 we'll have to clear the digits + */ for (; ix < olduse; ix++) { *tmpx++ = 0; } diff --git a/bn_fast_s_mp_mul_digs.c b/bn_fast_s_mp_mul_digs.c index bca2a71..75fa706 100644 --- a/bn_fast_s_mp_mul_digs.c +++ b/bn_fast_s_mp_mul_digs.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_fast_s_mp_mul_high_digs.c b/bn_fast_s_mp_mul_high_digs.c index e0e9281..779aa14 100644 --- a/bn_fast_s_mp_mul_high_digs.c +++ b/bn_fast_s_mp_mul_high_digs.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -12,7 +12,7 @@ * * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org */ -#include + #include /* this is a modified version of fast_s_mp_mul_digs that only produces * output digits *above* digs. See the comments for fast_s_mp_mul_digs diff --git a/bn_fast_s_mp_sqr.c b/bn_fast_s_mp_sqr.c index 2c01cd0..0a68d42 100644 --- a/bn_fast_s_mp_sqr.c +++ b/bn_fast_s_mp_sqr.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -48,14 +48,14 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) /* zero temp buffer (columns) * Note that there are two buffers. Since squaring requires - * a outter and inner product and the inner product requires + * a outer and inner product and the inner product requires * computing a product and doubling it (a relatively expensive * op to perform n**2 times if you don't have to) the inner and * outer products are computed in different buffers. This way * the inner product can be doubled using n doublings instead of * n**2 */ - memset (W, 0, newused * sizeof (mp_word)); + memset (W, 0, newused * sizeof (mp_word)); memset (W2, 0, newused * sizeof (mp_word)); /* This computes the inner product. To simplify the inner N**2 loop @@ -67,6 +67,7 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) * Note that every outer product is computed * for a particular column only once which means that * there is no need todo a double precision addition + * into the W2[] array. */ W2[ix + ix] = ((mp_word)a->dp[ix]) * ((mp_word)a->dp[ix]); @@ -95,7 +96,12 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) olduse = b->used; b->used = newused; - /* now compute digits */ + /* now compute digits + * + * We have to double the inner product sums, add in the + * outer product sums, propagate carries and convert + * to single precision. + */ { register mp_digit *tmpb; @@ -109,16 +115,21 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) /* double/add next digit */ W[ix] += W[ix] + W2[ix]; + /* propagate carry forwards [from the previous digit] */ W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + + /* store the current digit now that the carry isn't + * needed + */ *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); } - /* set the last value. Note even if the carry is zero - * this is required since the next step will not zero + /* set the last value. Note even if the carry is zero + * this is required since the next step will not zero * it if b originally had a value at b->dp[2*a.used] */ *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); - /* clear high digits */ + /* clear high digits of b if there were any originally */ for (; ix < olduse; ix++) { *tmpb++ = 0; } diff --git a/bn_mp_2expt.c b/bn_mp_2expt.c index 96cf84e..5c4e256 100644 --- a/bn_mp_2expt.c +++ b/bn_mp_2expt.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -24,11 +24,18 @@ mp_2expt (mp_int * a, int b) { int res; + /* zero a as per default */ mp_zero (a); + + /* grow a to accomodate the single bit */ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } + + /* set the used count of where the bit will go */ a->used = b / DIGIT_BIT + 1; + + /* put the single bit in its place */ a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT); return MP_OKAY; diff --git a/bn_mp_abs.c b/bn_mp_abs.c index 60a3470..a5e9ab0 100644 --- a/bn_mp_abs.c +++ b/bn_mp_abs.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -22,9 +22,16 @@ int mp_abs (mp_int * a, mp_int * b) { int res; - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } } + + /* force the sign of b to positive */ b->sign = MP_ZPOS; + return MP_OKAY; } diff --git a/bn_mp_add.c b/bn_mp_add.c index 43a08ab..b144a8e 100644 --- a/bn_mp_add.c +++ b/bn_mp_add.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_add_d.c b/bn_mp_add_d.c index 9703ad3..11b2ecd 100644 --- a/bn_mp_add_d.c +++ b/bn_mp_add_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -82,7 +82,11 @@ mp_add_d (mp_int * a, mp_digit b, mp_int * c) c->used = 1; /* the result is a single digit */ - *tmpc++ = b - a->dp[0]; + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } /* setup count so the clearing of oldused * can fall through correctly diff --git a/bn_mp_addmod.c b/bn_mp_addmod.c index 4ad89e0..691dc50 100644 --- a/bn_mp_addmod.c +++ b/bn_mp_addmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_and.c b/bn_mp_and.c index 8c18fdc..9abb618 100644 --- a/bn_mp_and.c +++ b/bn_mp_and.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_clamp.c b/bn_mp_clamp.c index c349f7c..c6285ce 100644 --- a/bn_mp_clamp.c +++ b/bn_mp_clamp.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -24,9 +24,14 @@ void mp_clamp (mp_int * a) { + /* decrease used while the most significant digit is + * zero. + */ while (a->used > 0 && a->dp[a->used - 1] == 0) { --(a->used); } + + /* reset the sign flag if used == 0 */ if (a->used == 0) { a->sign = MP_ZPOS; } diff --git a/bn_mp_clear.c b/bn_mp_clear.c index bc31c42..be2562e 100644 --- a/bn_mp_clear.c +++ b/bn_mp_clear.c @@ -1,10 +1,10 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with + * 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 @@ -18,6 +18,7 @@ void mp_clear (mp_int * a) { + /* only do anything if a hasn't been freed previously */ if (a->dp != NULL) { /* first zero the digits */ memset (a->dp, 0, sizeof (mp_digit) * a->used); @@ -28,5 +29,6 @@ mp_clear (mp_int * a) /* reset members to make debugging easier */ a->dp = NULL; a->alloc = a->used = 0; + a->sign = MP_ZPOS; } } diff --git a/bn_mp_clear_multi.c b/bn_mp_clear_multi.c new file mode 100644 index 0000000..d262b2f --- /dev/null +++ b/bn_mp_clear_multi.c @@ -0,0 +1,28 @@ +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} diff --git a/bn_mp_cmp.c b/bn_mp_cmp.c index 4bf8082..995e4c4 100644 --- a/bn_mp_cmp.c +++ b/bn_mp_cmp.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_cmp_d.c b/bn_mp_cmp_d.c index f2725cf..600438f 100644 --- a/bn_mp_cmp_d.c +++ b/bn_mp_cmp_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -18,15 +18,17 @@ int mp_cmp_d (mp_int * a, mp_digit b) { - + /* compare based on sign */ if (a->sign == MP_NEG) { return MP_LT; } + /* compare based on magnitude */ if (a->used > 1) { return MP_GT; } + /* compare the only digit of a to b */ if (a->dp[0] > b) { return MP_GT; } else if (a->dp[0] < b) { diff --git a/bn_mp_cmp_mag.c b/bn_mp_cmp_mag.c index 87b56d6..c52d725 100644 --- a/bn_mp_cmp_mag.c +++ b/bn_mp_cmp_mag.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_cnt_lsb.c b/bn_mp_cnt_lsb.c index df0846f..e46161b 100644 --- a/bn_mp_cnt_lsb.c +++ b/bn_mp_cnt_lsb.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -20,6 +20,7 @@ int mp_cnt_lsb(mp_int *a) int x; mp_digit q; + /* easy out */ if (mp_iszero(a) == 1) { return 0; } diff --git a/bn_mp_copy.c b/bn_mp_copy.c index 4e3eef8..1c45f3e 100644 --- a/bn_mp_copy.c +++ b/bn_mp_copy.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -26,8 +26,10 @@ mp_copy (mp_int * a, mp_int * b) } /* grow dest */ - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } } /* zero b and copy the parameters over */ @@ -35,7 +37,11 @@ mp_copy (mp_int * a, mp_int * b) register mp_digit *tmpa, *tmpb; /* pointer aliases */ + + /* source */ tmpa = a->dp; + + /* destination */ tmpb = b->dp; /* copy all the digits */ @@ -48,6 +54,8 @@ mp_copy (mp_int * a, mp_int * b) *tmpb++ = 0; } } + + /* copy used count and sign */ b->used = a->used; b->sign = a->sign; return MP_OKAY; diff --git a/bn_mp_count_bits.c b/bn_mp_count_bits.c index e48bda1..33b971b 100644 --- a/bn_mp_count_bits.c +++ b/bn_mp_count_bits.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_div.c b/bn_mp_div.c index 4e0f353..b211cf4 100644 --- a/bn_mp_div.c +++ b/bn_mp_div.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_div_2.c b/bn_mp_div_2.c index 1ade93c..1c545f1 100644 --- a/bn_mp_div_2.c +++ b/bn_mp_div_2.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_div_2d.c b/bn_mp_div_2d.c index 9bc1fd6..66db765 100644 --- a/bn_mp_div_2d.c +++ b/bn_mp_div_2d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_div_3.c b/bn_mp_div_3.c index d82f29f..0c41db6 100644 --- a/bn_mp_div_3.c +++ b/bn_mp_div_3.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -35,10 +35,17 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); - + if (w >= 3) { + /* multiply w by [1/3] */ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + + /* now subtract 3 * [w/3] from w, to get the remainder */ w -= (t << ((mp_word)1)) + t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ while (w >= 3) { t += 1; w -= 3; @@ -48,11 +55,13 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) } q.dp[ix] = (mp_digit)t; } - + + /* [optional] store the remainder */ if (d != NULL) { *d = (mp_digit)w; } - + + /* [optional] store the quotient */ if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); diff --git a/bn_mp_div_d.c b/bn_mp_div_d.c index 0f683a5..2502341 100644 --- a/bn_mp_div_d.c +++ b/bn_mp_div_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_dr_is_modulus.c b/bn_mp_dr_is_modulus.c index 381af17..0206e0e 100644 --- a/bn_mp_dr_is_modulus.c +++ b/bn_mp_dr_is_modulus.c @@ -1,34 +1,37 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines if a number is a valid DR modulus */ -int mp_dr_is_modulus(mp_int *a) -{ - int ix; - - /* must be at least two digits */ - if (a->used < 2) { - return 0; - } - - for (ix = 1; ix < a->used; ix++) { - if (a->dp[ix] != MP_MASK) { - return 0; - } - } - return 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + diff --git a/bn_mp_dr_reduce.c b/bn_mp_dr_reduce.c index 7d7259e..500f558 100644 --- a/bn_mp_dr_reduce.c +++ b/bn_mp_dr_reduce.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -57,7 +57,7 @@ top: /* set carry to zero */ mu = 0; - /* compute (x mod B**m) + mp * [x/B**m] inline and inplace */ + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ for (i = 0; i < m; i++) { r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; *tmpx1++ = (mp_digit)(r & MP_MASK); diff --git a/bn_mp_dr_setup.c b/bn_mp_dr_setup.c index c1dbbbb..f269436 100644 --- a/bn_mp_dr_setup.c +++ b/bn_mp_dr_setup.c @@ -1,26 +1,26 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines the setup value */ -void mp_dr_setup(mp_int *a, mp_digit *d) -{ - /* the casts are required if DIGIT_BIT is one less than - * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] - */ - *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - - ((mp_word)a->dp[0])); -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + diff --git a/bn_mp_exch.c b/bn_mp_exch.c index b2cdab7..71f6e04 100644 --- a/bn_mp_exch.c +++ b/bn_mp_exch.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -22,7 +22,7 @@ mp_exch (mp_int * a, mp_int * b) { mp_int t; - t = *a; + t = *a; *a = *b; *b = t; } diff --git a/bn_mp_expt_d.c b/bn_mp_expt_d.c index cf5c8ed..49594f8 100644 --- a/bn_mp_expt_d.c +++ b/bn_mp_expt_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_exptmod.c b/bn_mp_exptmod.c index e94e658..2da394b 100644 --- a/bn_mp_exptmod.c +++ b/bn_mp_exptmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -60,7 +60,10 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) return err; } + /* is it a DR modulus? */ dr = mp_dr_is_modulus(P); + + /* if not, is it a uDR modulus? */ if (dr == 0) { dr = mp_reduce_is_2k(P) << 1; } @@ -69,6 +72,7 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) if (mp_isodd (P) == 1 || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { + /* otherwise use the generic Barrett reduction technique */ return s_mp_exptmod (G, X, P, Y); } } diff --git a/bn_mp_exptmod_fast.c b/bn_mp_exptmod_fast.c index 8a5e565..1fe9df6 100644 --- a/bn_mp_exptmod_fast.c +++ b/bn_mp_exptmod_fast.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -94,15 +94,15 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else { - /* use slower baselien method */ + /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; } } else if (redmode == 1) { - /* setup DR reduction */ + /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; } else { - /* setup 2k reduction */ + /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto __M; } @@ -111,7 +111,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { - goto __RES; + goto __M; } /* create M table @@ -173,15 +173,17 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ if (digidx == -1) { break; } - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; } /* grab the next msb from the exponent */ - y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it @@ -206,7 +208,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; + mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ @@ -231,7 +233,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* empty window and reset */ bitcpy = 0; bitbuf = 0; - mode = 1; + mode = 1; } } @@ -246,6 +248,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) goto __RES; } + /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ @@ -260,12 +263,18 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) } if (redmode == 0) { - /* fixup result if Montgomery reduction is used */ + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) { goto __RES; } } + /* swap res with Y */ mp_exch (&res, Y); err = MP_OKAY; __RES:mp_clear (&res); diff --git a/bn_mp_fread.c b/bn_mp_fread.c index 004b0f1..ef665e5 100644 --- a/bn_mp_fread.c +++ b/bn_mp_fread.c @@ -1,61 +1,61 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* read a bigint from a file stream in ASCII */ -int mp_fread(mp_int *a, int radix, FILE *stream) -{ - int err, ch, neg, y; - - /* clear a */ - mp_zero(a); - - /* if first digit is - then set negative */ - ch = fgetc(stream); - if (ch == '-') { - neg = MP_NEG; - ch = fgetc(stream); - } else { - neg = MP_ZPOS; - } - - for (;;) { - /* find y in the radix map */ - for (y = 0; y < radix; y++) { - if (mp_s_rmap[y] == ch) { - break; - } - } - if (y == radix) { - break; - } - - /* shift up and add */ - if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { - return err; - } - if ((err = mp_add_d(a, y, a)) != MP_OKAY) { - return err; - } - - ch = fgetc(stream); - } - if (mp_cmp_d(a, 0) != MP_EQ) { - a->sign = neg; - } - - return MP_OKAY; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* read a bigint from a file stream in ASCII */ +int mp_fread(mp_int *a, int radix, FILE *stream) +{ + int err, ch, neg, y; + + /* clear a */ + mp_zero(a); + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == '-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + for (;;) { + /* find y in the radix map */ + for (y = 0; y < radix; y++) { + if (mp_s_rmap[y] == ch) { + break; + } + } + if (y == radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + + ch = fgetc(stream); + } + if (mp_cmp_d(a, 0) != MP_EQ) { + a->sign = neg; + } + + return MP_OKAY; +} + diff --git a/bn_mp_fwrite.c b/bn_mp_fwrite.c index 93d51fd..a1fe564 100644 --- a/bn_mp_fwrite.c +++ b/bn_mp_fwrite.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_gcd.c b/bn_mp_gcd.c index b73657c..d46d468 100644 --- a/bn_mp_gcd.c +++ b/bn_mp_gcd.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -23,16 +23,21 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) /* either zero than gcd is the largest */ if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { - return mp_copy (b, c); + return mp_abs (b, c); } if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { - return mp_copy (a, c); + return mp_abs (a, c); } - if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { + + /* optimized. At this point if a == 0 then + * b must equal zero too + */ + if (mp_iszero (a) == 1) { mp_zero(c); return MP_OKAY; } + /* get copies of a and b we can modify */ if ((res = mp_init_copy (&u, a)) != MP_OKAY) { return res; } @@ -49,12 +54,15 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) v_lsb = mp_cnt_lsb(&v); k = MIN(u_lsb, v_lsb); - if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { - goto __V; - } + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto __V; + } - if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { - goto __V; + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto __V; + } } /* divide any remaining factors of two out */ @@ -69,10 +77,11 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) goto __V; } } - + while (mp_iszero(&v) == 0) { /* make sure v is the largest */ if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ mp_exch(&u, &v); } @@ -86,10 +95,10 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) goto __V; } } - - /* multiply by 2**k which we divided out at the beginning */ + + /* multiply by 2**k which we divided out at the beginning */ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { - goto __V; + goto __V; } c->sign = MP_ZPOS; res = MP_OKAY; diff --git a/bn_mp_grow.c b/bn_mp_grow.c index 2a8249c..e6ae02f 100644 --- a/bn_mp_grow.c +++ b/bn_mp_grow.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -23,7 +23,7 @@ mp_grow (mp_int * a, int size) /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* ensure there are always at least MP_PREC digits extra on top */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + size += (MP_PREC * 2) - (size % MP_PREC); a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * size); if (a->dp == NULL) { diff --git a/bn_mp_init.c b/bn_mp_init.c index 2cfa002..f39b5cd 100644 --- a/bn_mp_init.c +++ b/bn_mp_init.c @@ -1,10 +1,10 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with + * 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 @@ -18,7 +18,7 @@ int mp_init (mp_int * a) { - /* allocate ram required and clear it */ + /* allocate memory required and clear it */ a->dp = OPT_CAST calloc (sizeof (mp_digit), MP_PREC); if (a->dp == NULL) { return MP_MEM; diff --git a/bn_mp_init_copy.c b/bn_mp_init_copy.c index f87ad16..f0f3590 100644 --- a/bn_mp_init_copy.c +++ b/bn_mp_init_copy.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_multi.c b/bn_mp_init_multi.c similarity index 81% rename from bn_mp_multi.c rename to bn_mp_init_multi.c index ef96dc6..1989b55 100644 --- a/bn_mp_multi.c +++ b/bn_mp_init_multi.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -49,16 +49,4 @@ int mp_init_multi(mp_int *mp, ...) } va_end(args); return res; /* Assumed ok, if error flagged above. */ -} - -void mp_clear_multi(mp_int *mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_clear(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} +} \ No newline at end of file diff --git a/bn_mp_init_size.c b/bn_mp_init_size.c index 2408c1a..6e15ec0 100644 --- a/bn_mp_init_size.c +++ b/bn_mp_init_size.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -14,22 +14,21 @@ */ #include -/* init a mp_init and grow it to a given size */ +/* init an mp_init for a given size */ int mp_init_size (mp_int * a, int size) { - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ a->dp = OPT_CAST calloc (sizeof (mp_digit), size); if (a->dp == NULL) { return MP_MEM; } - a->used = 0; + a->used = 0; a->alloc = size; - a->sign = MP_ZPOS; + a->sign = MP_ZPOS; return MP_OKAY; } diff --git a/bn_mp_invmod.c b/bn_mp_invmod.c index 2dd7a0c..ecfc167 100644 --- a/bn_mp_invmod.c +++ b/bn_mp_invmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_jacobi.c b/bn_mp_jacobi.c index eb0c47b..4c49eb5 100644 --- a/bn_mp_jacobi.c +++ b/bn_mp_jacobi.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -24,6 +24,11 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) int k, s, r, res; mp_digit residue; + /* if p <= 0 return MP_VAL */ + if (mp_cmp_d(p, 0) != MP_GT) { + return MP_VAL; + } + /* step 1. if a == 0, return 0 */ if (mp_iszero (a) == 1) { *c = 0; @@ -37,7 +42,7 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) } /* default */ - k = s = 0; + s = 0; /* step 3. write a = a1 * 2**k */ if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { @@ -48,11 +53,10 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) goto __A1; } - while (mp_iseven (&a1) == 1) { - k = k + 1; - if ((res = mp_div_2 (&a1, &a1)) != MP_OKAY) { - goto __P1; - } + /* divide out larger power of two */ + k = mp_cnt_lsb(&a1); + if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) { + goto __P1; } /* step 4. if e is even set s=1 */ diff --git a/bn_mp_karatsuba_mul.c b/bn_mp_karatsuba_mul.c index bda2f1e..95353ea 100644 --- a/bn_mp_karatsuba_mul.c +++ b/bn_mp_karatsuba_mul.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_karatsuba_sqr.c b/bn_mp_karatsuba_sqr.c index c9e3e67..04dd286 100644 --- a/bn_mp_karatsuba_sqr.c +++ b/bn_mp_karatsuba_sqr.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_lcm.c b/bn_mp_lcm.c index 75b5829..0c0c237 100644 --- a/bn_mp_lcm.c +++ b/bn_mp_lcm.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_lshd.c b/bn_mp_lshd.c index 1ac185c..15fca0e 100644 --- a/bn_mp_lshd.c +++ b/bn_mp_lshd.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_mod.c b/bn_mp_mod.c index e6027ce..d5ebb16 100644 --- a/bn_mp_mod.c +++ b/bn_mp_mod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_mod_2d.c b/bn_mp_mod_2d.c index fda6335..c25212d 100644 --- a/bn_mp_mod_2d.c +++ b/bn_mp_mod_2d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -20,7 +20,6 @@ mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; - /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); diff --git a/bn_mp_mod_d.c b/bn_mp_mod_d.c index 7ebb61e..c5dbe46 100644 --- a/bn_mp_mod_d.c +++ b/bn_mp_mod_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_montgomery_calc_normalization.c b/bn_mp_montgomery_calc_normalization.c index a1ff2cd..a38555c 100644 --- a/bn_mp_montgomery_calc_normalization.c +++ b/bn_mp_montgomery_calc_normalization.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_montgomery_reduce.c b/bn_mp_montgomery_reduce.c index 99a8a55..3fabaf9 100644 --- a/bn_mp_montgomery_reduce.c +++ b/bn_mp_montgomery_reduce.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_montgomery_setup.c b/bn_mp_montgomery_setup.c index 29aead7..36253af 100644 --- a/bn_mp_montgomery_setup.c +++ b/bn_mp_montgomery_setup.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_mul.c b/bn_mp_mul.c index 6b00235..8153169 100644 --- a/bn_mp_mul.c +++ b/bn_mp_mul.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -20,13 +20,14 @@ mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - + + /* use Toom-Cook? */ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { res = mp_toom_mul(a, b, c); + /* use Karatsuba? */ } else if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else { - /* can we use the fast multiplier? * * The fast multiplier can be used if the output will diff --git a/bn_mp_mul_2.c b/bn_mp_mul_2.c index 2bfc939..6a5b4a7 100644 --- a/bn_mp_mul_2.c +++ b/bn_mp_mul_2.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -61,7 +61,7 @@ mp_mul_2 (mp_int * a, mp_int * b) if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; - ++b->used; + ++(b->used); } /* now zero any excess digits on the destination diff --git a/bn_mp_mul_2d.c b/bn_mp_mul_2d.c index 450f619..072ba33 100644 --- a/bn_mp_mul_2d.c +++ b/bn_mp_mul_2d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -72,7 +72,7 @@ mp_mul_2d (mp_int * a, int b, mp_int * c) /* set final carry */ if (r != 0) { - c->dp[c->used++] = r; + c->dp[(c->used)++] = r; } } mp_clamp (c); diff --git a/bn_mp_mul_d.c b/bn_mp_mul_d.c index 8379035..ae665bc 100644 --- a/bn_mp_mul_d.c +++ b/bn_mp_mul_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_mulmod.c b/bn_mp_mulmod.c index 2e3400a..4b14b24 100644 --- a/bn_mp_mulmod.c +++ b/bn_mp_mulmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_n_root.c b/bn_mp_n_root.c index 0f1bb56..d91f469 100644 --- a/bn_mp_n_root.c +++ b/bn_mp_n_root.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -48,7 +48,7 @@ mp_n_root (mp_int * a, mp_digit b, mp_int * c) } /* if a is negative fudge the sign but keep track */ - neg = a->sign; + neg = a->sign; a->sign = MP_ZPOS; /* t2 = 2 */ diff --git a/bn_mp_neg.c b/bn_mp_neg.c index 73f948a..e710790 100644 --- a/bn_mp_neg.c +++ b/bn_mp_neg.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_or.c b/bn_mp_or.c index 466a171..786a9e5 100644 --- a/bn_mp_or.c +++ b/bn_mp_or.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_prime_fermat.c b/bn_mp_prime_fermat.c index b0e9746..de19676 100644 --- a/bn_mp_prime_fermat.c +++ b/bn_mp_prime_fermat.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -28,7 +28,7 @@ mp_prime_fermat (mp_int * a, mp_int * b, int *result) mp_int t; int err; - /* default to fail */ + /* default to composite */ *result = 0; /* ensure b > 1 */ diff --git a/bn_mp_prime_is_divisible.c b/bn_mp_prime_is_divisible.c index fcad869..cea3d98 100644 --- a/bn_mp_prime_is_divisible.c +++ b/bn_mp_prime_is_divisible.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_prime_is_prime.c b/bn_mp_prime_is_prime.c index f9cece9..21c8619 100644 --- a/bn_mp_prime_is_prime.c +++ b/bn_mp_prime_is_prime.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_prime_miller_rabin.c b/bn_mp_prime_miller_rabin.c index c85136b..ef89125 100644 --- a/bn_mp_prime_miller_rabin.c +++ b/bn_mp_prime_miller_rabin.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_prime_next_prime.c b/bn_mp_prime_next_prime.c index 2072ff2..7dc0e51 100644 --- a/bn_mp_prime_next_prime.c +++ b/bn_mp_prime_next_prime.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -31,9 +31,7 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) } /* force positive */ - if (a->sign == MP_NEG) { - a->sign = MP_ZPOS; - } + a->sign = MP_ZPOS; /* simple algo if a is less than the largest prime in the table */ if (mp_cmp_d(a, __prime_tab[PRIME_SIZE-1]) == MP_LT) { @@ -137,8 +135,8 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) goto __ERR; } - /* if step == MAX then skip test */ - if (step >= ((((mp_digit)1)<= ((((mp_digit)1)< - -/* returns size of ASCII reprensentation */ -int -mp_radix_size (mp_int * a, int radix) -{ - int res, digs; - mp_int t; - mp_digit d; - - /* special case for binary */ - if (radix == 2) { - return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; - } - - if (radix < 2 || radix > 64) { - return 0; - } - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return 0; - } - - digs = 0; - if (t.sign == MP_NEG) { - ++digs; - t.sign = MP_ZPOS; - } - - while (mp_iszero (&t) == 0) { - if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { - mp_clear (&t); - return 0; - } - ++digs; - } - mp_clear (&t); - return digs + 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* returns size of ASCII reprensentation */ +int +mp_radix_size (mp_int * a, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + + /* special case for binary */ + if (radix == 2) { + return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + } + + if (radix < 2 || radix > 64) { + return 0; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return 0; + } + + digs = 0; + if (t.sign == MP_NEG) { + ++digs; + t.sign = MP_ZPOS; + } + + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return 0; + } + ++digs; + } + mp_clear (&t); + return digs + 1; +} + diff --git a/bn_mp_radix_smap.c b/bn_mp_radix_smap.c index 45d02aa..2c4d966 100644 --- a/bn_mp_radix_smap.c +++ b/bn_mp_radix_smap.c @@ -1,18 +1,18 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* chars used in radix conversions */ -const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; diff --git a/bn_mp_rand.c b/bn_mp_rand.c index b944d57..c744994 100644 --- a/bn_mp_rand.c +++ b/bn_mp_rand.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_read_radix.c b/bn_mp_read_radix.c index e32823f..ac87993 100644 --- a/bn_mp_read_radix.c +++ b/bn_mp_read_radix.c @@ -1,77 +1,77 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* read a string [ASCII] in a given radix */ -int -mp_read_radix (mp_int * a, char *str, int radix) -{ - int y, res, neg; - char ch; - - /* make sure the radix is ok */ - if (radix < 2 || radix > 64) { - return MP_VAL; - } - - /* if the leading digit is a - * minus set the sign to negative. - */ - if (*str == '-') { - ++str; - neg = MP_NEG; - } else { - neg = MP_ZPOS; - } - - /* set the integer to the default of zero */ - mp_zero (a); - - /* process each digit of the string */ - while (*str) { - /* if the radix < 36 the conversion is case insensitive - * this allows numbers like 1AB and 1ab to represent the same value - * [e.g. in hex] - */ - ch = (char) ((radix < 36) ? toupper (*str) : *str); - for (y = 0; y < 64; y++) { - if (ch == mp_s_rmap[y]) { - break; - } - } - - /* if the char was found in the map - * and is less than the given radix add it - * to the number, otherwise exit the loop. - */ - if (y < radix) { - if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { - return res; - } - if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { - return res; - } - } else { - break; - } - ++str; - } - - /* set the sign only if a != 0 */ - if (mp_iszero(a) != 1) { - a->sign = neg; - } - return MP_OKAY; -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* read a string [ASCII] in a given radix */ +int +mp_read_radix (mp_int * a, char *str, int radix) +{ + int y, res, neg; + char ch; + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + /* set the integer to the default of zero */ + mp_zero (a); + + /* process each digit of the string */ + while (*str) { + /* if the radix < 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (char) ((radix < 36) ? toupper (*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == mp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != 1) { + a->sign = neg; + } + return MP_OKAY; +} diff --git a/bn_mp_read_signed_bin.c b/bn_mp_read_signed_bin.c index 448e327..7817243 100644 --- a/bn_mp_read_signed_bin.c +++ b/bn_mp_read_signed_bin.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_read_unsigned_bin.c b/bn_mp_read_unsigned_bin.c index 8ca2c11..3b4f5cb 100644 --- a/bn_mp_read_unsigned_bin.c +++ b/bn_mp_read_unsigned_bin.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_reduce.c b/bn_mp_reduce.c index 38689e8..d4c5b10 100644 --- a/bn_mp_reduce.c +++ b/bn_mp_reduce.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_reduce_2k.c b/bn_mp_reduce_2k.c index 91d5f6f..f73d3b9 100644 --- a/bn_mp_reduce_2k.c +++ b/bn_mp_reduce_2k.c @@ -1,56 +1,56 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* reduces a modulo n where n is of the form 2**p - k */ -int -mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) -{ - mp_int q; - int p, res; - - if ((res = mp_init(&q)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(n); -top: - /* q = a/2**p, a = a mod 2**p */ - if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (k != 1) { - /* q = q * k */ - if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { - goto ERR; - } - } - - /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); - goto top; - } - -ERR: - mp_clear(&q); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reduces a modulo n where n is of the form 2**p - k */ +int +mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (k != 1) { + /* q = q * k */ + if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + diff --git a/bn_mp_reduce_2k_setup.c b/bn_mp_reduce_2k_setup.c index 7308c32..6bdfe7f 100644 --- a/bn_mp_reduce_2k_setup.c +++ b/bn_mp_reduce_2k_setup.c @@ -1,42 +1,42 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines the setup value */ -int -mp_reduce_2k_setup(mp_int *a, mp_digit *d) -{ - int res, p; - mp_int tmp; - - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(a); - if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { - mp_clear(&tmp); - return res; - } - - if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { - mp_clear(&tmp); - return res; - } - - *d = tmp.dp[0]; - mp_clear(&tmp); - return MP_OKAY; -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +int +mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} diff --git a/bn_mp_reduce_is_2k.c b/bn_mp_reduce_is_2k.c index 3e4a757..117a8fa 100644 --- a/bn_mp_reduce_is_2k.c +++ b/bn_mp_reduce_is_2k.c @@ -1,38 +1,38 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines if mp_reduce_2k can be used */ -int -mp_reduce_is_2k(mp_int *a) -{ - int ix, iy; - - if (a->used == 0) { - return 0; - } else if (a->used == 1) { - return 1; - } else if (a->used > 1) { - iy = mp_count_bits(a); - for (ix = DIGIT_BIT; ix < iy; ix++) { - if ((a->dp[ix/DIGIT_BIT] & - ((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) { - return 0; - } - } - } - return 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if mp_reduce_2k can be used */ +int +mp_reduce_is_2k(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return 0; + } else if (a->used == 1) { + return 1; + } else if (a->used > 1) { + iy = mp_count_bits(a); + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[ix/DIGIT_BIT] & + ((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) { + return 0; + } + } + } + return 1; +} + diff --git a/bn_mp_reduce_setup.c b/bn_mp_reduce_setup.c index 6f2b8eb..1ba69e9 100644 --- a/bn_mp_reduce_setup.c +++ b/bn_mp_reduce_setup.c @@ -1,29 +1,29 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" - */ -int -mp_reduce_setup (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { - return res; - } - return mp_div (a, b, a, NULL); -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int +mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} diff --git a/bn_mp_rshd.c b/bn_mp_rshd.c index f657ec0..f246a93 100644 --- a/bn_mp_rshd.c +++ b/bn_mp_rshd.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_set.c b/bn_mp_set.c index d749463..dab437f 100644 --- a/bn_mp_set.c +++ b/bn_mp_set.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -20,5 +20,5 @@ mp_set (mp_int * a, mp_digit b) { mp_zero (a); a->dp[0] = b & MP_MASK; - a->used = (a->dp[0] != 0) ? 1 : 0; + a->used = (a->dp[0] != 0) ? 1 : 0; } diff --git a/bn_mp_set_int.c b/bn_mp_set_int.c index a9a37f1..26611aa 100644 --- a/bn_mp_set_int.c +++ b/bn_mp_set_int.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_shrink.c b/bn_mp_shrink.c index 023a46b..ef83aee 100644 --- a/bn_mp_shrink.c +++ b/bn_mp_shrink.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_signed_bin_size.c b/bn_mp_signed_bin_size.c index fe8f499..d392ebc 100644 --- a/bn_mp_signed_bin_size.c +++ b/bn_mp_signed_bin_size.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_sqr.c b/bn_mp_sqr.c index 77539fc..d354c0b 100644 --- a/bn_mp_sqr.c +++ b/bn_mp_sqr.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -19,13 +19,14 @@ int mp_sqr (mp_int * a, mp_int * b) { int res; + /* use Toom-Cook? */ if (a->used >= TOOM_SQR_CUTOFF) { res = mp_toom_sqr(a, b); + /* Karatsuba? */ } else if (a->used >= KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else { - - /* can we use the fast multiplier? */ + /* can we use the fast comba multiplier? */ if ((a->used * 2 + 1) < MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { diff --git a/bn_mp_sqrmod.c b/bn_mp_sqrmod.c index c32d562..778b68e 100644 --- a/bn_mp_sqrmod.c +++ b/bn_mp_sqrmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -21,7 +21,6 @@ mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) int res; mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { return res; } diff --git a/bn_mp_sub.c b/bn_mp_sub.c index 2bc4123..eb99583 100644 --- a/bn_mp_sub.c +++ b/bn_mp_sub.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_sub_d.c b/bn_mp_sub_d.c index 2fd8bdb..d9938f4 100644 --- a/bn_mp_sub_d.c +++ b/bn_mp_sub_d.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -45,7 +45,11 @@ mp_sub_d (mp_int * a, mp_digit b, mp_int * c) /* if a <= b simply fix the single digit */ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { - *tmpc++ = b - *tmpa; + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } ix = 1; /* negative/1digit */ diff --git a/bn_mp_submod.c b/bn_mp_submod.c index 1606ff0..868dd2f 100644 --- a/bn_mp_submod.c +++ b/bn_mp_submod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_to_signed_bin.c b/bn_mp_to_signed_bin.c index 023c80f..1e21667 100644 --- a/bn_mp_to_signed_bin.c +++ b/bn_mp_to_signed_bin.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_to_unsigned_bin.c b/bn_mp_to_unsigned_bin.c index 54e0739..f7cae69 100644 --- a/bn_mp_to_unsigned_bin.c +++ b/bn_mp_to_unsigned_bin.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_toom_mul.c b/bn_mp_toom_mul.c index 63f253c..2ba4624 100644 --- a/bn_mp_toom_mul.c +++ b/bn_mp_toom_mul.c @@ -1,273 +1,273 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* multiplication using the Toom-Cook 3-way algorithm */ -int -mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) -{ - mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; - int res, B; - - /* init temps */ - if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, - &a0, &a1, &a2, &b0, &b1, - &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { - return res; - } - - /* B */ - B = MIN(a->used, b->used) / 3; - - /* a = a2 * B**2 + a1 * B + a0 */ - if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a1, B); - mp_mod_2d(&a1, DIGIT_BIT * B, &a1); - - if ((res = mp_copy(a, &a2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a2, B*2); - - /* b = b2 * B**2 + b1 * B + b0 */ - if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(b, &b1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&b1, B); - mp_mod_2d(&b1, DIGIT_BIT * B, &b1); - - if ((res = mp_copy(b, &b2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&b2, B*2); - - /* w0 = a0*b0 */ - if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { - goto ERR; - } - - /* w4 = a2 * b2 */ - if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { - goto ERR; - } - - /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ - if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { - goto ERR; - } - - /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ - if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { - goto ERR; - } - - - /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ - if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { - goto ERR; - } - - /* now solve the matrix - - 0 0 0 0 1 - 1 2 4 8 16 - 1 1 1 1 1 - 16 8 4 2 1 - 1 0 0 0 0 - - using 12 subtractions, 4 shifts, - 2 small divisions and 1 small multiplication - */ - - /* r1 - r4 */ - if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r0 */ - if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/2 */ - if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3/2 */ - if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { - goto ERR; - } - /* r2 - r0 - r4 */ - if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1 - 8r0 */ - if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - 8r4 */ - if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - /* 3r2 - r1 - r3 */ - if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/3 */ - if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { - goto ERR; - } - /* r3/3 */ - if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { - goto ERR; - } - - /* at this point shift W[n] by B*n */ - if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear_multi(&w0, &w1, &w2, &w3, &w4, - &a0, &a1, &a2, &b0, &b1, - &b2, &tmp1, &tmp2, NULL); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiplication using the Toom-Cook 3-way algorithm */ +int +mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = MIN(a->used, b->used) / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* b = b2 * B**2 + b1 * B + b0 */ + if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(b, &b1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b1, B); + mp_mod_2d(&b1, DIGIT_BIT * B, &b1); + + if ((res = mp_copy(b, &b2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b2, B*2); + + /* w0 = a0*b0 */ + if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * b2 */ + if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, + 2 small divisions and 1 small multiplication + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL); + return res; +} + diff --git a/bn_mp_toom_sqr.c b/bn_mp_toom_sqr.c index bccf709..7db1592 100644 --- a/bn_mp_toom_sqr.c +++ b/bn_mp_toom_sqr.c @@ -1,220 +1,220 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* squaring using Toom-Cook 3-way algorithm */ -int -mp_toom_sqr(mp_int *a, mp_int *b) -{ - mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; - int res, B; - - /* init temps */ - if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { - return res; - } - - /* B */ - B = a->used / 3; - - /* a = a2 * B^2 + a1 * B + a0 */ - if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a1, B); - mp_mod_2d(&a1, DIGIT_BIT * B, &a1); - - if ((res = mp_copy(a, &a2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a2, B*2); - - /* w0 = a0*a0 */ - if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { - goto ERR; - } - - /* w4 = a2 * a2 */ - if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { - goto ERR; - } - - /* w1 = (a2 + 2(a1 + 2a0))**2 */ - if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - - /* w3 = (a0 + 2(a1 + 2a2))**2 */ - if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - - - /* w2 = (a2 + a1 + a0)**2 */ - if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { - goto ERR; - } - - /* now solve the matrix - - 0 0 0 0 1 - 1 2 4 8 16 - 1 1 1 1 1 - 16 8 4 2 1 - 1 0 0 0 0 - - using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. - */ - - /* r1 - r4 */ - if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r0 */ - if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/2 */ - if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3/2 */ - if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { - goto ERR; - } - /* r2 - r0 - r4 */ - if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1 - 8r0 */ - if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - 8r4 */ - if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - /* 3r2 - r1 - r3 */ - if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/3 */ - if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { - goto ERR; - } - /* r3/3 */ - if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { - goto ERR; - } - - /* at this point shift W[n] by B*n */ - if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* squaring using Toom-Cook 3-way algorithm */ +int +mp_toom_sqr(mp_int *a, mp_int *b) +{ + mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = a->used / 3; + + /* a = a2 * B^2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* w0 = a0*a0 */ + if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * a2 */ + if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))**2 */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))**2 */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)**2 */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); + return res; +} + diff --git a/bn_mp_toradix.c b/bn_mp_toradix.c index 52097b1..2c52dd6 100644 --- a/bn_mp_toradix.c +++ b/bn_mp_toradix.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_unsigned_bin_size.c b/bn_mp_unsigned_bin_size.c index 558efb0..47bbc64 100644 --- a/bn_mp_unsigned_bin_size.c +++ b/bn_mp_unsigned_bin_size.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_xor.c b/bn_mp_xor.c index 6622074..36e6733 100644 --- a/bn_mp_xor.c +++ b/bn_mp_xor.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_mp_zero.c b/bn_mp_zero.c index c86cabd..a888589 100644 --- a/bn_mp_zero.c +++ b/bn_mp_zero.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_prime_tab.c b/bn_prime_tab.c index 83c5469..7dfdc8c 100644 --- a/bn_prime_tab.c +++ b/bn_prime_tab.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_reverse.c b/bn_reverse.c index 4e785c4..89cbbb7 100644 --- a/bn_reverse.c +++ b/bn_reverse.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_s_mp_add.c b/bn_s_mp_add.c index cf677d8..e07931a 100644 --- a/bn_s_mp_add.c +++ b/bn_s_mp_add.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_s_mp_exptmod.c b/bn_s_mp_exptmod.c index 931d49f..68c91e7 100644 --- a/bn_s_mp_exptmod.c +++ b/bn_s_mp_exptmod.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -105,7 +105,9 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) } } - /* create upper table */ + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto __MU; @@ -132,15 +134,17 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ if (digidx == -1) { break; } - buf = X->dp[digidx--]; + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; bitcnt = (int) DIGIT_BIT; } /* grab the next msb from the exponent */ - y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it @@ -148,8 +152,9 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ - if (mode == 0 && y == 0) + if (mode == 0 && y == 0) { continue; + } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { @@ -164,7 +169,7 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; + mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ @@ -189,7 +194,7 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* empty window and reset */ bitcpy = 0; bitbuf = 0; - mode = 1; + mode = 1; } } diff --git a/bn_s_mp_mul_digs.c b/bn_s_mp_mul_digs.c index cb3dbd7..2d78a2d 100644 --- a/bn_s_mp_mul_digs.c +++ b/bn_s_mp_mul_digs.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_s_mp_mul_high_digs.c b/bn_s_mp_mul_high_digs.c index a0c2c0e..4e4d536 100644 --- a/bn_s_mp_mul_high_digs.c +++ b/bn_s_mp_mul_high_digs.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_s_mp_sqr.c b/bn_s_mp_sqr.c index d45a00e..9bf3ef1 100644 --- a/bn_s_mp_sqr.c +++ b/bn_s_mp_sqr.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bn_s_mp_sub.c b/bn_s_mp_sub.c index 32a01d9..4381af8 100644 --- a/bn_s_mp_sub.c +++ b/bn_s_mp_sub.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/bncore.c b/bncore.c index 8ca206a..acb78a0 100644 --- a/bncore.c +++ b/bncore.c @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/changes.txt b/changes.txt index 8508424..fbbd0a2 100644 --- a/changes.txt +++ b/changes.txt @@ -1,3 +1,16 @@ +Aug 4th, 2003 +v0.25 -- Fix to mp_gcd again... oops (0,-a) == (-a, 0) == a + -- Fix to mp_clear which didn't reset the sign [Greg Rose] + -- Added mp_error_to_string() to convert return codes to strings. [Greg Rose] + -- Optimized fast_mp_invmod() to do the test for invalid inputs [both even] + first so temps don't have to be initialized if it's going to fail. + -- Optimized mp_gcd() by removing mp_div_2d calls for when one of the inputs + is odd. + -- Tons of new comments, some indentation fixups, etc. + -- mp_jacobi() returns MP_VAL if the modulus is less than or equal to zero. + -- fixed two typos in the header of each file :-) + -- LibTomMath is officially Public Domain [see LICENSE] + July 15th, 2003 v0.24 -- Optimized mp_add_d and mp_sub_d to not allocate temporary variables -- Fixed mp_gcd() so the gcd of 0,0 is 0. Allows the gcd operation to be chained diff --git a/demo/demo.c b/demo/demo.c index 0691efb..7da356c 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -181,7 +181,6 @@ int main(void) #ifdef TIMER /* temp. turn off TOOM */ TOOM_MUL_CUTOFF = TOOM_SQR_CUTOFF = 100000; - printf("CLOCKS_PER_SEC == %lu\n", CLOCKS_PER_SEC); log = fopen("logs/add.log", "w"); @@ -225,21 +224,6 @@ int main(void) KARATSUBA_MUL_CUTOFF = (ix==0)?9999:old_kara_m; KARATSUBA_SQR_CUTOFF = (ix==0)?9999:old_kara_s; - log = fopen((ix==0)?"logs/sqr.log":"logs/sqr_kara.log", "w"); - for (cnt = 32; cnt <= 288; cnt += 16) { - mp_rand(&a, cnt); - reset(); - rr = 0; - do { - DO(mp_sqr(&a, &b)); - rr += 16; - } while (rdtsc() < (CLOCKS_PER_SEC * 2)); - tt = rdtsc(); - printf("Squaring\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); - fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); - } - fclose(log); - log = fopen((ix==0)?"logs/mult.log":"logs/mult_kara.log", "w"); for (cnt = 32; cnt <= 288; cnt += 16) { mp_rand(&a, cnt); @@ -255,6 +239,22 @@ int main(void) fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); } fclose(log); + + log = fopen((ix==0)?"logs/sqr.log":"logs/sqr_kara.log", "w"); + for (cnt = 32; cnt <= 288; cnt += 16) { + mp_rand(&a, cnt); + reset(); + rr = 0; + do { + DO(mp_sqr(&a, &b)); + rr += 16; + } while (rdtsc() < (CLOCKS_PER_SEC * 2)); + tt = rdtsc(); + printf("Squaring\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); + fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); + } + fclose(log); + } { char *primes[] = { diff --git a/etc/2kprime.1 b/etc/2kprime.1 index e1384db..c41ded1 100644 --- a/etc/2kprime.1 +++ b/etc/2kprime.1 @@ -1 +1,2 @@ -259-bits (k = 17745) = 926336713898529563388567880069503262826159877325124512315660672063305037101743 +256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823 +512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979 diff --git a/etc/pprime.c b/etc/pprime.c index 9360a09..389e1fa 100644 --- a/etc/pprime.c +++ b/etc/pprime.c @@ -59,7 +59,6 @@ static void gen_prime (void) r += 2; /* next candidate */ r &= MP_MASK; if (r < 31) break; - if (!((r>>1)&65535)) sleep(1); /* update sqrt ? */ if (next <= r) { diff --git a/logs/mult.log b/logs/mult.log index 4b1bff3..e69de29 100644 --- a/logs/mult.log +++ b/logs/mult.log @@ -1,17 +0,0 @@ -896 322904 -1344 151592 -1792 90472 -2240 59984 -2688 42624 -3136 31872 -3584 24704 -4032 19704 -4480 16096 -4928 13376 -5376 11272 -5824 9616 -6272 8360 -6720 7304 -7168 1664 -7616 1472 -8064 1328 diff --git a/makefile b/makefile index c939c8b..9de5e56 100644 --- a/makefile +++ b/makefile @@ -1,9 +1,12 @@ #Makefile for GCC # #Tom St Denis -CFLAGS += -I./ -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops +CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops -VERSION=0.24 +#x86 optimizations [should be valid for any GCC install though] +CFLAGS += -fomit-frame-pointer + +VERSION=0.25 default: libtommath.a @@ -35,12 +38,13 @@ bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_un bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \ bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \ bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \ -bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o bn_mp_multi.o \ +bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \ bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \ bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ -bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o +bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ +bn_mp_init_multi.o bn_mp_clear_multi.o libtommath.a: $(OBJECTS) $(AR) $(ARFLAGS) libtommath.a $(OBJECTS) @@ -106,6 +110,6 @@ clean: zipup: clean manual poster perl gen.pl ; mv mpi.c pre_gen/ ; \ cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \ - cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; cp tdcal.pdf ./libtommath-$(VERSION)/ ; cd ./libtommath-$(VERSION) ; rm -f tommath.src tommath.tex tommath.out ; cd pics ; rm -f *.tif *.ps *.pdf ; cd .. ; cd .. ; ls ; \ + cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; cd ./libtommath-$(VERSION) ; rm -f tommath.src tommath.tex tommath.out ; cd pics ; rm -f *.tif *.ps *.pdf ; cd .. ; cd .. ; ls ; \ tar -c libtommath-$(VERSION)/* > ltm-$(VERSION).tar ; \ bzip2 -9vv ltm-$(VERSION).tar ; zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/* diff --git a/makefile.bcc b/makefile.bcc index b227e8d..2a6b0b5 100644 --- a/makefile.bcc +++ b/makefile.bcc @@ -23,17 +23,18 @@ bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \ bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \ bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \ -bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj bn_mp_multi.obj \ +bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \ bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \ bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \ bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ -bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj +bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ +bn_mp_init_multi.obj bn_mp_clear_multi.obj TARGET = libtommath.lib $(TARGET): $(OBJECTS) -.c.obj: +.c.objbj: $(CC) $(CFLAGS) $< - $(LIB) $(TARGET) -+$@ \ No newline at end of file + $(LIB) $(TARGET) -+$@ diff --git a/makefile.msvc b/makefile.msvc index 0af7c89..df655dd 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -22,12 +22,13 @@ bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \ bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \ bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \ -bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj bn_mp_multi.obj \ +bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \ bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \ bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \ bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ -bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj +bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ +bn_mp_init_multi.obj bn_mp_clear_multi.obj library: $(OBJECTS) lib /out:tommath.lib $(OBJECTS) diff --git a/pics/design_process.sxd b/pics/design_process.sxd new file mode 100644 index 0000000000000000000000000000000000000000..7414dbb27696fe716fe8c73a5c2b21d8c3e0c23c GIT binary patch literal 6950 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 literal 0 HcmV?d00001 diff --git a/pics/makefile b/pics/makefile index 07bbca9..18c3d44 100644 --- a/pics/makefile +++ b/pics/makefile @@ -1,30 +1,35 @@ -# makes the images... yeah - -default: pses - - -sliding_window.ps: sliding_window.tif - tiff2ps -c -e sliding_window.tif > sliding_window.ps - -expt_state.ps: expt_state.tif - tiff2ps -c -e expt_state.tif > expt_state.ps - -primality.ps: primality.tif - tiff2ps -c -e primality.tif > primality.ps - -sliding_window.pdf: sliding_window.ps - epstopdf sliding_window.ps - -expt_state.pdf: expt_state.ps - epstopdf expt_state.ps - -primality.pdf: primality.ps - epstopdf primality.ps - - -pses: sliding_window.ps expt_state.ps primality.ps -pdfes: sliding_window.pdf expt_state.pdf primality.pdf - -clean: - rm -rf *.ps *.pdf .xvpics +# makes the images... yeah + +default: pses + +design_process.ps: design_process.tif + tiff2ps -c -e design_process.tif > design_process.ps + +sliding_window.ps: sliding_window.tif + tiff2ps -c -e sliding_window.tif > sliding_window.ps + +expt_state.ps: expt_state.tif + tiff2ps -c -e expt_state.tif > expt_state.ps + +primality.ps: primality.tif + tiff2ps -c -e primality.tif > primality.ps + +design_process.pdf: design_process.ps + epstopdf design_process.ps + +sliding_window.pdf: sliding_window.ps + epstopdf sliding_window.ps + +expt_state.pdf: expt_state.ps + epstopdf expt_state.ps + +primality.pdf: primality.ps + epstopdf primality.ps + + +pses: sliding_window.ps expt_state.ps primality.ps design_process.ps +pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf + +clean: + rm -rf *.ps *.pdf .xvpics \ No newline at end of file diff --git a/poster.pdf b/poster.pdf index 1b6ce6efda3ad1a2c66674345ad53fd5491636d7..1d25593205012250dc541846db51b117a9ceaf7f 100644 GIT binary patch delta 7798 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 IwUsdcA9<&gZ2$lO delta 7884 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 N1EVuC%Bsns{|`%xy08EM diff --git a/pre_gen/mpi.c b/pre_gen/mpi.c index 2f7a853..4e748f8 100644 --- a/pre_gen/mpi.c +++ b/pre_gen/mpi.c @@ -1,10 +1,55 @@ +/* Start: bn_error.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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +static const struct { + int code; + char *msg; +} msgs[] = { + { MP_OKAY, "Successful" }, + { MP_MEM, "Out of heap" }, + { MP_VAL, "Value out of range" } +}; + +/* return a char * string for a given code */ +char *mp_error_to_string(int code) +{ + int x; + + /* scan the lookup table for the given message */ + for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { + if (msgs[x].code == code) { + return msgs[x].msg; + } + } + + /* generic reply for invalid code */ + return "Invalid error code"; +} + + +/* End: bn_error.c */ + /* Start: bn_fast_mp_invmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -27,6 +72,14 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) mp_int x, y, u, v, B, D; int res, neg; + /* 2. [modified] if a,b are both even then return an error! + * + * That is if gcd(a,b) = 2**k * q then obviously there is no inverse. + */ + if (mp_iseven (a) == 1 && mp_iseven (b) == 1) { + return MP_VAL; + } + /* init all our temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { return res; @@ -42,15 +95,6 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) goto __ERR; } - /* 2. [modified] if x,y are both even then return an error! - * - * That is if gcd(x,y) = 2 * k then obviously there is no inverse. - */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto __ERR; - } - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto __ERR; @@ -152,10 +196,10 @@ __ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); /* Start: bn_fast_mp_montgomery_reduce.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -190,6 +234,9 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } } + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ { register mp_word *_W; register mp_digit *tmpx; @@ -208,6 +255,9 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } } + /* now we proceed to zero successive digits + * from the least significant upwards + */ for (ix = 0; ix < n->used; ix++) { /* mu = ai * m' mod b * @@ -253,12 +303,20 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); } + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ { register mp_digit *tmpx; register mp_word *_W, *_W1; /* nox fix rest of carries */ + + /* alias for current word */ _W1 = W + ix; + + /* alias for next word, where the carry goes */ _W = W + ++ix; for (; ix <= n->used * 2 + 1; ix++) { @@ -271,7 +329,11 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * array of mp_word to mp_digit than calling mp_rshd * we just copy them in the right order */ + + /* alias for destination word */ tmpx = x->dp; + + /* alias for shifted double precision result */ _W = W + n->used; for (ix = 0; ix < n->used + 1; ix++) { @@ -279,7 +341,8 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits */ + * m->used+1 we'll have to clear the digits + */ for (; ix < olduse; ix++) { *tmpx++ = 0; } @@ -301,10 +364,10 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) /* Start: bn_fast_s_mp_mul_digs.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -435,10 +498,10 @@ fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* Start: bn_fast_s_mp_mul_high_digs.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -447,7 +510,7 @@ fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) * * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org */ -#include + #include /* this is a modified version of fast_s_mp_mul_digs that only produces * output digits *above* digs. See the comments for fast_s_mp_mul_digs @@ -537,10 +600,10 @@ fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* Start: bn_fast_s_mp_sqr.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -585,14 +648,14 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) /* zero temp buffer (columns) * Note that there are two buffers. Since squaring requires - * a outter and inner product and the inner product requires + * a outer and inner product and the inner product requires * computing a product and doubling it (a relatively expensive * op to perform n**2 times if you don't have to) the inner and * outer products are computed in different buffers. This way * the inner product can be doubled using n doublings instead of * n**2 */ - memset (W, 0, newused * sizeof (mp_word)); + memset (W, 0, newused * sizeof (mp_word)); memset (W2, 0, newused * sizeof (mp_word)); /* This computes the inner product. To simplify the inner N**2 loop @@ -604,6 +667,7 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) * Note that every outer product is computed * for a particular column only once which means that * there is no need todo a double precision addition + * into the W2[] array. */ W2[ix + ix] = ((mp_word)a->dp[ix]) * ((mp_word)a->dp[ix]); @@ -632,7 +696,12 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) olduse = b->used; b->used = newused; - /* now compute digits */ + /* now compute digits + * + * We have to double the inner product sums, add in the + * outer product sums, propagate carries and convert + * to single precision. + */ { register mp_digit *tmpb; @@ -646,16 +715,21 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) /* double/add next digit */ W[ix] += W[ix] + W2[ix]; + /* propagate carry forwards [from the previous digit] */ W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + + /* store the current digit now that the carry isn't + * needed + */ *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); } - /* set the last value. Note even if the carry is zero - * this is required since the next step will not zero + /* set the last value. Note even if the carry is zero + * this is required since the next step will not zero * it if b originally had a value at b->dp[2*a.used] */ *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); - /* clear high digits */ + /* clear high digits of b if there were any originally */ for (; ix < olduse; ix++) { *tmpb++ = 0; } @@ -670,10 +744,10 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) /* Start: bn_mp_2expt.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -694,11 +768,18 @@ mp_2expt (mp_int * a, int b) { int res; + /* zero a as per default */ mp_zero (a); + + /* grow a to accomodate the single bit */ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } + + /* set the used count of where the bit will go */ a->used = b / DIGIT_BIT + 1; + + /* put the single bit in its place */ a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT); return MP_OKAY; @@ -709,10 +790,10 @@ mp_2expt (mp_int * a, int b) /* Start: bn_mp_abs.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -731,10 +812,17 @@ int mp_abs (mp_int * a, mp_int * b) { int res; - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } } + + /* force the sign of b to positive */ b->sign = MP_ZPOS; + return MP_OKAY; } @@ -743,10 +831,10 @@ mp_abs (mp_int * a, mp_int * b) /* Start: bn_mp_add.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -795,10 +883,10 @@ mp_add (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_add_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -877,7 +965,11 @@ mp_add_d (mp_int * a, mp_digit b, mp_int * c) c->used = 1; /* the result is a single digit */ - *tmpc++ = b - a->dp[0]; + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } /* setup count so the clearing of oldused * can fall through correctly @@ -900,10 +992,10 @@ mp_add_d (mp_int * a, mp_digit b, mp_int * c) /* Start: bn_mp_addmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -939,10 +1031,10 @@ mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) /* Start: bn_mp_and.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -994,10 +1086,10 @@ mp_and (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_clamp.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1018,9 +1110,14 @@ mp_and (mp_int * a, mp_int * b, mp_int * c) void mp_clamp (mp_int * a) { + /* decrease used while the most significant digit is + * zero. + */ while (a->used > 0 && a->dp[a->used - 1] == 0) { --(a->used); } + + /* reset the sign flag if used == 0 */ if (a->used == 0) { a->sign = MP_ZPOS; } @@ -1031,11 +1128,11 @@ mp_clamp (mp_int * a) /* Start: bn_mp_clear.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with + * 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 @@ -1049,6 +1146,7 @@ mp_clamp (mp_int * a) void mp_clear (mp_int * a) { + /* only do anything if a hasn't been freed previously */ if (a->dp != NULL) { /* first zero the digits */ memset (a->dp, 0, sizeof (mp_digit) * a->used); @@ -1059,18 +1157,51 @@ mp_clear (mp_int * a) /* reset members to make debugging easier */ a->dp = NULL; a->alloc = a->used = 0; + a->sign = MP_ZPOS; } } /* End: bn_mp_clear.c */ +/* Start: bn_mp_clear_multi.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@iahu.ca, http://math.libtomcrypt.org + */ +#include +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} + +/* End: bn_mp_clear_multi.c */ + /* Start: bn_mp_cmp.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1108,10 +1239,10 @@ mp_cmp (mp_int * a, mp_int * b) /* Start: bn_mp_cmp_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1126,15 +1257,17 @@ mp_cmp (mp_int * a, mp_int * b) int mp_cmp_d (mp_int * a, mp_digit b) { - + /* compare based on sign */ if (a->sign == MP_NEG) { return MP_LT; } + /* compare based on magnitude */ if (a->used > 1) { return MP_GT; } + /* compare the only digit of a to b */ if (a->dp[0] > b) { return MP_GT; } else if (a->dp[0] < b) { @@ -1149,10 +1282,10 @@ mp_cmp_d (mp_int * a, mp_digit b) /* Start: bn_mp_cmp_mag.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1196,10 +1329,10 @@ mp_cmp_mag (mp_int * a, mp_int * b) /* Start: bn_mp_cnt_lsb.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1216,6 +1349,7 @@ int mp_cnt_lsb(mp_int *a) int x; mp_digit q; + /* easy out */ if (mp_iszero(a) == 1) { return 0; } @@ -1240,10 +1374,10 @@ int mp_cnt_lsb(mp_int *a) /* Start: bn_mp_copy.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1266,8 +1400,10 @@ mp_copy (mp_int * a, mp_int * b) } /* grow dest */ - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } } /* zero b and copy the parameters over */ @@ -1275,7 +1411,11 @@ mp_copy (mp_int * a, mp_int * b) register mp_digit *tmpa, *tmpb; /* pointer aliases */ + + /* source */ tmpa = a->dp; + + /* destination */ tmpb = b->dp; /* copy all the digits */ @@ -1288,6 +1428,8 @@ mp_copy (mp_int * a, mp_int * b) *tmpb++ = 0; } } + + /* copy used count and sign */ b->used = a->used; b->sign = a->sign; return MP_OKAY; @@ -1298,10 +1440,10 @@ mp_copy (mp_int * a, mp_int * b) /* Start: bn_mp_count_bits.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1341,10 +1483,10 @@ mp_count_bits (mp_int * a) /* Start: bn_mp_div.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1556,10 +1698,10 @@ __Q:mp_clear (&q); /* Start: bn_mp_div_2.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1623,10 +1765,10 @@ mp_div_2 (mp_int * a, mp_int * b) /* Start: bn_mp_div_2d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1719,10 +1861,10 @@ mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) /* Start: bn_mp_div_3.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1754,10 +1896,17 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); - + if (w >= 3) { + /* multiply w by [1/3] */ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + + /* now subtract 3 * [w/3] from w, to get the remainder */ w -= (t << ((mp_word)1)) + t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ while (w >= 3) { t += 1; w -= 3; @@ -1767,11 +1916,13 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) } q.dp[ix] = (mp_digit)t; } - + + /* [optional] store the remainder */ if (d != NULL) { *d = (mp_digit)w; } - + + /* [optional] store the quotient */ if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); @@ -1787,10 +1938,10 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) /* Start: bn_mp_div_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1892,50 +2043,53 @@ mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) /* End: bn_mp_div_d.c */ /* Start: bn_mp_dr_is_modulus.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines if a number is a valid DR modulus */ -int mp_dr_is_modulus(mp_int *a) -{ - int ix; - - /* must be at least two digits */ - if (a->used < 2) { - return 0; - } - - for (ix = 1; ix < a->used; ix++) { - if (a->dp[ix] != MP_MASK) { - return 0; - } - } - return 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + /* End: bn_mp_dr_is_modulus.c */ /* Start: bn_mp_dr_reduce.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -1989,7 +2143,7 @@ top: /* set carry to zero */ mu = 0; - /* compute (x mod B**m) + mp * [x/B**m] inline and inplace */ + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ for (i = 0; i < m; i++) { r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; *tmpx1++ = (mp_digit)(r & MP_MASK); @@ -2020,42 +2174,42 @@ top: /* End: bn_mp_dr_reduce.c */ /* Start: bn_mp_dr_setup.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines the setup value */ -void mp_dr_setup(mp_int *a, mp_digit *d) -{ - /* the casts are required if DIGIT_BIT is one less than - * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] - */ - *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - - ((mp_word)a->dp[0])); -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + /* End: bn_mp_dr_setup.c */ /* Start: bn_mp_exch.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2074,7 +2228,7 @@ mp_exch (mp_int * a, mp_int * b) { mp_int t; - t = *a; + t = *a; *a = *b; *b = t; } @@ -2084,10 +2238,10 @@ mp_exch (mp_int * a, mp_int * b) /* Start: bn_mp_expt_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2140,10 +2294,10 @@ mp_expt_d (mp_int * a, mp_digit b, mp_int * c) /* Start: bn_mp_exptmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2200,7 +2354,10 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) return err; } + /* is it a DR modulus? */ dr = mp_dr_is_modulus(P); + + /* if not, is it a uDR modulus? */ if (dr == 0) { dr = mp_reduce_is_2k(P) << 1; } @@ -2209,6 +2366,7 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) if (mp_isodd (P) == 1 || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { + /* otherwise use the generic Barrett reduction technique */ return s_mp_exptmod (G, X, P, Y); } } @@ -2219,10 +2377,10 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* Start: bn_mp_exptmod_fast.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2313,15 +2471,15 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else { - /* use slower baselien method */ + /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; } } else if (redmode == 1) { - /* setup DR reduction */ + /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; } else { - /* setup 2k reduction */ + /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto __M; } @@ -2330,7 +2488,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { - goto __RES; + goto __M; } /* create M table @@ -2392,15 +2550,17 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ if (digidx == -1) { break; } - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; } /* grab the next msb from the exponent */ - y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it @@ -2425,7 +2585,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; + mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ @@ -2450,7 +2610,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) /* empty window and reset */ bitcpy = 0; bitbuf = 0; - mode = 1; + mode = 1; } } @@ -2465,6 +2625,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) goto __RES; } + /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ @@ -2479,12 +2640,18 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) } if (redmode == 0) { - /* fixup result if Montgomery reduction is used */ + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) { goto __RES; } } + /* swap res with Y */ mp_exch (&res, Y); err = MP_OKAY; __RES:mp_clear (&res); @@ -2499,77 +2666,77 @@ __M: /* End: bn_mp_exptmod_fast.c */ /* Start: bn_mp_fread.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* read a bigint from a file stream in ASCII */ -int mp_fread(mp_int *a, int radix, FILE *stream) -{ - int err, ch, neg, y; - - /* clear a */ - mp_zero(a); - - /* if first digit is - then set negative */ - ch = fgetc(stream); - if (ch == '-') { - neg = MP_NEG; - ch = fgetc(stream); - } else { - neg = MP_ZPOS; - } - - for (;;) { - /* find y in the radix map */ - for (y = 0; y < radix; y++) { - if (mp_s_rmap[y] == ch) { - break; - } - } - if (y == radix) { - break; - } - - /* shift up and add */ - if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { - return err; - } - if ((err = mp_add_d(a, y, a)) != MP_OKAY) { - return err; - } - - ch = fgetc(stream); - } - if (mp_cmp_d(a, 0) != MP_EQ) { - a->sign = neg; - } - - return MP_OKAY; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* read a bigint from a file stream in ASCII */ +int mp_fread(mp_int *a, int radix, FILE *stream) +{ + int err, ch, neg, y; + + /* clear a */ + mp_zero(a); + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == '-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + for (;;) { + /* find y in the radix map */ + for (y = 0; y < radix; y++) { + if (mp_s_rmap[y] == ch) { + break; + } + } + if (y == radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + + ch = fgetc(stream); + } + if (mp_cmp_d(a, 0) != MP_EQ) { + a->sign = neg; + } + + return MP_OKAY; +} + /* End: bn_mp_fread.c */ /* Start: bn_mp_fwrite.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2617,10 +2784,10 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream) /* Start: bn_mp_gcd.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2640,16 +2807,21 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) /* either zero than gcd is the largest */ if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { - return mp_copy (b, c); + return mp_abs (b, c); } if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { - return mp_copy (a, c); + return mp_abs (a, c); } - if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { + + /* optimized. At this point if a == 0 then + * b must equal zero too + */ + if (mp_iszero (a) == 1) { mp_zero(c); return MP_OKAY; } + /* get copies of a and b we can modify */ if ((res = mp_init_copy (&u, a)) != MP_OKAY) { return res; } @@ -2666,12 +2838,15 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) v_lsb = mp_cnt_lsb(&v); k = MIN(u_lsb, v_lsb); - if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { - goto __V; - } + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto __V; + } - if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { - goto __V; + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto __V; + } } /* divide any remaining factors of two out */ @@ -2686,10 +2861,11 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) goto __V; } } - + while (mp_iszero(&v) == 0) { /* make sure v is the largest */ if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ mp_exch(&u, &v); } @@ -2703,10 +2879,10 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) goto __V; } } - - /* multiply by 2**k which we divided out at the beginning */ + + /* multiply by 2**k which we divided out at the beginning */ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { - goto __V; + goto __V; } c->sign = MP_ZPOS; res = MP_OKAY; @@ -2720,10 +2896,10 @@ __U:mp_clear (&v); /* Start: bn_mp_grow.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2743,7 +2919,7 @@ mp_grow (mp_int * a, int size) /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* ensure there are always at least MP_PREC digits extra on top */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + size += (MP_PREC * 2) - (size % MP_PREC); a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * size); if (a->dp == NULL) { @@ -2765,11 +2941,11 @@ mp_grow (mp_int * a, int size) /* Start: bn_mp_init.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with + * 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 @@ -2783,7 +2959,7 @@ mp_grow (mp_int * a, int size) int mp_init (mp_int * a) { - /* allocate ram required and clear it */ + /* allocate memory required and clear it */ a->dp = OPT_CAST calloc (sizeof (mp_digit), MP_PREC); if (a->dp == NULL) { return MP_MEM; @@ -2803,10 +2979,10 @@ mp_init (mp_int * a) /* Start: bn_mp_init_copy.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2831,13 +3007,68 @@ mp_init_copy (mp_int * a, mp_int * b) /* End: bn_mp_init_copy.c */ +/* Start: bn_mp_init_multi.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@iahu.ca, http://math.libtomcrypt.org + */ +#include +#include + +int mp_init_multi(mp_int *mp, ...) +{ + mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ + int n = 0; /* Number of ok inits */ + mp_int* cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + if (mp_init(cur_arg) != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* end the current list */ + va_end(args); + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n--) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int*); + } + va_end(clean_args); + res = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int*); + } + va_end(args); + return res; /* Assumed ok, if error flagged above. */ +} +/* End: bn_mp_init_multi.c */ + /* Start: bn_mp_init_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -2848,22 +3079,21 @@ mp_init_copy (mp_int * a, mp_int * b) */ #include -/* init a mp_init and grow it to a given size */ +/* init an mp_init for a given size */ int mp_init_size (mp_int * a, int size) { - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ a->dp = OPT_CAST calloc (sizeof (mp_digit), size); if (a->dp == NULL) { return MP_MEM; } - a->used = 0; + a->used = 0; a->alloc = size; - a->sign = MP_ZPOS; + a->sign = MP_ZPOS; return MP_OKAY; } @@ -2873,10 +3103,10 @@ mp_init_size (mp_int * a, int size) /* Start: bn_mp_invmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3052,10 +3282,10 @@ __ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); /* Start: bn_mp_jacobi.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3076,6 +3306,11 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) int k, s, r, res; mp_digit residue; + /* if p <= 0 return MP_VAL */ + if (mp_cmp_d(p, 0) != MP_GT) { + return MP_VAL; + } + /* step 1. if a == 0, return 0 */ if (mp_iszero (a) == 1) { *c = 0; @@ -3089,7 +3324,7 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) } /* default */ - k = s = 0; + s = 0; /* step 3. write a = a1 * 2**k */ if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { @@ -3100,11 +3335,10 @@ mp_jacobi (mp_int * a, mp_int * p, int *c) goto __A1; } - while (mp_iseven (&a1) == 1) { - k = k + 1; - if ((res = mp_div_2 (&a1, &a1)) != MP_OKAY) { - goto __P1; - } + /* divide out larger power of two */ + k = mp_cnt_lsb(&a1); + if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) { + goto __P1; } /* step 4. if e is even set s=1 */ @@ -3152,10 +3386,10 @@ __A1:mp_clear (&a1); /* Start: bn_mp_karatsuba_mul.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3321,10 +3555,10 @@ ERR: /* Start: bn_mp_karatsuba_sqr.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3441,10 +3675,10 @@ ERR: /* Start: bn_mp_lcm.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3487,10 +3721,10 @@ mp_lcm (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_lshd.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3553,10 +3787,10 @@ mp_lshd (mp_int * a, int b) /* Start: bn_mp_mod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3600,10 +3834,10 @@ mp_mod (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_mod_2d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3620,7 +3854,6 @@ mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; - /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); @@ -3654,10 +3887,10 @@ mp_mod_2d (mp_int * a, int b, mp_int * c) /* Start: bn_mp_mod_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3679,10 +3912,10 @@ mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) /* Start: bn_mp_montgomery_calc_normalization.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3736,10 +3969,10 @@ mp_montgomery_calc_normalization (mp_int * a, mp_int * b) /* Start: bn_mp_montgomery_reduce.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3828,10 +4061,10 @@ mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) /* Start: bn_mp_montgomery_setup.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3885,10 +4118,10 @@ mp_montgomery_setup (mp_int * n, mp_digit * rho) /* Start: bn_mp_mul.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3905,13 +4138,14 @@ mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - + + /* use Toom-Cook? */ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { res = mp_toom_mul(a, b, c); + /* use Karatsuba? */ } else if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else { - /* can we use the fast multiplier? * * The fast multiplier can be used if the output will @@ -3938,10 +4172,10 @@ mp_mul (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_mul_2.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -3999,7 +4233,7 @@ mp_mul_2 (mp_int * a, mp_int * b) if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; - ++b->used; + ++(b->used); } /* now zero any excess digits on the destination @@ -4019,10 +4253,10 @@ mp_mul_2 (mp_int * a, mp_int * b) /* Start: bn_mp_mul_2d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4091,7 +4325,7 @@ mp_mul_2d (mp_int * a, int b, mp_int * c) /* set final carry */ if (r != 0) { - c->dp[c->used++] = r; + c->dp[(c->used)++] = r; } } mp_clamp (c); @@ -4103,10 +4337,10 @@ mp_mul_2d (mp_int * a, int b, mp_int * c) /* Start: bn_mp_mul_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4179,10 +4413,10 @@ mp_mul_d (mp_int * a, mp_digit b, mp_int * c) /* Start: bn_mp_mulmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4216,81 +4450,13 @@ mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) /* End: bn_mp_mulmod.c */ -/* Start: bn_mp_multi.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include -#include - -int mp_init_multi(mp_int *mp, ...) -{ - mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ - int n = 0; /* Number of ok inits */ - mp_int* cur_arg = mp; - va_list args; - - va_start(args, mp); /* init args to next argument from caller */ - while (cur_arg != NULL) { - if (mp_init(cur_arg) != MP_OKAY) { - /* Oops - error! Back-track and mp_clear what we already - succeeded in init-ing, then return error. - */ - va_list clean_args; - - /* end the current list */ - va_end(args); - - /* now start cleaning up */ - cur_arg = mp; - va_start(clean_args, mp); - while (n--) { - mp_clear(cur_arg); - cur_arg = va_arg(clean_args, mp_int*); - } - va_end(clean_args); - res = MP_MEM; - break; - } - n++; - cur_arg = va_arg(args, mp_int*); - } - va_end(args); - return res; /* Assumed ok, if error flagged above. */ -} - -void mp_clear_multi(mp_int *mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_clear(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} - -/* End: bn_mp_multi.c */ - /* Start: bn_mp_n_root.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4335,7 +4501,7 @@ mp_n_root (mp_int * a, mp_digit b, mp_int * c) } /* if a is negative fudge the sign but keep track */ - neg = a->sign; + neg = a->sign; a->sign = MP_ZPOS; /* t2 = 2 */ @@ -4418,10 +4584,10 @@ __T1:mp_clear (&t1); /* Start: bn_mp_neg.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4449,10 +4615,10 @@ mp_neg (mp_int * a, mp_int * b) /* Start: bn_mp_or.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4498,10 +4664,10 @@ mp_or (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_prime_fermat.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4526,7 +4692,7 @@ mp_prime_fermat (mp_int * a, mp_int * b, int *result) mp_int t; int err; - /* default to fail */ + /* default to composite */ *result = 0; /* ensure b > 1 */ @@ -4559,10 +4725,10 @@ __T:mp_clear (&t); /* Start: bn_mp_prime_is_divisible.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4608,10 +4774,10 @@ mp_prime_is_divisible (mp_int * a, int *result) /* Start: bn_mp_prime_is_prime.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4690,10 +4856,10 @@ __B:mp_clear (&b); /* Start: bn_mp_prime_miller_rabin.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4792,10 +4958,10 @@ __N1:mp_clear (&n1); /* Start: bn_mp_prime_next_prime.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -4823,9 +4989,7 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) } /* force positive */ - if (a->sign == MP_NEG) { - a->sign = MP_ZPOS; - } + a->sign = MP_ZPOS; /* simple algo if a is less than the largest prime in the table */ if (mp_cmp_d(a, __prime_tab[PRIME_SIZE-1]) == MP_LT) { @@ -4929,8 +5093,8 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) goto __ERR; } - /* if step == MAX then skip test */ - if (step >= ((((mp_digit)1)<= ((((mp_digit)1)< - -/* returns size of ASCII reprensentation */ -int -mp_radix_size (mp_int * a, int radix) -{ - int res, digs; - mp_int t; - mp_digit d; - - /* special case for binary */ - if (radix == 2) { - return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; - } - - if (radix < 2 || radix > 64) { - return 0; - } - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return 0; - } - - digs = 0; - if (t.sign == MP_NEG) { - ++digs; - t.sign = MP_ZPOS; - } - - while (mp_iszero (&t) == 0) { - if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { - mp_clear (&t); - return 0; - } - ++digs; - } - mp_clear (&t); - return digs + 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* returns size of ASCII reprensentation */ +int +mp_radix_size (mp_int * a, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + + /* special case for binary */ + if (radix == 2) { + return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + } + + if (radix < 2 || radix > 64) { + return 0; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return 0; + } + + digs = 0; + if (t.sign == MP_NEG) { + ++digs; + t.sign = MP_ZPOS; + } + + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return 0; + } + ++digs; + } + mp_clear (&t); + return digs + 1; +} + /* End: bn_mp_radix_size.c */ /* Start: bn_mp_radix_smap.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* chars used in radix conversions */ -const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; /* End: bn_mp_radix_smap.c */ /* Start: bn_mp_rand.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5093,93 +5257,93 @@ mp_rand (mp_int * a, int digits) /* End: bn_mp_rand.c */ /* Start: bn_mp_read_radix.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* read a string [ASCII] in a given radix */ -int -mp_read_radix (mp_int * a, char *str, int radix) -{ - int y, res, neg; - char ch; - - /* make sure the radix is ok */ - if (radix < 2 || radix > 64) { - return MP_VAL; - } - - /* if the leading digit is a - * minus set the sign to negative. - */ - if (*str == '-') { - ++str; - neg = MP_NEG; - } else { - neg = MP_ZPOS; - } - - /* set the integer to the default of zero */ - mp_zero (a); - - /* process each digit of the string */ - while (*str) { - /* if the radix < 36 the conversion is case insensitive - * this allows numbers like 1AB and 1ab to represent the same value - * [e.g. in hex] - */ - ch = (char) ((radix < 36) ? toupper (*str) : *str); - for (y = 0; y < 64; y++) { - if (ch == mp_s_rmap[y]) { - break; - } - } - - /* if the char was found in the map - * and is less than the given radix add it - * to the number, otherwise exit the loop. - */ - if (y < radix) { - if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { - return res; - } - if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { - return res; - } - } else { - break; - } - ++str; - } - - /* set the sign only if a != 0 */ - if (mp_iszero(a) != 1) { - a->sign = neg; - } - return MP_OKAY; -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* read a string [ASCII] in a given radix */ +int +mp_read_radix (mp_int * a, char *str, int radix) +{ + int y, res, neg; + char ch; + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + /* set the integer to the default of zero */ + mp_zero (a); + + /* process each digit of the string */ + while (*str) { + /* if the radix < 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (char) ((radix < 36) ? toupper (*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == mp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != 1) { + a->sign = neg; + } + return MP_OKAY; +} /* End: bn_mp_read_radix.c */ /* Start: bn_mp_read_signed_bin.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5208,10 +5372,10 @@ mp_read_signed_bin (mp_int * a, unsigned char *b, int c) /* Start: bn_mp_read_unsigned_bin.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5251,10 +5415,10 @@ mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c) /* Start: bn_mp_reduce.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5337,193 +5501,193 @@ CLEANUP: /* End: bn_mp_reduce.c */ /* Start: bn_mp_reduce_2k.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* reduces a modulo n where n is of the form 2**p - k */ -int -mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) -{ - mp_int q; - int p, res; - - if ((res = mp_init(&q)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(n); -top: - /* q = a/2**p, a = a mod 2**p */ - if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (k != 1) { - /* q = q * k */ - if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { - goto ERR; - } - } - - /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); - goto top; - } - -ERR: - mp_clear(&q); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reduces a modulo n where n is of the form 2**p - k */ +int +mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (k != 1) { + /* q = q * k */ + if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + /* End: bn_mp_reduce_2k.c */ /* Start: bn_mp_reduce_2k_setup.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines the setup value */ -int -mp_reduce_2k_setup(mp_int *a, mp_digit *d) -{ - int res, p; - mp_int tmp; - - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(a); - if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { - mp_clear(&tmp); - return res; - } - - if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { - mp_clear(&tmp); - return res; - } - - *d = tmp.dp[0]; - mp_clear(&tmp); - return MP_OKAY; -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +int +mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} /* End: bn_mp_reduce_2k_setup.c */ /* Start: bn_mp_reduce_is_2k.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines if mp_reduce_2k can be used */ -int -mp_reduce_is_2k(mp_int *a) -{ - int ix, iy; - - if (a->used == 0) { - return 0; - } else if (a->used == 1) { - return 1; - } else if (a->used > 1) { - iy = mp_count_bits(a); - for (ix = DIGIT_BIT; ix < iy; ix++) { - if ((a->dp[ix/DIGIT_BIT] & - ((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) { - return 0; - } - } - } - return 1; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if mp_reduce_2k can be used */ +int +mp_reduce_is_2k(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return 0; + } else if (a->used == 1) { + return 1; + } else if (a->used > 1) { + iy = mp_count_bits(a); + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[ix/DIGIT_BIT] & + ((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) { + return 0; + } + } + } + return 1; +} + /* End: bn_mp_reduce_is_2k.c */ /* Start: bn_mp_reduce_setup.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" - */ -int -mp_reduce_setup (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { - return res; - } - return mp_div (a, b, a, NULL); -} +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int +mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} /* End: bn_mp_reduce_setup.c */ /* Start: bn_mp_rshd.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5591,10 +5755,10 @@ mp_rshd (mp_int * a, int b) /* Start: bn_mp_set.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5611,7 +5775,7 @@ mp_set (mp_int * a, mp_digit b) { mp_zero (a); a->dp[0] = b & MP_MASK; - a->used = (a->dp[0] != 0) ? 1 : 0; + a->used = (a->dp[0] != 0) ? 1 : 0; } /* End: bn_mp_set.c */ @@ -5619,10 +5783,10 @@ mp_set (mp_int * a, mp_digit b) /* Start: bn_mp_set_int.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5665,10 +5829,10 @@ mp_set_int (mp_int * a, unsigned int b) /* Start: bn_mp_shrink.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5697,10 +5861,10 @@ mp_shrink (mp_int * a) /* Start: bn_mp_signed_bin_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5723,10 +5887,10 @@ mp_signed_bin_size (mp_int * a) /* Start: bn_mp_sqr.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5742,13 +5906,14 @@ int mp_sqr (mp_int * a, mp_int * b) { int res; + /* use Toom-Cook? */ if (a->used >= TOOM_SQR_CUTOFF) { res = mp_toom_sqr(a, b); + /* Karatsuba? */ } else if (a->used >= KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else { - - /* can we use the fast multiplier? */ + /* can we use the fast comba multiplier? */ if ((a->used * 2 + 1) < MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { @@ -5766,10 +5931,10 @@ mp_sqr (mp_int * a, mp_int * b) /* Start: bn_mp_sqrmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5787,7 +5952,6 @@ mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) int res; mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { return res; } @@ -5806,10 +5970,10 @@ mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_sub.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5863,10 +6027,10 @@ mp_sub (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_sub_d.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5908,7 +6072,11 @@ mp_sub_d (mp_int * a, mp_digit b, mp_int * c) /* if a <= b simply fix the single digit */ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { - *tmpc++ = b - *tmpa; + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } ix = 1; /* negative/1digit */ @@ -5945,10 +6113,10 @@ mp_sub_d (mp_int * a, mp_digit b, mp_int * c) /* Start: bn_mp_submod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -5985,10 +6153,10 @@ mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) /* Start: bn_mp_to_signed_bin.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6017,10 +6185,10 @@ mp_to_signed_bin (mp_int * a, unsigned char *b) /* Start: bn_mp_to_unsigned_bin.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6062,513 +6230,513 @@ mp_to_unsigned_bin (mp_int * a, unsigned char *b) /* End: bn_mp_to_unsigned_bin.c */ /* Start: bn_mp_toom_mul.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* multiplication using the Toom-Cook 3-way algorithm */ -int -mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) -{ - mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; - int res, B; - - /* init temps */ - if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, - &a0, &a1, &a2, &b0, &b1, - &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { - return res; - } - - /* B */ - B = MIN(a->used, b->used) / 3; - - /* a = a2 * B**2 + a1 * B + a0 */ - if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a1, B); - mp_mod_2d(&a1, DIGIT_BIT * B, &a1); - - if ((res = mp_copy(a, &a2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a2, B*2); - - /* b = b2 * B**2 + b1 * B + b0 */ - if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(b, &b1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&b1, B); - mp_mod_2d(&b1, DIGIT_BIT * B, &b1); - - if ((res = mp_copy(b, &b2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&b2, B*2); - - /* w0 = a0*b0 */ - if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { - goto ERR; - } - - /* w4 = a2 * b2 */ - if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { - goto ERR; - } - - /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ - if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { - goto ERR; - } - - /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ - if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { - goto ERR; - } - - - /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ - if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { - goto ERR; - } - - /* now solve the matrix - - 0 0 0 0 1 - 1 2 4 8 16 - 1 1 1 1 1 - 16 8 4 2 1 - 1 0 0 0 0 - - using 12 subtractions, 4 shifts, - 2 small divisions and 1 small multiplication - */ - - /* r1 - r4 */ - if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r0 */ - if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/2 */ - if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3/2 */ - if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { - goto ERR; - } - /* r2 - r0 - r4 */ - if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1 - 8r0 */ - if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - 8r4 */ - if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - /* 3r2 - r1 - r3 */ - if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/3 */ - if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { - goto ERR; - } - /* r3/3 */ - if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { - goto ERR; - } - - /* at this point shift W[n] by B*n */ - if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear_multi(&w0, &w1, &w2, &w3, &w4, - &a0, &a1, &a2, &b0, &b1, - &b2, &tmp1, &tmp2, NULL); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiplication using the Toom-Cook 3-way algorithm */ +int +mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = MIN(a->used, b->used) / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* b = b2 * B**2 + b1 * B + b0 */ + if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(b, &b1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b1, B); + mp_mod_2d(&b1, DIGIT_BIT * B, &b1); + + if ((res = mp_copy(b, &b2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b2, B*2); + + /* w0 = a0*b0 */ + if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * b2 */ + if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, + 2 small divisions and 1 small multiplication + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL); + return res; +} + /* End: bn_mp_toom_mul.c */ /* Start: bn_mp_toom_sqr.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is 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@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* squaring using Toom-Cook 3-way algorithm */ -int -mp_toom_sqr(mp_int *a, mp_int *b) -{ - mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; - int res, B; - - /* init temps */ - if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { - return res; - } - - /* B */ - B = a->used / 3; - - /* a = a2 * B^2 + a1 * B + a0 */ - if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a1, B); - mp_mod_2d(&a1, DIGIT_BIT * B, &a1); - - if ((res = mp_copy(a, &a2)) != MP_OKAY) { - goto ERR; - } - mp_rshd(&a2, B*2); - - /* w0 = a0*a0 */ - if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { - goto ERR; - } - - /* w4 = a2 * a2 */ - if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { - goto ERR; - } - - /* w1 = (a2 + 2(a1 + 2a0))**2 */ - if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - - /* w3 = (a0 + 2(a1 + 2a2))**2 */ - if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - - - /* w2 = (a2 + a1 + a0)**2 */ - if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { - goto ERR; - } - - /* now solve the matrix - - 0 0 0 0 1 - 1 2 4 8 16 - 1 1 1 1 1 - 16 8 4 2 1 - 1 0 0 0 0 - - using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. - */ - - /* r1 - r4 */ - if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r0 */ - if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/2 */ - if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3/2 */ - if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { - goto ERR; - } - /* r2 - r0 - r4 */ - if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1 - 8r0 */ - if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - 8r4 */ - if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { - goto ERR; - } - /* 3r2 - r1 - r3 */ - if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { - goto ERR; - } - /* r1 - r2 */ - if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { - goto ERR; - } - /* r3 - r2 */ - if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { - goto ERR; - } - /* r1/3 */ - if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { - goto ERR; - } - /* r3/3 */ - if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { - goto ERR; - } - - /* at this point shift W[n] by B*n */ - if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { - goto ERR; - } - - if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { - goto ERR; - } - if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); - return res; -} - +/* 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@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* squaring using Toom-Cook 3-way algorithm */ +int +mp_toom_sqr(mp_int *a, mp_int *b) +{ + mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = a->used / 3; + + /* a = a2 * B^2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* w0 = a0*a0 */ + if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * a2 */ + if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))**2 */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))**2 */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)**2 */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); + return res; +} + /* End: bn_mp_toom_sqr.c */ /* Start: bn_mp_toradix.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6639,10 +6807,10 @@ mp_toradix (mp_int * a, char *str, int radix) /* Start: bn_mp_unsigned_bin_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6666,10 +6834,10 @@ mp_unsigned_bin_size (mp_int * a) /* Start: bn_mp_xor.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6715,10 +6883,10 @@ mp_xor (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_mp_zero.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6743,10 +6911,10 @@ mp_zero (mp_int * a) /* Start: bn_prime_tab.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6802,10 +6970,10 @@ const mp_digit __prime_tab[] = { /* Start: bn_reverse.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6839,10 +7007,10 @@ bn_reverse (unsigned char *s, int len) /* Start: bn_s_mp_add.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -6946,10 +7114,10 @@ s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* Start: bn_s_mp_exptmod.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -7051,7 +7219,9 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) } } - /* create upper table */ + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto __MU; @@ -7078,15 +7248,17 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ if (digidx == -1) { break; } - buf = X->dp[digidx--]; + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; bitcnt = (int) DIGIT_BIT; } /* grab the next msb from the exponent */ - y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it @@ -7094,8 +7266,9 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ - if (mode == 0 && y == 0) + if (mode == 0 && y == 0) { continue; + } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { @@ -7110,7 +7283,7 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; + mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ @@ -7135,7 +7308,7 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* empty window and reset */ bitcpy = 0; bitbuf = 0; - mode = 1; + mode = 1; } } @@ -7180,10 +7353,10 @@ __M: /* Start: bn_s_mp_mul_digs.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -7269,10 +7442,10 @@ s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* Start: bn_s_mp_mul_high_digs.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -7345,10 +7518,10 @@ s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* Start: bn_s_mp_sqr.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -7426,10 +7599,10 @@ s_mp_sqr (mp_int * a, mp_int * b) /* Start: bn_s_mp_sub.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -7513,10 +7686,10 @@ s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* Start: bncore.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * diff --git a/tdcal.pdf b/tdcal.pdf deleted file mode 100644 index e4f4b35d72b373c6d41963aa62da5856b0c0d3a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56674 zcmbSyWmH_-vMw6j-QA^ecXx;2-nhHFy95Xh!5xA-1PBhn-QC?GJhIQ(_wM`N{c*EI`82 z#s%m^43Mxfasi3~P3%p9umS?G&Mr1dd+b; z;}q5-dU-UU6RQsWdlcq^Gl5=bTe`vWq8QOWW$ZFS!tu4y?}u%E2Pt#y3Q`h89(D1I zaYp&-YZ2@*XM#otV>o&_Oke!VOo;_`)rTQtw=y&g^G{tG7>os~;Ms=1H>#)}8}f#!XOO$sCg_#JFNdO8qT>yk=YWzd9t zCFygsGzB{3PEiNZ43u~ z9xGj&bZt5K^pxh2XXPc}L9)6-uCLqY-6xc+C7gWOl{Z|>*oVSa5?#P<2_f0tyNapI zf4OjBXw+P$44Q?+;Q!*re(Cl|LSpG&-w&Fw;J2x4sK(ynTngpFi>bj?ogSc)=VaPm zj(4G&r-Cc#AL4uI^L?N9TUJH$@ehqh<}$LfEALH!%a-LdIjJ{uD`1LZ@TKW{yKS6e z;7Tp)R61)gaSFV#N;J|tapAecfdx9TZG_1pBiMqxhcVlV-&4pBLImT2YOB zQMd3kzROCzt2CF=;RMDuqrpitT2; zl>~4PX5?huLT_VEzpN8f-GKwsK9P-RR9lv)vJvLtqpDRg^@g8z)ysHqlOS}#*kznp zpnU{%yT#uXz8?~-*Mn4dZ$KB}$`s9}Yb+PivMX?zyp|54#>Bz_qwqgT0GFrC5Zo=2 z#d7x{1z3SNNYaBsJtF0v9xR2oz8pV^QC-*JwqX+dz)wLGfvN9Gu4mY>Cs< zc5Q_+`%%zd5qGeEtRuOugs5-LHNV)6k&l(_o>H!dpvRYlycKs1K;5i?PbM~(d~NOK zyH-%>_+1UVpylw441&3S!qGy>r?CTd4X(ulYfQRHS}dFOXy)WJ=cbZw7|Mqqp*PCQ zgwNS$`Ya?JHp_Qz$9-Zfys}~ZH(zm*ioRzaT`>&PHMg^@cgUx%9~VQwt4oyRppv0Bdt>K6Ld@~ z9K$Ug*=1}K-r@1gs%J*A!_Z_BdPrOK#h?ZoJM4mJw~~h3-fU%pDO zw^)e%Y87clPbZwBn!=qc#|O;_OGB2nothcU31%y3v*NdT)jhOmf6R=Rb&8P-YPH#L zVeKV>eeW#{$;Ue=*b_i}2W=Pd>n7#0-%0Pq<~D#6zg6%VtmWMVgF1D(4|z%I=qZ8= zlRP-%2EpG4D@iLAnrBqO-7=8~Q{Y!+f9Q*+)lkdVj@-ck`vdL(vX)^>I%upD!wJH3A0IAwPxEoSBJ5kr+ z(~Z<%9Rea@-oS~tXYVNNt3v&kINl9SWAChmjtE_w?AbLRrkA*^s1h=04)kNyW|!+s z3~{Rl#e~Jyofkx|fz^Qvn=rA@@+;5hiV6~Y8(9Ov?6SC zvWUraaXDzz!G$K&qF<)E+^h`fQUxPah<>?XOR3%Wwttr<;2r&yRju#t3OUT|DHMzB zRP@WoS-c4~`ou8hVR4hct^^2|=;R z>7saDrGWF^v&Yzi3Z&|+f~c+C#RkZ)HcFHRNeA3gytVMBB1tHk%Dn1EKH_hllR9d} zRN5$FHls02Y_RIfrP9F;dB@Co84U5pt+-=;9V&KJg}cTFP2KmGKb%Ca7?++8Rv+&?!9blbIys=mY2B>h|^a~-vefmcP)w{-6zOs$rwOKkV)b- z@D&b8Y1D1>vWw0dz#E_U>5}Id*Rd~OjdHf%C=;Ts3zfTetuPC!?ko1|WVMoKjw}G4 z4zNzI{|a?Ziu{2CO#f}+KdwH|0W8ZuP=cDL1CSV?WMmG61&G?)xd824oQeOy2o+d> z3eef!)yV|tOw9Z*fjrRE(n!SKgII^@L%`0>&d9>aLCnR*%*e&92m3LK(?@q=mOtaG zd;kmLf9w0x`)^bt@uA}bo_t^sW_DtZKMns}au9R>`;vu&nE9{%A7U=zk2e2m!AZ=_ z^>+(SVwS(=L;L|<07_2wCaOReVx5mgh)ECw)PNo?#Crcw&hlr7zqS93iCCFf{!>hp zq9q@{!-d%SP*Yj}?!uSY?OSy z>&;2|49GcWvL9~!oG|6lvlVHvF#0^tmPnaZFy&=MPBm3;hTi!)3xuUw%cSLJP^cPx zibu|elV3N1^+n<@b;3pSmT@eF+k|X^FgcAto+-EYhufO)wZ8eUwQ}OoM9A&1_9t1y4suRmakfj?uNC@JQHq6^isTBFR@8BCQ&vg|pO%F= zBfn+!{kpN&kzXZ4jC(`AcA|tCCD*Ea^5`|?Dj^slfQ-?;8L!vY_sQ=Gb5DPF zul?69N;cp=Fmzilu;}pxDdWLi?oLm_izJiWD0Pr0ZlB}(C1hgQ+d?Nat+!1F1CPV( zr}_JkYtun_Mwj72o6-n+b@DQ8+MN^yxEV^6r-o-r*x48kNi5O$*jg;OU zYF}C(`0d?gd6gzmnW|<#=hy$wa`F<#DmEFJ1d!CNddK-qxo_X+NOS_G*B<(%$T< zrlA1&`j6d-JQM4^4$DXdIqC5!dr*wr&GdH^tZGYNR?4}iR?&!3hrQ70$o(iJk+MFs@|xXs>wll{s^7*YuAvEryG8OUdo~t6VV1yo!)(Bt21p=f7$WwE z5_RhQ1fr;6U%|=;VgIBLqS~lVNLgrdzj6BkkBSCmj$lMg0Mx7eid~3y&#>j6v_6$- znHagj3@??{R_ak1c@o_dV2ChR3MZ~7(fed8%Irx1F&pMA$d(toD^KXJ`CQ_z&y9w! zpjvF$x8v>7H1#PH5F5T)ifr1D7d_iC*hDobCqHozU_YZk_+~lB!sm3uEJz!iIEk}Ug~xs+Qjb%gG6!bql?Khe6&FOgm3D8fO#y(w zZfyu5=`JYmmmzQC7azJ}j~TPXb0( zvfb8ra66yF4lx>&rOi&h7F?gr<*Jq-6~nE78Xw5?tl=-Hxm*w-_%}FfvibuVZ3#{w zQ43A3sxMd&R@sW<-#>u@eX<9(K3hNVH9_G~Wdp?3Ob`0@bjm?!X@(iHBqQgY8Vgd{ zCmQ4))| zF38QDYw7G9c(+5^w_~}TJ9Nt|&QUnvJ<>F8)Y7SwS9Ik>a&a?XP0Wp@$zi3YIT}^n zlX21I(Mj~Pm?7p?9c1;fk>eTFhueqOEPgYazmziF$j|7}n;ku2Vik~XLo$Y+Ymd%E z+=<5^;|>|J86a&9q_Ae?#VW9?j{GS30x6=rZehk&Qxpg&WdqL1kLT%k%QyirsVrG0 z3Ftv|Oz%NF1O*TJuLdW%AD;3&%*%Z)qfIl-tro|TmA88-u~5o*dkP=br_ z7b*FVcD^+@^YS1AmY&>-GGALU@>a${;6?M|rimVIJuVAZ-_O3ejI2 z@f|j%sqO29ee3gzyI=Iz?9+!6p>~R~m#0AMx0d=)?6eS9mwZf(q6~67Oaal@dAzc+ zZF3_CL;oc&Cwa-|LjSri`aiv0n0MTVQZ(`JF2Fs1`}5vq+wtB-vZ)^zqo974{cI$Y z2<2F|sx{5+oM0;MS}aNVcrb;Bwie_0-V6<1a(++hAFx`!(>Y7jPaB#5av@_wbZp(! zAYcXEqilr1pQiX~W0Ix1(1^>+3g(ekz}4ihWvE8wU(R;ic=OKwG9mCC2*fr=A8}M* z)c7ufqAlR-`+Vz9^2zV<|3!{${{U0}D|Gw|Zv7AJ$ntMA`Tq$X|LXoXe*16q_z!Hz z@?U@uAi=^#{PFo0X8b3V{4f0YA7Mt;eVs2KlD2_$_>$YJn*n}?f*W$#og89ouTKt#O;TY!5MRXcv^ry$d_OtPqL2A8F zo(R{r<@3)*_)uCIHQ!h0p$kkKtKK!9ywH*=f71@SmP*VZoyccVl&|d6%pG)9O2`(M z^KEff??}DrzSqCqyqR>-29d^YJ-anV{veJQaeEHTI;2;l@M|uok#wSGdENGBsyZ4? zhM(B|`p`?c!!u$D#W8Ejgr5HlTEy*oa7Q^JHkUkpF@u*b*u(T=x-lFrt1z_uOi6e{ z&m%LqY@>>ExJrW;*FYi*@+#a&i9G2`6P~4IQn~X6fo0Nw9PhPA_JI|Wq+T$0`my{B zNgGiU|4{jrMgMGStZ;-h;{j!+*mQM4&~^hV=ryf1t2*h>)#B64)bw|XR?Hjm*)J)6 z(3qs})Rz2HY&^bMSmj4y%7tfrZ{do_&W=-OtvTq=GZ{(R_enN#zCi>=iB$Tv1sw6dJ?=FEEYpRo^l9gODoyk8_@e+z}Q^ySP?Fe?qbH}I3NMJ5t z-ClT(sCl-y+Qm5wEez=P;A{n>W{NGqgn#2$WkG(3S#cb}tq`TbZU0S(%=JUg_iiY` z6&l0;vwMX79KTw~IraElI{R!)8k+1O8RAje_~UB`O>P1&Yn(|sySkm7cwJofE0Ttf zNuj|#m|B)!#$laYdH%{v->#qFID?gkYDgy?j>m>Hd`NqBM51wALEbNwlpo65{6Y)A z!cmRG5#^uh)|~?uv?{yS!rF*dHyvn8>hY9eq!VgGRpNrTX3xksd_9o^%RXx~2ZsaT zRUCW2S^VyV{%j;RTo;={iz;!grW$d>qxc2RwW5xMfCN)4y@`btr6prhixU;c%yiQ7 zXD;M1@7R;b4pg1iXEjtwHbKR5XjQ{^!udYO?RfYvHWle?Ecu_9BOK^kvH1Nqn{^Ib zk3e`7W`|FeNq$6QbWw8;lTpwW{O&x_ThdQRb(8AfAi&yIcLz>_z>x7$y0b-?^MvlP zaAnC5$FO3C3i*#18hF|5;FUQ$<1^4Jm1x1N8mEiJL-U0vha{SO#XiZ+hQD!yg1t#=}c&46sW@p5_GJN)SWadxy>kh`^lXKT^ zMt(P;Vu*U+r-fdzE!z!+ImuF6J-74>Wqj^Dbt`W5N_oe-2JFfxJ17JgQ)00!#$V8- z5_goxd^}}^1~HC-$_#j-g|j@0HCKqvoHeyKdd#2UC5RSpns)NYTP*A*ei$s)Og^99 z7ejzA=qj)!%pb?kcM@`i_3DYrd7tamDe+G)3;#yw&^Lp{0v-^-s4uXIXr=I>4?knt zU$<|7dA-tpqjbwk#}v+@^bqeCCb191PR-nC=6nagPBD=Ee=HB{pNPZXX5fFdJb(RZ z|4+;FS5N^K@c(Oh{&fFa<$qhAf0~v5vO@onS@|$j|2^Qp%nCCx7d!jkTn!5`3p*#* z-z8RJc2<_Z3&gCSQICh1=3kJN!=IOkcc#mEaQAn6$Oss)AA=fPrPTna|3b@=59RCU;M7xyGHLi z&re>GlbdQ)W_uH}FR57~KkoLRGH@wXJvMmQo-cVydI?$hNkM~3Fs4a_VNsu<4533< z0)Ft;A)P7`RF@;FgAapBeW%J6ad0dGyBIK0Em4(c@WQ0J4z7|bJ8BT}K`ppn?bM;Cl z-ly8J^bO>RAe{=NNeVw*tPq^5gB99X!c4KRzVVgH^er2IPn0~vh|llW1=n3X-_Ky7 z!gqb)`^($>ZJGcYobZx_-}+Y3@A6rU>5uWu5^C^?0dpj+$X6h@&B(oY;+K6p^w4UR zbel0GUOVpF9;oLRsEa?(paXQpG71pR6yCaKvI`-@guZFd@W033OWq-dy+tmaD?$79 zP*AVvW49-~{dWBRzQW{-ni@lvpbG+Q!41e)Vsb%#xvxdRzYGV3Kt;TO+I(A#B9S3y zNm&D{Wq^Um8b<#WANpgl68SZL@d6o92--hT5EOYkH{lHpdD?`8~0wXO#-sW0XV&9k@@*KKZ3wcC8~jbYb1m^wS9dExdE~xpLha^}#wb%w%$Jz8Hlv z!19-Qc6LD=u=#UOsk)4w|E~8QC5T?ay!M*E@bFLF_wb6;xMSnjJ!8X7k!WbeRCbgT zUsmB7sGyd)!=3s3s6onEFBr4s7F%;Zn~C8RJh@(_+f`Y3Mu(rNne!Ff{;CwEyeH=h z33WL?@Ge=s1Ow%AekeW0og$rGe9pHxK_xP^HQHYBgEM*aIpJg^%J$TCHMN$AUs9*f zUz!Pmi6xpl?x^LSZCGdre~bY=KPvC^OHV;Cgvcs9;$a`42%~rqmnpU z-&|ufI7sl=^t#I*%+vw`SfAGz3Z_nNp4f}9pVq!3^zzW%nE9GlEwc*ChOp(f?cmF# zH;eMqawgDnk_Cx#ZL3vF4uZQETE0y@$sFgl@T2Ao>St2VWcf2&>N^XlL*sKx?HMHA z&pF*???!yBB;IY(9e3Xsn5Bl$_byHWj~=Frx>3767|j)gU@4lqgl;k`haW@Pr+i$%0bf}OR5qVx5J=Q?JoL;>my{g5;l zJb2Y*taX=^RKrm{=fKq8>>(5m`q%GTke%708FR_b7eSigpNFo|-;!WO&g7t=OXM<( z5E~vC_o$kJ@4DFQT0+GUIW(8_wfPaf2d}?X2;8QK^S4H=o#YUnL)~8IsVIvuhbV=o|MR;_yvoq9RQ*dq&gy1qeVnrvJ)OX;L}s zo!?-Jdv=9B?xl`${FX(tiA3oh>Sq}0<@;*^04EgbJ2J7-r?lGG(>YXQRIxEM0x$fH zHS3)1qHUG<8(9%9ufMG!iJ|W(DFM%&equlSIf2*;1Lr#FdqRyyK*uE1E4xW*z{G}G zL-;~^msuPK-65Ae)yaYRW0a?C(^3l_hmP;zN?Kd0g~9ibU8+cuk~EO|N@@f>nTgkj zv(BZ37<`QCueQz2w_}8idwg}Z^UjJYp5li``CNN9D$V#})C+_X6OjZahce~MF9hl- z{E{ZK+eN9?o+9gl$HF^+pJ&V4jcxYx>{u%0slS|F;ml{mirp>s=-!J*Qn%t0|ys< zl$6?HBQP{Apikj*87!4JF^RV-)0x(f_J^|uCRUGv77uqSD6_;q?q~G}`OX|F!}o1W z0^2mDbL1;PhPUMUJQp>V-&nl;Obp0?OJRSbsx94aLtO%-;652tf_X)$e^l6G$`FXK zQ6sF`Vm(zFFQU}*h#Dh5JT(n@!=NS;CxIdaDW#(4Pamg-%cqvyt@Haj>r$IqIQRbQ zc<=YBW@yg9rIG2xMGvj&M7XF`q{s=LLLoGx7uv&Jt>R)eP@DY)6$&a7N* zo(6(+r-~8ssd2vePtIeV_I>q11SUmtie-C&1{YOScl@O;WTTDP ztpd=PlI-Z63>Z9{d+!JsF6U_mGB@NsnUJ_?EMqF>j0TH>xo*u|CQq3$5EG307C_PJW<(hLIu^CLBJ*0)FT?htyuQQne z2UOUAtfubK0aT+kKVDMg{J?bNrh-X-4f>S{rUD&}uli5E#PNY)OJ$)?^qL2O(9*<4K9t5k>3ThJsAB zU)90egLOe39r_oDX^eth6Kv>XyAOLb;Xv`5YxN0Ae$Rr<+6jpsj8|9QZlvWouaQ!qQZw@X+nGdYP$spm zFXFL&bcf)LmD0v3>w%a_mz*~>2M%{3_F=$d*;D=~EH{FLES5!$osWRi!AKBpt~&19 z%F(TGK1*Ukng9(W97jPS9??AYXwh7?BpOOysbtHc0k*1qgWguqMX7tiX?(0au@IAJV|QCyo5}gmc0)nHy`6F*-?Oc)Q6B zF?bS=D(RvCe#WU?VDR%obdf>+xu+o^`Sj}GQ3^nNj~Hvlz`=%m(v`-VTK=TIRXY1z zsQ;Ok9FX8`Nq8d8q@;0y?;9HAdc=&Bl|9T~wb2wt|nDcaWFho(2ya zEim7(cf`z_`2=pfuGx{oeNI5xs9iYa;l4iL-;sNu`z19t)NUY8)O|nUq*b!-Bip9$ zGU){<3Z)b3gm^lE;^qz1-Bfz$KyN8GdV-*x0z19&kI(ZJbZ;5QY3Y9Oq8mlRr0K~` z50`CHQ%9z)?;cni4N1Tcnm(%(C5;s((fQKXAx2(Zt4K?r)k2q~Xo*bOt4DDhvW{`5 z!gjm2R9acc>GFgA07F0p)+K3kf) zSbWga|Bfh%7&!y~^2-3)qKcYQT6CiFBAU!hA9-#cy2OCaCQg8AO*BExA-V>aliupjPa+Af%#A6pHUTzY(MDo|4W^;i;<0` ziLjly4UqUlyQ&M&R)d(C`J;>Gzei(Z`*(klzu0pIRwia*1{QXvk5(LP#N2EgAME)@ zQl7ap@t;Y2to{$BO$`77ECDtEJAf0w1>i~ZuNi#g@BxYc@+ALBvH!ItA1i{@VgIY{ zkGIUq{KtX)`m;%lIoE8B1@y+rN2|K{@L&EV72^YZTL&E*v5@sfV-Nz;{ z|3ktC_&9rJ_J2q?04^UA&i|IMFatb4(gglX*Z<)A|19b6>HqCyGc$AjmtW2DaklIq z+x)M(|LJ9Oa4K@5Q7&O&MvZ$WtpqqVh#m&|G4O=&41RvTHPTlw(p4~vTM!&? zC`BqdI9V)^WcV8c=^zjq-qK_YYzXkuAYJ-=H%0ayVx52{{zcg1?P1V_?~RZaZ+Bs= zLU70Mu1>)sT)$dcL6PZd;dmpl9)8RmXozBRuc!y@yx5(=%RJSyz1e{!;O}k^O9cLd;92GxtFDuHTw2ALm4uqPAG5HeVZ zA4DmhYA_3*$vds&Gl*jL739|y-uyS$Y9AjEh1$++g2S52Zc;E1h47NT@8Pd#sK{Ur zBfmw1bU_rJHu~Qh#y9%GH`QL{6^r!WD1|{vjs?kY)x>u=`Imk@h3D*t-ZYbJQMuM{ zkiVKf5^e8$(SkpL=dKF9_fYZf`x65KX10-bp&Yc|0u_0h{5O*m*6e+F1QiyE9?4DL zp#)&KUjr3a9G}5+L$cm`N}5_eitVm%;JG#}ZxT6FB$M4&-AL&T4V~efyv-nhfb8(x z6Mz=*8!Q#PHg7cx6FT;DWX~fLD$tCEYkeWkh3nQFP8KSopxaZ=JglH5UMI0)tWa^R; z)ke5U_FpT=T~!2p*O#+MoVk1fm+8(bjfwF+-V#EOzbn@j=-Xp1iEh*~5$`G`;To{$ z>};h{YW$qw_LK0%h%qN8R&$@0Ita9~B^ASd*-_-lj(#@#V@<}9p6_CX+;t_vEOo?9V^Rb19RS|?W3ys9hThr(nZ3|NVg z7|B|O>-`}z$Y=w50%J|i*Nc7Z3yQNl_BI!&l8x(*xYOHnRrbBhc_JeOwZFp+_&xpL z#X5iWr|r>$XdyH-Z!)iL3>j%N^P%d#IB)RRxCG`ktDF^@E}^v2vMdsqVG`OrNEmBk zqx)6xh4H#A<}L9vCc+F@r|B){Y^3Qd`8Hd@l>=7fJ@w?yHYx~SWjoO+M=lr1PDt<@ zH6HGM&Ip$SIz^Tgrf)#p0I?Td`)J%N(IDs}%2~+vX*+@M?KT&55WJqQc_nnwa*PQx z4cdXPzc3kHEEKdp1(uVQbGmQ*fE_#WPgf;&94_nndUPgygX(lf(6;X0%wv+D+9u|b)jl6- zZOU(|)@$W%%3$~xx%rtBQBg+*M-9Xm2o3E?Pv5VHfQ8V3$L$sSWJOvI%MvxGbLUJ@ zNPXG*%Y+v8nqu5HK}+!rba6yJ{zq`pjJt6DBNsAl9D6kPl52VeH}`8O7;6o@2uRX? z5X*kgJ>%4UNxLNi;$5aZ^^xIUtQ;!fcz2?1O7BSMA>t7l&RDgFo6e_C!imb1<0{Wa z@crKNqTMIz*eG@L2Sld0!zT{afUhvJuP2!SoE#}odNjU7hSee&qOTY8>5zVJU|10R zCVufVw)oVhA*6A-kyOvE6p6QfzvVC@&WYUmjeiy3D%%INIvOfX5g)UmkGhWs(c8?Q<^!zT;THs`8kh1ZL?JRzZ$jDhxTtuJVD zzBSEln4)`Iow}}L>&WY9bi6*COZuxAwShxSws9VMohn zSXp=u((l(L;s)$k@gDD7qf}}6A)f^3rtU{tFoouOssr6;%0uftHJzp((e-n(7uv{d zSEYNRY=lC#dN!fi$9FYBLSW4YC$@NV^YqebUg5BEeOsP}W9HG|-P|bNuZZuWe)E&% zR>td}t5X`@6?2&lQcK+4oGH!o-Q~>B88C~~4li7=Nu;DxVmTeEd+3&}MBI-Q?IZz# z>FaMi?i_43h~V01{tre<_zDBuZ@X>D!X(3!>k8@nC80Kw$T}QxIOo-wN<>VS9@Nvw zwsY8WL3GJJ7NX*-l%Qv(UY;c3iNZfYu0O51JK^)u;!d+GR+Kp9=NVNE;iZwf{9b+D z%ToyAQUP*I4WUeVlT3NRy09H~g+B${*V{?(XmS9s^1qe}$ECm;Dvsi)Dc49HkEYlo#`0LYMatsm0trZ0#o ziO7|M4f7ygamzQv?4B*Hq}m(EOx)QWA~B@5JSV_suKo;>cD5qMF5Pz?p4*N$eC4b+9Y+hC(nH&lrj7 ziy!`}5qf8t9~5(V-EZ&2hovIzs6N<0p){Bn0lU#3m6((v+0ff+y5R$J=QRd2m*P@s zWKut?DQ^`kO#uF327C=ExzfH4aJ|~Kztv)9tJ8IbtY1xL<~sRG`+7u>&(buYHzxgp z^VVz#m6OslCfy%+PAekB5UwVsfcnv3I=PKUyO|X&Y%!zmS&L(ZG-IyR`F^Zl*1vkQ z+Z!Ga*j=n_2rzXB8_BAPm6mD?ObwDRl1cwpJ^7*V1)qpakvTPW2r z+++qTv5Z*fzV~bre(J%Ss_7MMCFj(c@ECXmA7BEE%eFU6is<+;!q_&Gjxs%3wskgo z&qHL;3jP+_GnCK3C=qIPm>3f{!@V=9WYo?(5-Y7!&qb=?Ya;E0m%{jw(a-PK^#f1P zkroys8(+uop_A>}D@6*0RuVC#Z?0ZwjGx+Gf3OY@&eru93hP|msr$wlO=_C|&?j9u zm1>9?nOQ<^YRYqzTO8h0;+Q=18ij(%1jKBlxRf@LV}%v0PTYHhZ4Cd4F-QSQxFme5 z<_9>G4wQ~9u=o)fc6_Q^`jb#HZTBq076zIEX?%2-PXc2C)@PL?;Iv`1oK2MObXAP1 zf{WS=+*Lh9Mo5&7E3f*tEom2Zz~d+H11y1f@XSlZ*o<7$ZsEhFCA~U2LXus}naRQOj*RE)#)$wrD@Wp0d%|8m$}8RH_ieEACZSXScCuflg`;V@%tiD*@BX$XuF^C_|Ql0cLXRp!F&BYME`MmP21F+!FFBrHDAf? zovFBe>r;nGXG!E5N90l@g!fo4M&$h160 z;3{@dIf9~GWs${69tH1f6@FVfdwxg`cvX5d=@bx%+2qSxGgn$)`Mj z2X7DX5&;|GPM9)-r53AN-Zj|@X85$>Nxfyk68v*p3iV(1Mw@Bcterv@%TcjCu^OPW z`!sHR5J|`<49@M>Km%n}yT}V;y*lYI(=V|HT0l!q0H?8N)6Y$TpXtBw#}w!k6LsVU zF9-^1mRZ3y?|4H%kyS7`%JX#y({xH?$lp%+yr@7@=Ow6exB7S#L*_IZF2i2^c0jE@ z;vCW~c72Qe{GQB%CUW#>o89&h5Ak_FG3!>aTV7g}8TmSh2Qp7?4t6oj;oZ8I#1*+SKwCMY=hrJHl z{v!8DLGt2&WX}#!qG8i`X0ph@Jom=JSH?C(Hq5AIk5V=Sty<=Y2B69J9>SYPpv6m2 zeatg#D?3<`cv9{qt6N^-DJc#=MM~kkTaL_L2K zV#Khj7OkVuRi)GS&Lb0E7BPzQun(lRp=&P#R!>xrxVh#-<@+-sB_#x1++}GP7-h)} zM!BFX8;5VrWxG^T&q@}k94yMhCU9sC^~DtbTQ3`8ZG}PlKAujMV!7d^F70GzC9@fPL{O!E#`4PgWEc&Czco7XZFOjMI$#y#5e#W1Wwws1|@2& zdU%vF3CRZYY}_zkg1px?5mpsuTVwVy*2d8_pDMiFRT$7Fl;L z0#`0b5q3O=&g3B~sZ*u(p?}h_!ZG34e?+|C-QYvgc$ib4RM^Gw0^@4ag#TWg2oysF8&Lus9E1be|_(q zdW*0H#X#YNFWCc?qE1B_AzoH}i&VgyC)7ddb8TmZymFfE#b*kYcU0a z0QHRDC#Q%bIKd{X80mfwUWc)1L5lMxxPf=&DLpxk2!Mc6Srp!ktIU+J(Y4adkPnZVkP1ImJnlTyft{vXbM#*`-KMOm?UWO&y_> z$72zm5#1X|1Pt(}sA}6kPINc*yh`w=U*xu&Pz-4-5bLM24F2H6ITV zLuT?>nXTT@Zy1Kq;o$K!rC*!ksb_Ffg(pa7S`fkL?a2>MriaLDi`20V5|S%;=nXtg zA?Xujsbj{Zc-pRLCo(2gEIhd=30_d5RP;-#i3oj1!Hryzmb=pw0yUA;^YWhD5_l;~ z*W0D)XhZDm7rw%%mKx?IzSmoyc}Ad{{pB5jI>AgR5tLZW4D3-tQ@aA!J?uj?@e5KN zN8fGuR%)ro!hI_z9Kh;0BwD>3;C;%y_tWo)6T%a@b=QxeFD2$q+hHgWPvU?qTip6r ziY4y24r8#_13Z~5`#XGp)dr?A2FI^2)%H|pI3kFc6C0(C|#?Gka;BvaBTut{Y0$73r#k0v>FhiWeZxB$hmrxdWW;ooMsMgK6}eOFjnuSkduyu zGq>;5win*sX8gQ~j~=dtitBp_`{fw6z?h>AA1ZpZ(eT)g*R?67)uzmDq=O#ZIGOo3vcT?@Nu%P7k>E1e-}J{R!AiVV$MF#8oZO?*iG=Cok@# z%BQOK`2|=Ak^z*-@P~~pDAg_LxQxPwb)#7~g{cm6WtPorRr2LOe($zyrDT{>P7B;} z)9MJ)lTo;!FZ}2YQMEjmeUMb z>$N`eY~-ff6w#^B4ZgeiT7%Dn@7w!aV+!tH!8@OB#lQEtrGK*SII0Z8PkgfmR@K+(rfDG(%Wt^J zyU;Q}|CFS{H^5|TEGj}%Hs%B|u!v!F#4Puv?*c4#IqLl?>F}@rHlz5pwA%A3Wx`84 zup|YIVN&m%5jG|1$Y&7OrF}ruB9GB_iJg{nngCl=)+KQglb~OVPSHK+DoH#!&(jB1 zVK#>)uPgLXOcF;o(iYE3r(|ppbaSXg~)iv*q&V(k2{A8%)pJ#L`G6AND@8%2J`siT7Rlc9VvikFcB zb{#_tsW&im#7yuv8^?vAJv#>El!+e83)(nA-0}CjJZeq2g=@KD+a-rOV+|CmceTPb zPRlw7=d|?al@IY!j>?DO1HIw9!wam4Z5G)m{Z2#Y*{oXJ-Z(7kl(y=S6a%TA924PX z^ZOo`o?LJ~p5WAVP3_yq}fg$2<29qnu2Y zX)GEdkL&iwL;+>+b{iC3!ObxgF!{wEvpsnRCEvJBG45`Qzq0QGOy!xW$ z2mc0tNBK+2ZB@Cg%Uc*;xR@v83%93+_%J zL4yPtbkN`$+%>qnJHg%EJvan+cMS>d1b27m4mq21&i=dm-@TWid%CKtrmDKC>5r-R z`3m|O4lA=0F*q4kp3JJ$!WbGeudciuHRPZJ-AuUmGDkClYKvN^DFjlZN5cWlzUda({;ksvbtn=Klm(hjoI->8_F8ti-6{+Iz zCFk1`nFFeMd#&G{&7do`ulKHgmF#^3{70>$C8Y)nKL^d7`!lTmuN7|o#mG|A(yr1N zXHUMX>_@U6DFpHjx<^v+#KIB$E2Sj_&rlyf5J-dwHN|CDG&N|Ae6TJGx0nSh=7hm< zxA}>vy*kpvEwpVNa8G0gRj2hy&|jQ9vkTp&EsfIDrUdPCIkgz(-ZyZm zBMP6J70N~hVze%pW!1`I%Q zOHIV(ki_};ApJ?{qab#@m6qktim;YYoYg}DGriBpXmO|<5zk}7^eoQ!($r7AQtUcE zrkfbpXR=4mx!!(F69Tk@jl;H(;^snqXxI?B&UI$WJKjQE-E=o7J2L!iY5Q&&$CrD( zJT=0No&U3lP2ovxbS}nisKca#0?}|?c)t1NDY&a%g5k=%K!Ng5^`}><=#h#azdrXP z9C{)=L{fs)`TL}4931jW0gazw;!$yp|3zf}i!1*(L89}&WD74d{r_II z@QY=K2mGa45Rs6U5Rw6@78Jz(jcVc7?ET;8_8F{n9sBfD{f^0BexS!49NzZ~!>|53R$?g#O>J z1JgfS z)3bx5ETCAX-+4gsY{0)MG5(dd`!AFj%*=pa9YDnVmxh8F_>b-Yi9i07Q2^Nhf*{$; zpJ7(|Ke~#DmFcfI;7i95v9kRc!$uE~0X68aFf%{_1Tp*>W@r89E(Ym6nEyPu$w zA%K4j0g%e$ucAQ$n!knw=*(XgW%%Fp9}F*D`1>yTt^WXZ`ftGpBj}^(*?))rS^mKQ z1pYrj78WY<2Dk}w*}-1ASJ|rwA?|SIu@;OHZz{@y2L!n>V!Iu+jWW`^M@O|GiMh#F za1zlAWi@BlPvC!M7Ci7up^1+V_PWAwPU*Wx*PzIg4{4*HGE zZFR2Zln&|dfFK}U!h4HIcY=Vp1r`94zO}O>(t#ShlEfp}rO|P6WeAqRflR;a)w%Wc zVv7-vS!5-!-wcjSN*Kb3Cs7O?<^+@8Ta*Y9ivJ6ulFVy#*jK4Ga1gO-C>;W_s9cQ# zuY7c{B*;4CP+t3je+lw~Vz4Ig8RMdO460Beu+FH>+q>D8fsiPqlmEIdkAE@NoNit-Du%;7QH*C6FsdT370IdF%}so3yARelaN2--Z`?Z+-+h-lfir+UGg-hQ$M%+5j^?MiS# z)TjjEZ?6<9c^M&zk}#*iR0M7>FFLGa<{=72<#=hNevlK!euKzp8N@z3W<9y=Wf?q@ zK(;ojqLhS=g=3>}9nuQU#?4XaCh_dZnb;*bHcE^sgoEfCD2mP=chT%8QAnUK^?p|~ zir>&9Lcybut{5})d}F#xqs;WP;rq2!Y3XymrIcYmIMaoSyw`YbKPrQglCjwoPl>14 zTC7mAEcJl zkF;`sWo*M?v0fV5(|7lfLjP$wwvXeF^`Qka(dx*%rS4NWVL>LLtkcPr!?{1*on(Bj zmBPWmpvq<{!{_e4%h46VNCjLvLN|wCd7Hkjn0%{U9fT!R&d)N%U~R~@bAiWH~5mng`65w6X$GM%%xqA+J;S*5^^-9 zhVyJg)$}y`XkFx1mJ@j>>Di}tFLyKJ?2*D~(C+i_XtwsZYq60=&e_x(>Z&XyUDafB zLzS;=o;c%K=FJoxeBA5hhn3!FfW#UR8eU)h_erFO2jwjT_!pw2HPILjX)9;QNg%Lk z3+qX8ometI#_!gVm$NsSOluSB3ocuH3%ipeZa{5PNJ=HrE5?a*)ZJE^N=LN1hHE=E z_@sFOskPikKYVh@*b}FofOX%4XzyZHuaJci*wwH$zP##_W^N^~VXq|C^hsg$Zjzmp z&y1kkaZH-KCS&5$5vi(YtI}IB6|7j710^#H)k^fsD(;ruPwtLJs;2$r&H~dJ7FJa( zKdHqrlo5G$991ekZbXk{_P6^_`+)PT;`r$1LR$uD7Fo6LfV&e9>NqKfwcF{+O&WW8 zOLTRqyRNlY#`>GxNqI7A1}pQ_Z>aqvf@^8{XLxgMCOer1$0YTVH_L+&pJk>?N0#=u zC-3dv8r{!`NCc-FjAf>;ytd5LPN!c)Sla$v(T$tng#A55ulb~QZVxG$;t}v5XlLvY zT)Y$8F1q|?FnwPp?Y!&z-f_Ey&CfSqkeDKotz7h7=G|34dzt(s)_uD+u_8YazvA&A zT>VL9u&bvZTC!`!yXQ(oOIH#9qfWX6WAol_-&E&&`R6xuW{+RP`nR24ADHGY0TPQi za9a$&rRUhhET9Jyc+`9)p1c%mAG4(Be#$947d~iAa7cmZzWaL0#`oCi`uQx1v3e;# znAW($ML?;nVz{osHz`3Yeg6{%gDHw1sg?46^Q^^GZj5@5x4%{%oT2M^x=@w0GZV(Lp?P_CPM0?M+^3O=LNLP#(V;mO3RBnJ=abw=z)2=*R2IEp zR09M_-Na`|di}s3|6;xV@{siV$@kw`uYU+*|7N`cU!Ie{HMcK;-;&#xrz*(K{mXb2 zR8|!iQveySa;$&Yh<_8@{xX{WZnFJ~_+7RC57YIZ3j4d^`lsBM74%5|Pi8B~vipbF z7G!m?ve5r~tCjEX0^46!#NS&0veAB-74Yh8Ad~SgvFytg{N1qsS}Y4>0q_w4{}jgl zUB1fjcbo6G`N9BX{Zp{|V!tr6y-1^f`S<)E1`H!JsG=`FFaMJK@6J9C;|vruWb3j{ zSLiwskgyk*mV9EhUt!8Lm_@CC`#?E?eiFet-}snW*B2dqE{~l#x7(U2Eh<*r|9qd; zeC>42e*HtHu(%zEsg?;^Y+;V0-AK=H9Y&P0sIn4bHc3^rH`>IQjDU~Vs3N_L><3;C ziuU@t9*n4O7%@&1ArB4(4-O|I5^vY&ayOc}*;}t9qyaQ@h?-ZF;OVry zz$gN8UNf(zbU56NgHA-$>N@Dc$8}^1uh#=`8$0lf2EvAVkV!t0Y2bZCb``XY!#r^t z=HCv$xSrutn`WP{qo@bQ;7DF&-4~F503$ImH8MK{r+<}9Tur&aSL{th_sm-J#MD?5 zT3gHbV~cS2d93i+0@oO_?&_u-&JlP;H%cVp6_ZXiFm}aLVCws{nGePIs(JQdyD*LE z$7^#ELo-Vxh>9m_D90G+W?u=#&QWq~Fs7_pjGauIsIpzpkGve$(yy>>RA0e4;PrWy z?eg?1cx$U0A)(xR8a?)Jcrq>!2H5wb9U$NIz?%T@^+`7Fe=6TS%Zd+8_l#nin;~m& zuR(*odE@B>9hoVo`%)}XCaToq90FrdLXrPg%)v5ycjN6j?_?caP z0{dVEA|}@Fz*R}cu%re7ae3-FPo&L&&E-#X=l}vsqA1P*C>NX2Q9+^~jFrR< zvm)=Es-QB!)fQVA)Eeu|n%=zACWfAG(iZIW)+rO-&SriE(@QSt{3`{L2vYqo+r?seOfg9S)H3P9)14bY2Gt88)4wpXUY!4F? ztwsO}B#EaJUAvDjn1oC1u2^Y5+(n*X8h=YrfFit?m!q%&NvX@nnS*=Wqo@vr)-+o+ z1m!P!TM*KsI@Oa<64oxHx!?Cu;(9>(6vN;_;a%#7z$Kr86=Z2LPRL|p+$n@Y zyn~MSHR|3neqU+)rMy=5nikahqxeBC88ledHmOeJzSwrLUK!_}7Uh=#y1{tHE+kD{ z)ABDz@JKF;9E)Embi;cZ5QPkQ@uZVFeer5If8Pb`WDpl@&sy1&wT{aY3ic|ti|c|l z@PNNJt^uQP_CX}-YAOIBUt*JsXqOGAsi+GAfi##xXM30(;_G7Ir8J%O0ek89#!EUv zm;GyWypPRAs8vBRnMcd{oXoUZy(M)7`RS~lM+5}oQK1B(NE9R;<`pn5gfdt=bb-d} zpgGlH61K5Ji=}JVcBC@6umrCJ{w3q?dk@&!H>cfX7iVHC_Bxd)@OK!nzCugTN}+Xk zSRllfJL!$KUQYkKfdk3u=wQa@0-?ZK7aobYro<)NJvpI#&46;cxco($+bfFB?3{PQD-0)s+ zBPG^U___q7l!wHnr$Tfu4R3aNfr&exAq2>W>K{UBf=3{#9%)~pI1#UM*xsJL@e(i2 z%lR_51#x$%U7^U{HOfJ-J=u{;@w}Rw>~Fkfp|9+-98xv*eO<{FzTrzS>%f#pIvY!kY! z+={(`!-CMY|L%t$zzm4SU=7);_QjFB*%GH`M3ow=E>m|9op~MDp!h>!;O=3iZz1vR z;23KNWsyB{vt?4*TPUVH0mQw4SSmR^N1G3u@H7gwBRaA(?CZ3+9@r!3Y(Q=g+Vrig z?)i^a(>0H2rX;q!+R6`ze^HeKTT{laGJ)7F?1EKbIl+R9LWZdH0W>^FO1iT2p! zWe)d)Zp`eN4!N98Eg97yJPzu4a@*PM{ov)A0`8-Q3W&&Tv1W_B9%JtrSe{u<=o!vi zJ-gXg)xq`}Pe#g?8?+Pe!&d?h-ek~^h;-sqWYp_d10=|2%gB?Yn`3$JGMC1YLSnQm0UWfR)`HjuA$XGuFPQ_#%5=8nvMuQ*!8cf&B*|9L@Z znZ+78a^e_VUXWbmW2SFC4&zeQR7dV9=MpT@uf~$Xz6iKd zI4)=KtwO+ZV_Tw}GFl5V6f5eE+=s2JtQ|c93$O8f0>5@x&GI~7zxENa%hSa)46V(U zI7IlP?EAde0h)3J9-neE3HbJ(`Oy}GzESJF)qzmQ^*Jl~?rnS(KcBFTAz+ZikH0#^ zEqlI*3WueGj)lma9235FpK&=$8#{UkYewqug%&=s)TOelqnJ%L)xFo6zb%>l;Y3Rj z`FP(-01x?^EmhSHfUp?8FA&lBb1P4A;%Sd?r-{SeBe<+F`l=8ym)%J@*x=}V8pbS82ABAR z$rmD2rF6mtvyc~UX15B`TD6@D;KCQM&E7nSNEWnJi!PhXtv5n~eGm=J81*>CpmPs5jfO6DKFu+SR6%k%i2~Hnn?lnFANWn+63MrXb@0+-LpmSUGZj<5^SX<#*d21?y`M*Ga)2<2^?Q~9 zq~hQga<-$c)YS+G0mE`y1__3!#rI+8-M~*ExAvViKaiql1rS7RmMt!M#>fdGmN~wyL zSjgB{f|Iv@;%M7gX}*!&l)7%|-=nZIaw17_cPG4pdlgxUrfnZ{Q)Wp;-9bK}V@ z#W$n=duCpbwZ7Ydz)O<4N`=d}E>n>%KsHLMk}K_gIc|F)uCgKU4pi>-c+QIG3F~*z_*Sgo@ zApVF>Y(b4?F~P}EB6-^Z=rfE#1l-U*Bpi@VAZj674*GV~gh#8S%6i*$L>fMYk1gwQ z%`X1v@mJG7?j_qUHk46}SLoxlc0_q_2^|_)Gl7ef;^Pe?LH9~^z)nNtK;)@a{(70_pwZ6REr8SHYu;f5&&gs5Kt-!qDeG7P#fo0d z4DXP{;rX5x3*EzRy8nJiWQ=vs*SdKxhJ~ULqJB;%xTsI>jF3Ov(9V^aU7E z+_>FQOyM zV=MBhJH29FVw26gb400dMRU2Y@pY>mi}}nm8mB+OYCqQH4NvvV?}b}roW6nKEL@>s zs3RM%O4W-aOPYq_7<5IT#OO6uxh7lMi0i)1)a9WGt@KAifwE#&y3 z)rJ@u8}t#dt2RK~95{lEcGA+@4OgpxWE+R>uzYQ5`gv(r=uNW5D5XdW&(C6m$v!C^1Ag z*!JI4&HZX_Z%aW_$*G|3+6A>OyYB_7RW79Strl}sFgLvIBSB&AN8Ms9W~?~r?ui3&HvjdjlaFdPWy763zmuwLDzUGpTrqRN4CjrQ$5uXAYtij}=*KsKYf?6GRKRe(wd_!;4;P zsA}J2Ey?3DA4)tU-xNbc-5G|$_u0h|9P-raI8WOOBlPLnco;I7Ksy90M~avbUdo9z zc!Z>HQ`j?G?6VSY8ouE$!_f+)5{uzGaE`E4zv~u=_p{P*0aIdiXrVNTWr=A}j<_?Q z%O!f#@&)Gda8uAFvZE$)1t{05;_}+!mOPD6IUHN7am*?1!oN*FR<~s88B;IVca?>n zW}{fLfXJLK48_GPz#a>esn6})!x|%mQI59+HCn6&R(pzJVgEwg!p3Dv4f>mE< zEh$2;57*p!6(i)BQ!y@@BWl_Jn(0_xZ?ZPhd}rxZOKDh%M)0|XZ+fg?S=5C)$WA?$mfL<@E8Yrc zZR({J=B2+@zR-eWd#J4uBXqv8{Fvi@rE4umqxq1{d-C%2Sb*P%LnM6=zqD~U zJ6{#qgk7?y@~u%N+jY%$&xa^Y$(oP=k(EjWqH=u^-+sQn=rGp}!-Y(R%i~bKfPTir zJA9B?e@xWHa~A;QTVeA8=bT_RH-?E$)FsNo68Ts*-%yZD9;-4?qy$z&M_O=9^nTWY zwX%gogmsr3O`uG!o^Q5f%0F6y2v`lGfDe}5#p`@3r*nOq?IE8q2JrH=_j_TSMrhCc!D47g9*;2ho)3*XP*BD~siR`>aJlL7P1yu!z7l^e z1$FO~jm?m3{;=j;0=c$mq|ARhRM32n-o=nD2Hl3F+`Zg-N3SB*OEP9H@CI|UQ<2-d z>J4H!F_otW-$#-gcek{%eJocFzzB0{Dsy}b3{+CQ&P$tZ^x#DrhGjl{kk|S za9xAg%MXW2YKR0~v0)It5u|&mndyO1l-t9H%&bGA^@$BrfOya6sM7TUV}p>mk|Zzk zhq)iiOb%o;*3H97*2g|>w<;5Cs}3r>nt=|B13cw1r;UNh1810);TS6 z72R8l)^=_aMMUo>*N8Bm@@LXF`{GFIQ{6Z(RLpE9@sKJmONO4d&5Y%!!vvk&r2c{ETHZ zIts%)%u>;}8ZCMFHszkM<^O(a{usVOR)GOygZmfy% zs|>ZdTL!~=*M~Sv;v^~#DLT&4gi&tv{_`{ja(OJJn)}(;x;2fVIl;6|Fx8H6?$_!U zZFQ+;gO@^w(!I9WY}jlz;qvLT>SwFq%RMxHx3T}59WK+ayfZT5k-Ku_!*Oe3GF@4REM0&aJTx=1OtCsw; z2=~(N$HR}l=qZdo_zQg25=7^TK2|E)s{>>t^bXlgcK=WCp3rI}0lk-BQdlF@>z&Y# zm+yV#mZ=0CFcoOh-p>o)%+?hk)mT!wF5ys}nTs&dex5oQF@g3-M;09(PWL7?9 zWy@nq`g8f=YXdp0GSf{arZr^fZ(T6T_JZ9C7_pT(uz(mQ`e z%5CHe@7EZ&9K%>gmb;n5Y!WLo<=9XD?;lF8LeG3&)26R;SrqbLFj)OOJwtoOghALMIFhauj1D(~0t$l-O|dQ95{o@9VxTq11*i z5^pe9)-@m8Fe=O%@cZRpy%X#A2~L)p@SjjMU&m_zM_oF}q-SX9#;7a=-uR2!Bo zw}r&GjXi~eP(b9m<0_p@o*}F_fcZfA6P8Y4%N!Zo*Qt1{a&@oZ;Js_%c4K=DiUOD( z4_bK#V>jYee^CJmw_1;P8SSZn!k|G?F=9N}+RogeR3~fFBrr^9k0#L7=yRl(WHtf> z0ZZhUyNGcjU#BY@9aypMZ=~F?aG-^0yyWh}-ui1-y3Q}Qb(wTmYQ&9ynaM)K5y%q) z{rUJgjP@aki8J(8ptuq7xDCy~Gst93F)rr^$HpdM{1IDWV7{~2@@7-NLbM#6RO0;` z0k8M0K=$us%xf4)RU65wJ0$Z`h9a^dQpSbH3C3!K#8oZMozY45r&I^0#X`J=*QN!?q!$4_Jxd4W5|$}}5DvoW}eBa>wUv6p&0ZopO#3%)p?DTQeS)Mky@ zpAT^YS1Jw93jHjV7Ue3JSv^NYrfRE!6=?}TTw^g_hpv1=@e|jYQ()TF{a{tBfsS?NYH;5efU~;NOopjv(n@PY=J! zjYMZ_Vo1^xtgPPjps?dU&0YvOudlli&ywHN3GAlMal9062n8!PM~XR&tE{uY?nyxH z2{`{iO0q(vS~hQ?;8Q<2+2UJRp}zH{Tlk?xp8+1z$v2VfmCsC8Aw*)~Obq=tRTvau zuv(Y7Ml@FWLdAGD(UJxVA;03|X!hX!#@hed}9 z4j6{f(l}TSr$gz4W&>LcZZ&jY5wC;uj%?7S{RI(IT?*?{B+*a@G zp$^5yh0N;V*EgNgBG;zS(-b=R3`P9N`yhbDg6o|_tkE_35b1D*7+d`~Oq}9RNOpd( zTN78t3}3wNXFKy>@(!$a_3|x8vK>R6m88Xfhf-&!sm(+Ate1hF1 zxX>|ee;Xk$^Mp~@i;pH+S9Ke)?oM=WXM2`!K<6JmNbpSLT7JWzh5ycE`@ zOK)OP8^4l+ux?c5o?G0y(=n<)2^W+gzR)zeOO%Wb%il-{tfWALIxkxIh@1u2-xows zSWKDNUW@=6{S{_H{q8f^m(w4bv7V}G=O>t=S|_){?a>?o>9GTPT?#DyHx*~dPsRH! z*D#3zOdN_ttfh`NEjZU9o8K$IM3^4^?ZAraqrQLOE_;(tF7!moVaVg5Swg$xVJaBD zz^3gn5}7igo?jMj7>oLR*g()HEoIOqawFV&x9f$8>jfQ(SzwleKTPJOxNWE>Z&M}- zeZv7u!g!mv4vaZgmr`{K#1O1kJH_0+gd|T$LY=QqEYF8q7Z#1Jt~D4-yu>pqFSOVHB3_#(sWRmgpp=HDGy~kkRDjqL_tu*jA*Ax_kIKOh%eiYE_+ZkE&yl zj$V5Q9mvaSj+4sudGR*qLO@K|O4rZ#`8dCriM1coJ-sa8^KqOnxE&A6UKOgRiG@L$ zuVDangoAl}3u*aGPK~zL>6>ELc}dU;ND5IUd!ygY*_y@{U8it;2Ck5J^pI*E0?#rq zTcaMTdx3k2i`7zwMJH>zcLQoV>GLK~&%P*vuc!5$#knY5uXmlW%%<<*;Md!Ds>c?~ z6=>42O&1If6oUrYeAF9G`!;tOSpv54M@d#SHhohVnh^tlbw&AzjywEalNm^lo@I6@ zmNfF6Gq2N4Y{{{q!(=P*tBB=nnn{o5za<<9cI#yI#M(D{3J$PFq=cAJM2C6Gq zX9jwm$U-h^@Ii_PR>foQ$Oh^a0-W9xGk4W~(}wPKMxWurde0bj%XNTbz_`ijl_`X3}X_s`NKq*SeqD~egDX3h^8k-~DA59(N8?CQRQ zwGEJ0#Ro@|&RCt?K4PT)v{2=3N(0Rv3Ct#zT5f=!MNLrQN94htDm34t9zcD_IwifG z;FZSvaUQU(#L3S1Z3g3Y5-!0bsQ{0Ug^G(KQm6|-d@=lSyn9|97O>@Xis0#R08#eo zrjM??`bYEI&$xx_CF?EU-DDiM5TRwi_sMn*S_t)uq~xPGwiCp1_J=4m$6 zz$x6^_*`*nOrq4x#oQeTx8@+y`9Ry%v54(#7-WI5u*JfO4ve}d?mezN*tc-Rw~Xgp z)QB5Ob)Of-#-lkt^DC3hIb2j6yyH+U@qyqJ2rO<`zSc$A&wC|zbZ+fSlA)L4gfB!x|@Iy~Kf zUC3SEi{#rU^I4|bZScSER6a9F6CP;&QZEufUilN1za1d9=)&t%^sYbaEx}NSCN&J< z)o6B8KE5B|0J%SkhQr-xWNXe?CspmyWAk*MjOn4|QczZiT2v4LvYgN{^5h+lb^t+> z*i!KNV=gBG;*Y~`;`hPQ03Gq$V<-B{=H-A^KKyrQ`Z_bNNC*t;{(W*(DS>pb<^1$e zD)2QxK9FgW%`*uPptHutf<8P3)HixE63SXBZgg`e+ou6#>{KXgl9?ZWkRM>5q!NzF zGxOu$G3Vl=c41j_3-Ql=PY_%#KR0XI=r$#}tCY$05Us1$=C541O}zkzb;OU0@{URRIo}z2Gf!EI`hRAVvD8qjUBIlqH!f= z4O^q;)kC{BK^|6Z!<#Jc7kNl8!5SF47Q(0PQ9g97eQ2vDVotGd`!1Z^lC}6PZZTjI zoeEPiRUUi@EwDu19I!I5tZ7hFDHV;YJo0|vna-GH>8TW^`-;jh`wm{Y9x93q%8D&z zTRs(_B={<<`srPlIHpNRRFwUiBQmzpylYV1H-$GCyQjWR{u4IjVVd+7(dP`tx2C?> z@Vt>-x}#w9V{R5=m+d^&G?J2Ii4)P^#TDV^aRa#Hv<9)L?y|T%36FR1KF)t2uqv;{ z`G%i)_O9&}-+Gh^lg~AihcA{!FQ$O+Vx6~6!Ryu3R5TVe|Fz|O-z{df@J3@8@~aH! zWyhTs+0f0xN@yF?G-Jv1Ar)l=mN|cf$87EGbfFB`>EzA`vQsI?`bf2HZtRSF>tn)n z`nJ}Uf`ihS69hF|_SniW6}kxm8g8vhBeJOU$prp-$sX=%7HXcv&H#-wqtg7OS#K9b z_^#!23p|mG_5`6UXMH5+wu0}8HLOa%eHMAZ+HcPFqStYYlZ|V9|jlNp)7TIC>1bSEg zV_-%j9;KD6suaE%ok(LDf$)}_9ASlV>+3ue2Sohlt;wS3izj{z;pn7aF9 z64VZ%qzs@NQ>k1dMa|&aB?n*DHxcl@pi)ch2UrYO=}wXG=8RW5D{k)}M-;OvZRina zxsZ-fCN?+OOZ$5)FeV4(ed#fk4Is){`o` zSbmKnF7Y~LQA@v?=PSnSipX?oSZ^lK0XG@jYsn>^l!P+fsa!&%Ry4mA)1oYCX8h@|REjdU-Tx6*Im za$H;o)vdCHm*qvTU#VjQH`y;ixmd;CsQYeglacfffI zxm6<=A`qh?N)9KmILWw)d_RPA*O|(m!`~o&V+G0fzMWf+CP_Qm*_&bqlliee)>8@` z+cSvDI*H~>_D>c|f>MR&d{!m~Ls>aIO(>69oXC)P<_TA&oAE1D$)v0CC)dzI^MM{0 zp(<()B0K*`kV7<=y@NVh&Pm|8OWt7NUBG=9BZ9n4-Ms_j>Ll^4#05lg(fd`sbb}>R z{%-sNqPTuBa!mw@9t&aqXZ1#K63hlVEB(DpGdFm_-A-R_`PhOtd=|h&5m~XazALj+ zJ>j#VudJkTpVL*Bt%{bJKYvKz*-sGxzmN=hw}v_Rc06rUS?$~w>p959^y_X^1t~^f6YYJ;8w>Gz{i+B)X%-{Ko?zDAe!5$XP15Y! zd7e9JhBon_TYh(TqJ9ft01mS5Mr1|`>j^Zz+JuudZXsXAjA@_jxL$}@Qq91Y>LY)* zgdXk=pY=fd?u$k`*L-FUhsXI$J<~JdN}TL$hjw zzhTavvlNBv3^x%Tw#G%DffCv=cj+;`n1$hmRCg7V^Urg&w#9Ck=-ids6m}mC`cotr zpAuB=i|^mRYl;YN*}UG>`XM@+TzY^vD{<>Fy}qS*nlFPpI3SO6V$%j~Mmv`E`EaGR zSJlCe4aX4p$YE88@!3$l4r^`re4|Q%_GF$~py@RMNyfY8``qhd3FpUF(XuDOw=g6q z-&@|vYJ(q?x*8jA8?y69d>|<9y>2Z$154TePAke+AD~c2)61~5O6^-xqrgL+7ub&K z?Qi4sK5#X{Nkx-`-RU(fVOl!*545zD2R~jOL0N9em5jb@PC2Mt(;EWj)B&gBizGLp zE@5Xb)y265_w5buuWxE}Q8NVmv21OySQ_eYWZ1DB?kiUpgd#>h51bfZ&)Hf&8-$jd zeC*o84Cm-Ck}?+K>hP*iy5nEvFiM30468x{%GSkMpOmzNUy-92b7IeTKGhO%8nS+O ztK?RZL?!2Te1vqhX_Zi*v?!x)>xY7#826cTU_cmT%07#=YOftnylG7i;tcRq*$G-fws)HMSKz3y5wGV}ei&(0ep! zwA1Y+r|l4p$fXfZrMmuMlD@IyEVo+uRZvLNT^(Kj-K!kLY}*m)XP_FK6Nao%%}ihf zGru|N&tn6qZ#L$42H{CIWMA9M)yj7UuLp2GatP+@)R;t@CO%;yN3~_5kozMssV&sD zr^W{rE3&jZey~Sd!jwXlfMAqgjk9y@ZuQu!A+S-0PJ5oLc z`r$fSQnVYTh*kf z!u)`Rb-lx_|Lrt>EjGASbyM%uP_J-1`@%om|oXN}9yX0R{D9rjI} z!1LSjFZx5Ko$(@y&P}k6lcz9mu74s0!lg#q?%W6Hpl&pw?fX5t-{8i~`KjDpz3cxG zkNshmluM6lIc`0mc<#3Q0-YfSXb))l9+}{{vdoX>QK=jdez`}{4*8+6O+ox|3dU|I zV2Se!yPtc+HT>z|rRe=n;}(^mdGX}DP#WBMu)Qqm{EgebRRZMXFS#&&2Z(qFH|Hjd zHjTHbZq9+dSb$@Fc}%{*bM|#bdnA5D7phPWVS#gk(Dckvl0`!3N+_hh_NkAXm-Iif z(dpznf!NLYs;zmKpHzx^Mf-LeTjLRaGQ3;mNC~)$ppj&!Gnq$N13Q0<`;Mk!^EQ*h zgRR&MvBDw)3Q%@?6&~j28e?bX>xrWCv`>li;6*FB-w=o758tX2_V+=()P|;E0_=!f*R2!rEk41P)kJ zOt&78I~s!9uf_RA2P+{)9k?$`{rxDjd*TD|liFE>{6l9GJ?BRgs$a;{!UXHPbo-{r{-QI+EFF`}UqU;Fe;BYccJ+jbJj!JkW`$h3!?qPa>mXTcGK zfouL4?MGVQb}z4|R0zC-FA2u}v^yDD8#=jo^|N0(OK+(kC&g{$h~vA#P60K3MFwSe z9%ck#ZG3p>Js}pZ=_#d3-A6$B1-&Q?w}*nLEe}dRkq8mQ*Uov^wwruvu|wgS07kHG zdQ(z5%}Bd2#oAl4{=l4iYL6qr3l}qtkb>(s&GW6Rq)_{70w!qE4&r+rc<-08k~hKn z2GIJyhijN}T&6Pg6$i6lBI>y?HYcbMZi}Is{BTu+h~#hekungLPM8;4L*l@<7#&9P z9F&lI!z<#Hev1SF_%Ljhrt*x!Gw{sQ`HTT4QOd_FV#JA`m5X)u3^BC0$^WlN%ikC8 z{_l{M7jpNXfNX~U=tlk@%Y*&JwD60H3&@MSFfIR%$Nt0X{NI)}e~I|be*AwxE&p8F zzolA${~Oi9^4o_zJqRTJk1)2OA;8cCU}z4oaj>#C(APD$eerMqN9d13>z8HQ%?%9g z0l$v^5ozvV_XkG|Fm|y9q4K|ZZYxUzfW4Cyz~0!_zyQDp;0FkR7;m9}P~KvIkH1K7 zX%Ooz52C#l0m=ZCKa2iV$Ug(%#vlaT6krB&bN?FyxA}|u1vmkm{}~4Vg~$98m-CNB z+CYx)*+47|2)2IN{uS2#_c1K=f5kI`pl>EN5RwhrK;Snh^eYDBS^wqzCEZKv-`ijL z{^t=0Fd|~5XCq>LfsH`k{ef%@f8ge9EHCg85fhLB1cJX{K0wf7sqDWs-Z63@iW2--mTK#l%&?xi$P#b3_7Y=41HFPGr=VE?Z{Cy-G-bUy1?V0 zv3=yYW%NdC+d=c%rkc^z*hV~6;2Y7IjGK`q5sC~Vm@9EE!UhbO%Z;^)Dj$7NQ8mk? z=JX^U2{c$p2n6`JwKy0LAs8hMIT0l}Sx`4T7~h*k?db%iQ7~lGZ7nGhFcVJLk=N#? zD9$>2=C3LRHo#KnA!@R;&4Q}&QF!O4v9oTK{V;ej)}Xu_c}HBVy?DJqT1`A{=*pV9 z{?$kE=$O`5m_%oQYWBs|_CyULdI~>EFc^L^3NYd^0#mDfX!<~vm6KvVv|1wAch9VX zk4CmG4P|91MN3+{&qw3WYOJ-@bq@FSFq5O;M~L3wn!MkL>F=NIr@SA;(-0@GJmY0; zfwi^J;tT5Y{9x|SjH;Z2>dpKkET!q4N?-``>J$S%9fMkLK^R%hp%r)wAny`$Gd|vM19CD`^vCwd1Ru^V5@4aI}b^?e=H9ClLmAH~PuN`L_(H z{9R!3xFeHDFbsIG=n&3e;L}%IsLEhHSlLO5{crceV8Myh)?QV3by+`gNbzxlmHSd5 z>RKUGT0fcXYALO>mpyZ|d5+|OX%>FiAjIZ};%xVQG89az#zH&`gyHd;fq)Nu1i}&_ zPSbfh!$LTxqq;o?`lBM+c+Wo9!9qF{KMMp#!FtUs-=Pq91rhE3^izR;%r5}bocrlF z>$Av1<|C7Pk&5cC;E6#p9O}74rCaj49S*JFG8I+*$CD&1ZTV*mlF(5ezXtG@{C2qP zkpouZIPYg-BEp=kTf!h?+6|P4l5$TX{>V+jAXNQJ7!pj?XKz?EASlZJkT57p=NjJ| z7VioaguXx#9I(EDM03#bT+tG_g&~>We}Ey;?|9}FTykoUCX^jGw0ijIBrXiSx7Qh- zL}vN9rw7~{A_okOn7jOW_hx8$9t~MGMhKCLFcWrd_PNSumA*%Y^ZAicU~%Eu5W%d6 zHjr0?SUYXbgi?j;#6tIzb#%SP=#1_~{{Umc<(TQz;m@`e=n;3px^ILEHtsD7d2Z+I z{&Cs}9-*sCOQZ!A*xwUL&jLS3jETu#tJ9IIQyqmz+Dpr6Hdt`be}X!Va1sXndXQ*Jd4IZu-D*(6Z zCW4X<+QNpW1r8w%6+4DFmH&@2mk3VHFalIJm#ZTcUOgj z^H!*S>%cfC)8nfEXYN+qRQ7 zc4OOi8#`&x*tQzm_)gl#&%N(=PjcqW?Ae&vv*(ZfTWhaH-PSID5rJD%3>)R&2VYI)3I)s^$zs z*89{Rl6ue8jF7MdELnehEOJ?NcEt`(O2PD%r!&>Ko6ZmZMtgR{)P1C=FE}P}TZ3yy z5AGoEvv2U-=c#A$97rC&*q8}S4YyM`ov7^mp3hbHqy{fAnU-Hi*+sBpw9PXPKv(x& z&hGr(`|+VoY(U?G4S2t=pvhY#&y&E;LohLafYC+Y^)>s(^Ms&19tKJb>g1c?f{h2N*6cFXu}txYe9Zi8vatv z-tLV`<`+W=SLR0h*8I!TdFs8HPn&SMSGY$d#VzE*aE5doeHHo3q+1`lFRL-6AewP4 zZrfeuXlkrGtx6BUVj0e|lfR?HoxFGFy*jDRPvRXx`S2;gR@t`hOFV*<#S5b;58N(r zMSxxXg;C+W?FK*54_lFyJFgTj*|c7YwnH&rlo+x=7H#Ba)^KiJNU9Jnt!T~|k5qR{ zA~oTZr7r8G@l9ZyWufLq-Mc1jR$Ld-^lORT){qWclJ1VdFDFRT_^cEbokkK3h9EUb z_75yX3nM>_L+W#JnwrFLB=f(mmc`N?TKUe|jaE$GS~AGBw~2$ed{=OhxD!IE7*Ep8 z2!*+F5ylidnLk1cu<7BndX9$(a?EIm_Z)E^w;|@Lm2mPY)-)J7o7pyq=!k+w;GrRR zpzgJo3H+dub9dJNmKzO9Vv*BOBIXmKl4H9TmJQWJhd;M|*ty5hbN<`>L5?Y z_nt5qL~IEo+xD?+O`nU&0mDOL&wg2Z8Io+|?)!V*LUfu6Nti))HJ%qRR1FmJ#M9ahyav<0PCDt+ z@ZGJ%y5Q+g8?+lA*!Br~Kd*|9q(lg4u|Cx6uJEk)G<3Q>LRYlUp#o!hQ^_Jveh2fn zBcR}K4~nPD8uv*~Rwd*A&d(BwhmGX!u!V(TU2v~uW&*2YOP;Tp3AD@!&=Gsq|XajT~6)rnVFM~PtX-JYlE$#h6wOtGxu(% zjmkocT^F^5`2}ja=Kh5xH*|OLSVkFO(Z!0*0|WYu4hWrca|x9pjULq1n;;v68{)%T zDG~1(W_v_=auj|MlngCY3F^^9cf_-vd{b09KR>w}I9CPZN^bhhdC5wJ36RU2x~0Ct zmEvLR>$dwKWiG&`)gYw~{A zE_^gfsfBAm$F$<*z9DD0sDE$t1*{66>%nwt_`B|26_7xLHNTW%mXu)g=m9nJmr96- zGY_TeYTH!Bud|e9wh@M%pwVwo6W~Bt)Dk0x$TmVms`vftXr0=Wrz^fL&3yh!a}(S* z9ay@}kz>e5w@@{(kZPy1KMHq7;lk5}r{I#Pn2(x;`l*mVe;=P`m^h9yc`Bi3i2l-_ zo_!xzaPGT2v)>Gm3BC@&8V=Qmj$eUqdv00IZ!b~FLB}%Fb zuf?CJ+jgwueSusddD{ybT`Ra5kItzlQAxjFR(`&X#=R@r0!#(Jz}#O8H21ALS4|ev z9e;RcvFXt|EuR#oOVXHz1_~y55l1H&UjS($&rI=l9*IY}*L!Hc-wILy7=cs+v=Woh z3){n5?-<}OLu;oHoS@{KOIOF>sOZPOns`W6_HbS|CE3yBdWFbEn$dD}g@IkD`6*28 zJ5oMYCA)Oa*w-F1f{CIJLe9@@a9P(x&+ut})A5q&9H|BanNx3{s>rhUPnOX2*2mcx z@$Bp`DdJmo%wXa#&=2}9M^Lf77Ph@DfxP&3InP>)NzDyDt{($)%;R(Sel0fLF;UeZ zmvrEqPAXI|21WXC#2UW_$=6qQ97?!IJRqql(^_IejS4sE%hQIYaG>s%B5z?Tz(u|Buzcydh7lY65Y`gJ7x+8j24D`WM`g`$YiZ0P1Yi2Y$K=l zfo3PXW|PF?z*8i`5f$890BNk(?GXA4SfFDo_@bY{UE-GiZq|&Iwvk1zavg zncM}8Q&c+1qoP7D2}!(}Th!TsZUCpP1^x6xeQ^H}FJ2jXbvo-FUnt6C3Ay4%RY8|@Pvk2YRI~0nhm6tQ z9?1<&nwT-rD#Vza%MUPPdq3I)P?aPDzkZBZJM5j`aeX-Ct6@4i{MOpXU+H4johfH5 z6u%n#<1`iF8^))&?;6(&=9*|*<=Zp`{@HL}-^XrvnYmIZIB*t%&+IyY#UvZkX<64} zcw%(oFoLvRBopur-BmVUwSU<7pIDcVORNg7Tzb!;!7ro$3=(RR z^G>@$1=u@Wj(g60aBMxY?gMfX_i64M!{`7Aj*92t}xT!Ph|pP#c-f%=Hz#z-KGzCRcvm2MgN zhHm6Sle|z6Sz#0^)pr`;)RfyiB&%ROWOXf^@mNCTky_E)`SB%(I(H;zb9pVk=HwjT znKE+P-hR`Lt)UY~cb6+K(y_K@?Lms23J$@(5@WIL3aiee(K9uWU)7l54P?P0t%+#H zBC*50s^10)Iel60v!w~gTjwv&k9RZ9ys{O|rwZp&JqC~R;LNF4Qg5N;AkHUowgN)M zEYQ48M4Yh}ZBL_mV}&I!gumhSEuQ%miWHF?gJ8yc@mxK6kBw?a z?=tguAJl{KT<@$$M=rx2acP5VeXaUmnUGo} z37%esLc|Qo3P{e2a4gy~T+Ow7AhOM`wYn1CmkHf;Q;70~2OtYtujwbENR4^;29a^Z|5gKk^O zom?@iN%9A#vXmKXW9uYwy73S*lK+K@ z#hAwqnd)5pLrRe@4TD2)GB?s5IlJ<-It`v5m;IAbszLCI>QWs^q%!6^bqvQQ8UySC zM8;XmgUSPR^}FO}tHQ86?FO$>GJ88jtBU(O%@^WVx=k0Ux{>uXf_jv@TXaQjKET)Ag+bnJ1d{ z9WS%c*-e=E`rVi+1I2wz*1GJdh{oe6vF*}EXG5aM(>X{=a|~rd=U52$GWJja7`03% z+)0qgFiDj6Ina@jve#}-Zr)rlq`=k!nDK7N>4}Zux;162uO9YX-z1T>cgUlvsZQy* zU^onxl9XEl;?Bwly}~NQr2DSnJx!wMax7hqmwD-gvaIdEDc8v%Z*!@4|ql> z1|obT0#ve)_hMTNBM0rR*ok{BO})9~HfskSwrvTPwA%eh=eT}T_)b8Psdmeb!iLyx zv~2>)`S3UfA3X89IQv96y`DZZ_YpAbQ|WRyD9x!SGcxl1W`8Rnc?I%l$u>a^1L-ul z?n3u?VZTH>#HPps>dFBUbVF9^5|u5eWDK@+v8X40^B#?D%Mw=2`38|*%CD#*)dCpoYoFj1_7VR1J!ZiQBCi}B{iGN0jw4cL~M23XIn0FmNFlQZc< z35g}l(fq>B;|N%lJrz_ql){{@%^=Hf#_v2;&UJ|GW)0XA2x5I08%|@%gm$U!Skm^o zQsHH$XWEo6NF2w_73MN_Z3G1CJ~keHM$0{N-7520=uV?sjZYx(bL>dgMg?VoZJan*Ict`<^oQi2(zy$5W#dE8es8Lm>11nb)kZ(Oio^Opq-k=#s01knoElx~k&(y0R}&?V;uFQ{fL zRrqb&fpXLC`w4~Xt2EBZ5Ox}Nn(o1*Y+qHcZ;4T2&H^#Cn^<Yb-Edj@`ZBE}mH&?fEV41EdWByW*9l3(vR&K;;j6!B=duia)zl)=#2gB)4 zX-r4z>%ie*x;t@Wd3TMRx+sB7S|&o))FE|$MP$1Oukvn5nE6MC}?R=5tNW9twvey@N3R7 zyW7$Ga#z=L2d=knAr^T1E0OFmU5#;Hcao)HYC6_^vR}4cC-Jv7uhXe3d6h&?g_5D% zLCbup`QKW~zbT_t4DiOI$xTrcb03stb?1XvMaxcr7J zta8Wou&1z>876>I*#`-O-v_T+g+n2yd<$5BsMab!J|nqoBELTp|KpqP96nWhF$VRB z9Fohgc5-Ns?{JyeYCbO9eS#FP^GVU&^~~Uuqs`T?HxW~I zQ4|5LP>jv9u%I{1mnv)ZF*_Cvh{d2u3cC2F4Wos8M_z(t;0Y-4hdn!FZ1FF8PS?Qgu=YbS#t)#CE%0K?g8}9b87zo* zQJ?%9!dr63@gDC5=1kxcUBbH%872c2v5#|-cKP?4`8VoJ5SbpAWaRHx>{5lnLQrSB z(ot&c9(-tv=`$3H56*17E>pLUMw1%hvtjl1(i7mv`nbhx=kVVT_iNb6H15^u-)wy) z;Z$su+By=GeW8C=OE5GjRVhwAk1!&|k*{*krr(QgD2Rd{ky`nhawNkybmk$SE7zR6 z3&9z;#}Iory#2N^4ZA1MbA`Fi)FlJnX0_kvML3|CXe4+h&EH3)ZWYDM#THWXUEx%A zRkkmlf-(8T!j@BVUkNW=l0(x)kU3Z$_MVBajxXP6=W^qF1^3Bio~B&X7{s=$G#2UA zv$@6+)S)5q8qDgZ%S6sH2R237@CGr?P6g(&V$3%krQ@tlF}4h{J-!(pGc8h7hvs_9SSp2olm*j%Ahoe%qUzt%^S$?xVNC372$ekViB)^ z$Cc+fO{U^agM9pLnyx8Q@A{LHPYT0ccn${|J-9ysm7v?H+Nd{qW$>Vo4}XEA-%I22 z%MJw`@dC~UqdijI*-(!1qY5h};tQ5HVX>7}CK5SmRRHCliFHs^Z{xIJCVr}c1yfY!=&`$zPRos$}Q8v#X6jLHF*C!;5y zt?*1aMAto&Ew}@!90;rlq<$M#9 zrQpTvy)?I+fiq1j7X9zSrQbWx$}XA3d#`TVW6Siqg+D z8Zdt6Q$GW~>Nc`ZuTYsxxs5nW)YJHlJR}p&oc92R$ilCN zz{CkRUd0rg2!3iN6T$0=giZoyPjwq7QR9mlYlBL1<1>2m)q!^5RK$yrKW zED}xT^fR>XO_S)E&az`&V3x{WA5tu#QEnKTT|=WMJkz0|)ykH#=np-+G}=u^@u2%W zd>Jm(rCVqb&ycpZcgz73no(qGnv{gox@K>^yR{$CQT@}&51{wJFN}e*MP%K&eV5P0U2zd_UvB_s1AHisN-kOni<&Tt_+(X-sk9n4q-k9 zi|^J4O*YPmgW@NAvVZRqzPDeikDpFr=3v)8|J*@$h#~_@56|PWEiW6H)BW{eW^Sg{ z+*2x)jN@e-UocAcWC#j`gXTtaKhzuDt9by@>5{}L-)c|SmSA0%R!UjT`B^1<+HgLc z#7fgxBp=NMLl0eLLEQ_KCFUU)mjS*>=4jjMVTIN}=_^YJ%M?ydfz5utno_b5i%!pY z`c>cPjt;`sM#ZemP-IdwkeWnaWk9v@WIGyVfU#p~p0ETN6lc-`TIn9AkBxFNYP?uo zEwBn|o08|%K&EEn5a(u>aGHK*BO<$4h=l@Eo_kx?O+)U7Z)!>4cc73FsuADSb@bP{ zVq2$932(oB3J^kmfR=EkRkW?F@LVh>2+{~cIaorzI?GDmKA?{Gp(wv5ZWm;Xhz4-;HLICDmVaGD#k*a0=zID1{NDPtcy~5eZ z8&iWUo&2@qX3Z!m0r%;Y7Lc|^_H8$0&63qqSC-)>70zME z0aC5bPHcdYbl^>*+$AX)M2V##TJ8Cr;AnBftlmBdf)2Ju5$#Q4fJdlm&$>t~tZ35L$Gr^kk{qQcxlXrC`nc0WP#^E2FF*fR+ z^*qE^g&y)vJ$pdhAqe*=!I})H)2yXJl9iP?$x99$aR&K%Ogl1;BAN|%1Z3i)UZzn{>V)VQnV8Mq>6O!KsZ;C=L+Ee#=P zZ!g#=th%DOIRghd$~8v{uA(wJ9t#ipJS8DpiR{_k+3s zLkOLy=h}ui6x1$R-J%&8(FFTxRx0qi)*W5%Xo_9D$fvN;Te@2YcPo(M^f68^H+K-_ z4)Q*hHlgWIBr)SC$!;pe!fxxnxAw*=8yC`(cI(d|z}>{BlR1dJk6S}(JgL2EHcrz- z%-k1Q&931@~HV(G;De}ukQ+exU>a~~VcDQoJ zd2kvT$r<5y5s@>9h#en}KMH*kr@8!;TG*EL?1ukBjXjKR4mqu!4s72wUZ#o&N5Hj> zD419!!XVZN*&1q2Ck*-ic+Aei^}~*?_OtxXsYgvb;U%06RbV~y`D5Lj<{KJ5xlaHQ zP#_rb!jOJiIJ5N!p2zja7tj|O!Z(Zjl6oVu912OWBR)Wu?$^!#rl`^Xix~6jm;tcU zaME{lvo*q{d1cE0IB36HHvoJe044rLQDX$i82_QV3~)F2Lw1?*l@jzf*=0FCHBn(P z07Z>om5%=3!ppy^{tHL#HQ{$A$baLgG5>eZkbgAyA4zII?G*mdUVimI`HN);z-I%X zy-WuXEoNYQ+=tgJ_Mg~^g*Y7Vn*6&*;fHBJd z@B4e+U%#wBDP62|3;@CqfQ|D%m6qBZ~=`K4+0jz+C&Us`ts-Tzo=dR@;CV}#4cRcKU@A!+^yHA_eV2yv@Cz+ zIKI9Of1dl(=LC@cXQi)>CoTYn*Pj>vfBK&Mm7n(q<%^aL;O6r?<%^Mt5%8w}I{Le8 zI1@b!!~abAidE56u!!pw3PmU(#T8}yh+G`PTZAuKiH|Fv=TFE>OBgqnCn^F8_9I&b zj7&Z+?Bhp#p{9=$y<;Bl$&gOcJt`e`?RLz(V_UY`ub*e?Yeu;}m%xQ{1|iF+1e?LUTQ;B8^Nc?aTmd#k7!P5S{lOfFzO%KnX@G72zh^CHM>#~V;`5mAF3g^Or`uGwjYrRiOL)i5uz>njNGi@E_IXqSf z-y;X8owbi3!fab^rAZda{uJIcIJ=KeI zCpztvFHVUV;E_UEv^@b)zQD99DoHHC4d{X~z@E5op#6B=fkbKab?xY2P((O^5ll89 z=Jd4q+OZ4s2yx;1*x5S02Ykq7d6$xJDI_t<5$)A{$qRful! zK#y;a-aY5@hOl&c3*;2;uM$d8n!iZVBYtcc=MgMJf061TLVO`9E2E@)UIhh0a=`Nz z(5Kw85oNT$h0T9sH)SJQXMYcYCrB{_*z0-@?5VYG$2(iy0Av%s;W=$T=^aj0rNNPd z663wZursfrr~g=oJa^K5z1*3lxfHEl(!=K0IZ+eiQ)KI+qCyCM(-$VH+1Ne@C!{G$ zIPn$=BEsui*S5fi*phDOr)m2K?U=XGOLdhYju*|K}0m5Xr2gKJA9GiO7M#@VAt?9i$L~nQM^oodfCQpOAO-SlMDCxx&RAVT} zZ_LcKp2qdWQf?!-L(HF(42Q<9>R8bf%M)0f8yo_MZ=9OiRmW~+O;r*qcA2W7yTTmn z?UcQ0QE+!91oqpK`V$5~3&ef$R~V!6OeJ#$UGP{+U)t7=-j!=uD@r$?Z#u(5gea{m zgpecfSfCA~89COV5G1(hW3=e3vwb3IM|I;aXM`QSY_R&4wJX|V&E$ON#1cRD-9e7w zE5G6qZ(aZA*AJgbw|piyn`X-7x-^g;@j_#^6}QLY%sch7^%iVXR?n0r~8 zgLJf@+dAu$a=(e@?uTNhqgLh8gaMZW#3y+q5BKFj9*vV!9Ok)3GOdzKp`=D&tmG%_ zl}GFaJClbNZJJ3fqY&uN&qKD>R3beP=R{ zwlznX4jY+SdDyp9h11Z%w^^EvWq=$g<{?(zs^g=${AC4i0z;Y$-?SUWhHB4Isy7nJu@Sn zeo+hS68L+1Y*Fq-jJbCsRhm=SfOTAQEv{9O&WS}=M8CQ)8&zdg3~ISL>;3O;Fx>@j#x(z zDh-cS!@3F$+G16gt~^lo1ZFc2SeDY=H#Ncqicb9zxQ4^OkG>~wI*2+Tjx7Zf$%^W0 zyt_q^!t5a^x{i5|uPVdBqwA&UW8l6rGQw10jqEx*Ja@+MZgxxCo@H#+>1=I(F;~r% z-Xt@JvGweBPeMuwM_s#S`5WfiprcIrVEoR;^ia;l&NCKIrv{hG&M2EqOe*(?hYN!1 z*W0J4PC37KEcvca8+;})T}?>u$sg7;@Z=dw;_&?RcZr~2AHBh85{)nwzn-z>`X=;> zByD4*s+`sMHo2}lScOfRAk>U&P4$IpZQp2jcE>cBq3LzXoX?s5b3EgMI9M_L4n3>T^0++yjt=8(cr&u16S zmc`tJNCNGURo6NVeU(P)!i2k80%1J84EcatSrID(og(12wgM8p#9yg#1>SGtq)y1sC!)HX&^SC~tj^flLnDcNW-Kh#l z@-LK9UtBXZK7t0eP-nLTq5VWUCH7LYb@**6PKLmAqsE393rbxLML;|y+Zglgw%L^6 zB{`_OX+{M1pj*Oyl^;O_TY8sRlEo-h$LMCG9F6T@RX+BZk7iyI57a`ac$H9e&c4Fy zYqO%d!v4xw%HW3~-2t;6FCkX-1ND38S;Rz1*rt20j3|$0LZQ5^PSV8i-rn+}4{$7{ zjbw?P(K!S4ROW~Erko?x%jDd_$?KMFdrV>;<4V&dF&H)RVET8BOtg6M{ODp5A&Cbo zu&fNFu;;09-=sRlwi*QNu<}vf!IyDF08{%PXp7#*VX9HAg5fT3M7wujeIpaLPosS5 zCNBuum1*cVaP;sqX5v6}<71gm#(@9<;fsdtDM~;`q$He_T$KJ*J9zLYJ*r9 zcWmzun*6Is2h@zcHD?hiFtL%)%m@z_)o^e{pN~a4iv$!h2)@64>4&f*&wT7@&fv6; zY*PAM6SHUPZiP;$}Q zWfR~!m?`w0RtNA+L8QJVXm44WbKA8xD@h-T<%Cro#k$uTzM!aqP~SF|+Hdp9pwb}#5FzceWwEva?R&00-bObg`b zjBad9TCh*@gcP>TLkKv7VLW^W16Ls!VUsH1EXS}DBo;N75^^6Q6Hwf1jo>MK%sXRC z?loDciaEkt4fGuGpJ0x-3XYQ|`*Dc1PHs6KS&wizHh>4>k$fVOZbhNdbx zJ_lc73%^sHVED#A-@ImG!NKNP-_4%mHGYv%hKP)tL@NjrnK`F%oYC+Ntr4e}$?+~- zvLSWmsA{~xev4rJ=7W_UTsY$RG<#MGLgSF{u(vr5n}HI8y#RcC?Zw(6=RS$^QSa`} zH%Ky*gvL#x2vG|+R#n_D)O=U-EwDK;2%d(mQQ`;zk!wP3My;^z@Lx8}qbgNlMq|M; z%KmT52$1a-Xh=>SY*O_6>$Hp{i=J z>ih08S(Oqi_RUrwg#)E6Rk$B>oYKV-BR^Ofkv~bN{DT$`%NkY$uEEypG$={R+`=p4*;~=6385&1QC^*-z61@Eq%!>$ zG{S~H$dHGZ@N`*dm? z-4qZR_n^uWde=tjIZsBNKq;j!(R+7o!EZx-HZ6fkN*~jFTbn}`qfo0}MB6bH(y0)f389gWgM&Qo?<{RC2d(_k7?+BjL-}9B(r8Vc zRRE2b8Ap>HhwU%&VYj-JFhYVYNuu%A4Z7f`&kiFkXRH|p-4WczK3Gj?gyyuYy8WS7hBdux z>bq*F39UtlVqF{Q6b!sg-;^DjNu&rVdr#L&aBf1*S_^!Sp91H*>jO}v3ZB3@D}Pu~ zPnx*8r$qnQz&X!L4_JB1meS+B!tHYx4~kYdixrbF%-D}@U0i2T-o&7Zd%L${0nP~P z;F$=HT04*})!UTP!kk3F*DN>SneC_V-TZ0YbDsUYnE%XpR_=P@eX^tu53|FJTJ4do z0&KRRHO;06{^m+SED)S2fu{%u{ZPFTxc}&kqV1P7>6k+7WZp^fvM#= z&u_$1{2@17ml2EA^eU5nl8x%d4~Y2)iKm}hBVY_ZzEgPPJg_twu^qTbsBcCh!by4w z<*AP*&qbYKBbA$bxA629>;eMMwA5!x+xC0-rRA+x^|5!6S=UAE2=RbSB6wn33zxCz zl$spDp?1rJj8lrY9%ij3Vr4ATB&VJ;pRwoK57N&y*xirA1&A@c z=(esWXwF}i7j7i2`Efdyn~A=!P#M0Pw_wrStbFaj z4k=}FKNrKw=2}Za;spxovAKaAaeXEIxa5RQdw-YaMDBfNA-9hjVf(3N@T7E6<~>Lf z^!-;ViYT2auEfd*?cik9rLiboFSv=z?t%8ELFHzq*w|}Wx+J1=0{^?`xN=2X>oV2l z`{+?SN24CDnZQ(>r~OWPiEZjt=nk77j>XhIE^+QHy;Jwqc;R^6+Rz*hRMf==1(j*v z#M;doW-gT{*lS5I4Q3oEDls42nZG_h$1zXmqR#~Jh|64Kw(Bd9OT%4wP}Q)08bb<& zfN%cB(C_#8O`s+?lOFNlW~r#8WDG^5Z@P^X6QlP>JL*!>d`V{E@}1ZY&HnU_7YCbHM&+iVqrsgjjS2kVq_ ziI{V$xvdcfiDs6&E$h!Pr?ja_u#$X+ee9)T@7!o@oWJ11$r@G$k>ARWPxd-;)KOoI zGqK!nu^w$lv?CLA$$Bbz@?hVGR!sn31@9inW$(?oVI*FHb=#4tn`>8L$G-l|kjY9Y zF9M1lK*|F7#^z*<6Q_jiGlpb4J+H-LJUfNU19|USV)kWL5VM}Wm%)kfsgwbb2TC`b zmByA^DgnJdr+q)+dHAJLIC#<6{9?{hrt(cuC&Kp>M;;c981!qiI%MY4nY^^!!YG;~ zhAH8X-tiL+es_M-rA&;fZtDWvqoGcs($@C%T2{~iiM66N!>!g#t>Zxr^6El95Bl$) zK1IVS<>ArS!Q`}zB0Q}6b+vM&fPOyLP0c<|r8W>xL1p8S_&V$Q-bdx_CzJD>xYWT1 zbVb4n2g*a?u2iP(5B)Tjt5W>%D*+}rLDYe5-(gCZjqUR>(Mvo#fw?wk393A0-s9=N zXu2Njof~O;CXyD9LmVm$f7A{oiXa9{ehc4JNr86K>RDzTGPqQ**Pq08TQq(MDG+|3 zP@CXIdMP3VY4PTL5Dl|G@i!MK*_yPp2Qb|Vfq4-r;7aH66Hs2i6S+aV*|$;W`E0u{Z*V19$AaS$Haa8EZD`N}QUP#pP#B zU!d~5+SwljYpw2oA~VFUQK!D3xb?XOdTQ@{fdXO0fO6>7OV_Qq;d=p!i|$nU7cTSL zx^P@hPUxQq4DL@<;{SqWUW4g>hh+dz#-FeZ9l+=EH#f|mrs02sWyF=FrDUakDhK=< zmHFkJ`6rt2o0a6xOZ#t_%>Uuz{`a>2BP8?c-1!G0^A8hu2F72A3>)juh2{SlkolX1 zyStG+V7>nzYyN+sE_#lDW&h$o7d`9!X6XL9V)@r9{+~wffA!ORjZXh{+5XQS{0XSg zv%L2EuPr0nD}eF3{k8WC-1zJMuN0O)fDabNzd|ugw68$L-~X5Z&9saifPd-Fvp=uzHH87-)6M``u>YF+Cn)l7DDZdC4}h?l85zZ~Z=3m$tF4JG^-Wh51905uM ze-!?g|2rd%_+OX3v;IUr{^{+G%l0Qk!N&IM$-k-;{88AXw5z~`(z$8W#Jp6(86RKg6_wNDJGSLm(gb#SyG3A z8X6%WkSc}&>lcI4i(yKD#RI7^s-tv_X})0t#VyUF{4AfK@R1jYs-}=90D#GZ5q^oZ zevbzf4k3!SRz=u>CgB9em4v}c`K}6g6B2h?2OMAo|M6}H)~4gbB{&&3t~NM6#oIL~ zR`NB_CInH0+XOtX7zT9SXUI*n44-^Y-cXiFWZVHpH)LJ)o>(zKpEvOA0&B#EI~ur? z13ukTCmT(S_~W1l)kN*ndF}bt*q}KtJa7B4GZ@K5fx-t|qxkPzr!XGZhtYbFOtITd zu8LLhfr9WF5%}Jm5eS~n5Z!)qWdMG^3(aZ}va)u=D%$m8?K@w8g0fa{&rCuoBleQC zdy|Hqz?-9f@A0g-O#VDl)1EYs1>Ff>CD4zHP&358b9XTMTwm`f%1WQXt55BpgZMFD zw(1#S$Cy^^9b^<3Bq8S>#7A$*Zd-K3yKrayxP|VA~<(JqSFYh8Y@u zAlsu%e?{OmVIHV}H*3c2qCg)to(UN-K5lx)Q2O41uIoer`SguZJYV99NS_VC#ww8GzONx`Mw z#!THV^+#=V-(}vUTlwtHBKJ;`n7KyVDjQ+f`PfL|xt?(Y;)F1ZpDQ_ejwZi$kEcxv zDwjH*`J9W5{KoZqq2BItj`Or=yEg9Zq-)#O@nBnxn{%OnGn{|Dqp=9j;ulW5MtXUB zYZr3H6Vm{#YMxIf0@TWC_7O{W(ETzVr6LZjK6*|X0%R)2JJdI`NDMOF@I}jJ50qx? z4j&5N*^L@nc1Og=#Z35wI`an;=^nXe+?6%WN?dh?c1G(JH^j}@RvLfj`RmmIisQl-fzcgQzVhowYrE{?l>H)B48K+>@j9FRgpDX1u})3 zP@D4{`gnPwsJ$OT%-iAEuIJqH30a!Kkdn9Rw&LLwp1hDtg|$Gc`%j+aaNW* z)mkpWmC^;>go6-%sOgKze56MHhME1{2EvgAzc+GewGf?Svj7|i*2XL}0`F`>f#sRPC><_V?jG>hy&~FRn?wLzOR{iyZvZ zh|%NC4uO)-Fg=q$AqszQ)tlYd)|~1%X8VQ?iPQW{Bz3t+#=PiVWWAqJHE%N77&?eD zKLN!0qI<09>C{-jTta4>z;~jFlq5vXdTv5a% z2)E`UlJ`OhJqbIG89WJ zH817b@%Hb9-S7mrZl{dCd?p)dDFKuH`on`r?>b@r+y|`|X3A47fQoE}x>D_qfMUj> z^&3RHxrL}P3(FF;vxPHd4W%sEIW`S7(oy+Dd?fb9H?tj5p8krO>Gh(cGfzV;uQizr zci>BbkjcB!L_+J&Z+xe&`$q}1=TO-Jie5`>Mx6w&2(b$Uqp3Otm#zuyIDhNc+gn^e zouwmF5T~5c3ttQVfn({(`&w`G$l02lk>xPlBMgP}hY9h_6G(ANjPj>K8L%8zCt}b*1|$Qe9RhnKz{2H7 zfsEnz&4{B=IPxp22l8?v2^L#56G>shm(>MB2)9XPYDMO}0Uq?V z8ljFBix=5^#>2`d<;VBQm>Bn>?LG6gM!aWf-5iLP_e>esq%A zY!px(f6z7)oS6rzjyNmxm-E`rIDH&DJqB@gE>$tPrjVRsAsol$d$=nQc-4n$%oD)L>JE~xXllXQbN#bAy6b$Q$J`I6!o{@lBvEzylu@;w7du1zEqgtb>ysL z$J1r*TML14JJjL(irS!az@^k0WatRsgmVyRIcqr1jM2)VdT3|+<#Kv-hc(LPtFfq_ zM|3Z5!|7Y-n*$3@9m%rX_Jm=HkQa}>u{r$uY)n=m01H>+kWdl^e8S5nf>JzOK|Jf(d`jfvxNFDBLEpxFMU zWs#?{62PGJ4RN8z8;!>>ka`D0!IZ9m`aNI~ipLVty?n=UalDf|KaV3FT8mS{z_j+-(i+dfGVJzi|J` zxm|W1YZ{ppptRZ<7TcDd7k|B@HTvn$LdKIgN5&o*5@fhGzPFr2ekK84 z;xbJg7XvLMg|^Dux=Gb2^YYT;2d14~J3^glwzzk~?51C)zTig+JY(nS&fAw~V&tb}w^G0>~7Q}L*N@W#{0$SApi z=4bSz_R2#hb6F$=sBT8d`FzRkJCoZISvkP$rs+}(sYOOjr+Eie$@0c2ThWAMnr*VJ z4Z<W(hvj_*Gr3U=JH5w zVmE4=k2&T^L$38hG^;tk5H95tvenW4b@X%UR-F2$LK~KDmve6dtV17*blI*m@)8t! z(ju}t^6u$uP5qcJ$nM0zF*sVmx35BjV9z9=wt@%}*)d#I$S(anZ&a@M`~DRxcomHM zJDKhON8x;xZ~I%U;C06RXRP3_6wcR4%->=KGGeNtib_9Y1%QykYfFMg4hHsSwvIOT zxW6j?Ggk0={QIT-Z?OWvg}l}&t!D+`p8mb9{}?M^0)!g=YpmcWdy^KIjS)aRWMuo# zv4UUJOG$v@pCVv7XadW1<(__<*FkGAv%OB(nVA8Rh<{DdnE(vPUsHKz zfDqkpdw`t3_Wtvh5g>Q>=NbCnWb=OiePuTOdG_}`Mu0BgpHuk1_V@qHYy8j5LtN%R zC+e>fasW-iKPJilVi_{hDE@7x4VYO2X3&4({?Ri1YfjBdV+qLfXCrg~xjmb|&#>v~ zXx#prN*qAu@6WOI>t1E`OpF|$X#{MXtQ~Oy<3hsB5D=~S85jf1wE@}X0Sbe!KYyL2 zGyePa5zuqgv$QdRrukVR?$4G0?|`hLkSevXlclA;p0%}+Jua!DshI;V;NRBJSkXw8 z5?9&C-oebq8kd2Zj**Uujh>2*nvPbV4Eir)=dZytS$i8pCxh3Dq|77$75rAu@1Is0b~*I`VKYvYu2P>KJ;x|(Dt<$7j_WDFR)x`OG) zvz?d@y6c6~y1Eh}UyvH&5U7vuhzWeOBuw}%r`vj)ANO_e-vD3p-`#uql&&z3e0un+#K>z>% diff --git a/tommath.h b/tommath.h index e5e166b..f5c2ad1 100644 --- a/tommath.h +++ b/tommath.h @@ -1,9 +1,9 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * - * The library is designed directly after the MPI library by + * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * @@ -82,8 +82,10 @@ extern "C" { typedef ulong64 mp_word; #ifdef MP_31BIT + /* this is an extension that uses 31-bit digits */ #define DIGIT_BIT 31 #else + /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ #define DIGIT_BIT 28 #define MP_28BIT #endif @@ -94,7 +96,6 @@ extern "C" { #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */ #endif - #define MP_DIGIT_BIT DIGIT_BIT #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_DIGIT_MAX MP_MASK @@ -121,7 +122,7 @@ extern int KARATSUBA_MUL_CUTOFF, TOOM_SQR_CUTOFF; /* various build options */ -#define MP_PREC 64 /* default digits of precision (must be power of two) */ +#define MP_PREC 64 /* default digits of precision */ /* define this to use lower memory usage routines (exptmods mostly) */ /* #define MP_LOW_MEM */ @@ -135,11 +136,13 @@ typedef struct { } mp_int; #define USED(m) ((m)->used) -#define DIGIT(m,k) ((m)->dp[k]) +#define DIGIT(m,k) ((m)->dp[(k)]) #define SIGN(m) ((m)->sign) -/* ---> init and deinit bignum functions <--- */ +/* error code to char* string */ +char *mp_error_to_string(int code); +/* ---> init and deinit bignum functions <--- */ /* init a bignum */ int mp_init(mp_int *a); @@ -165,7 +168,6 @@ int mp_grow(mp_int *a, int size); int mp_init_size(mp_int *a, int size); /* ---> Basic Manipulations <--- */ - #define mp_iszero(a) (((a)->used == 0) ? 1 : 0) #define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? 1 : 0) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? 1 : 0)