# libtom/libtommath

1 parent eed6765 commit 03cc01b5782df0d91fbc6ccf13279097d0e9b6f0 Tom St Denis committed with sjaeckel Jul 16, 2003
Showing with 398 additions and 71 deletions.
1. bn.pdf
2. +6 −4 bn.tex
4. +1 −1 bn_mp_gcd.c
5. +1 −1 bn_mp_prime_miller_rabin.c
6. +1 −1 bn_mp_prime_next_prime.c
7. +53 −8 bn_mp_sub_d.c
8. +9 −0 changes.txt
9. +30 −5 demo/demo.c
10. +1 −1 etc/makefile
11. +54 −18 etc/pprime.c
12. +6 −3 makefile
13. +26 −2 mtest/mtest.c
14. poster.pdf
15. +133 −19 pre_gen/mpi.c
BIN bn.pdf
Binary file not shown.
10 bn.tex
 @@ -1,7 +1,7 @@ \documentclass[]{article} \begin{document} -\title{LibTomMath v0.23 \\ A Free Multiple Precision Integer Library \\ http://math.libtomcrypt.org } +\title{LibTomMath v0.24 \\ A Free Multiple Precision Integer Library \\ http://math.libtomcrypt.org } \author{Tom St Denis \\ tomstdenis@iahu.ca} \maketitle \newpage @@ -389,7 +389,7 @@ \subsection{Primality Routines} /* finds the next prime after the number "a" using "t" trials * of Miller-Rabin. */ -int mp_prime_next_prime(mp_int *a, int t); +int mp_prime_next_prime(mp_int *a, int t, int bbs_style); \end{verbatim} \subsection{Radix Conversions} @@ -832,9 +832,11 @@ \subsubsection{mp\_prime\_is\_prime(mp\_int *a, int t, int *result)} function will always set $result$ to $1$. If $a$ is composite then it will almost always set $result$ to $0$. The probability of error is given in figure two. -\subsubsection{mp\_prime\_next\_prime(mp\_int *a, int t)} +\subsubsection{mp\_prime\_next\_prime(mp\_int *a, int t, int bbs\_style)} This function will find the next prime \textbf{after} $a$ by using trial division and $t$ trials of -Miller-Rabin. +Miller-Rabin. If $bbs\_style$ is set to one than $a$ will be the next prime such that $a \equiv 3 \mbox{ (mod }4\mbox{)}$ +which is useful for certain algorithms. Otherwise, $a$ will be the next prime greater than the initial input +value and may be $\lbrace 1, 3 \rbrace \equiv a \mbox{ (mod }4\mbox{)}$. \section{Timing Analysis}
 @@ -18,15 +18,84 @@ int mp_add_d (mp_int * a, mp_digit b, mp_int * c) { - mp_int t; - int res; + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; - if ((res = mp_init_size(&t, 1)) != MP_OKAY) { - return res; + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } } - mp_set (&t, b); - res = mp_add (a, &t, c); - mp_clear (&t); - return res; + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix sign */ + a->sign = c->sign = MP_NEG; + + return res; + } + + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* setup size */ + c->used = a->used + 1; + + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; + + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + *tmpc++ = b - a->dp[0]; + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; } +
 @@ -29,7 +29,7 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) return mp_copy (a, c); } if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { - mp_set (c, 1); + mp_zero(c); return MP_OKAY; }
 @@ -53,7 +53,7 @@ mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) */ s = mp_cnt_lsb(&r); - /* now divide n - 1 by 2^s */ + /* now divide n - 1 by 2**s */ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { goto __R; }
 @@ -112,7 +112,7 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) /* y == 1 if any residue was zero [e.g. cannot be prime] */ y = 0; - /* increase step to next odd */ + /* increase step to next candidate */ step += kstep; /* compute the new residue without using division */
 @@ -18,16 +18,61 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) { - mp_int t; - int res; + mp_digit *tmpa, *tmpc, mu; + int res, ix, oldused; + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } - if ((res = mp_init (&t)) != MP_OKAY) { - return res; + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + a->sign = MP_ZPOS; + res = mp_add_d(a, b, c); + a->sign = c->sign = MP_NEG; + return res; } - mp_set (&t, b); - res = mp_sub (a, &t, c); - mp_clear (&t); - return res; + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { + *tmpc++ = b - *tmpa; + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract first digit */ + *tmpc = *tmpa++ - b; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + + /* handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + } + } + + for (; ix < oldused; ix++) { + *tmpc++ = 0; + } + mp_clamp(c); + return MP_OKAY; } +
 @@ -1,3 +1,12 @@ +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 + e.g. (0,0,a) == a [instead of 1] + -- Should be one of the last release for a while. Working on LibTomMath book now. + -- optimized the pprime demo [/etc/pprime.c] to first make a huge table of single + digit primes then it reads them randomly instead of randomly choosing/testing single + digit primes. + July 12th, 2003 v0.23 -- Optimized mp_prime_next_prime() to not use mp_mod [via is_divisible()] in each iteration. Instead now a smaller table is kept of the residues which can be updated