added libtommath-0.29

This commit is contained in:
Tom St Denis 2004-01-25 17:40:21 +00:00 committed by Steffen Jaeckel
parent 455bb4db20
commit 6c48a9b3a6
33 changed files with 13855 additions and 12934 deletions

6
bn.ilg
View File

@ -1,6 +1,6 @@
This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support). This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
Scanning input file bn.idx....done (53 entries accepted, 0 rejected). Scanning input file bn.idx....done (57 entries accepted, 0 rejected).
Sorting entries....done (317 comparisons). Sorting entries....done (342 comparisons).
Generating output file bn.ind....done (56 lines written, 0 warnings). Generating output file bn.ind....done (60 lines written, 0 warnings).
Output written in bn.ind. Output written in bn.ind.
Transcript written in bn.ilg. Transcript written in bn.ilg.

6
bn.ind
View File

@ -14,6 +14,7 @@
\item mp\_error\_to\_string, \hyperpage{6} \item mp\_error\_to\_string, \hyperpage{6}
\item mp\_expt\_d, \hyperpage{31} \item mp\_expt\_d, \hyperpage{31}
\item mp\_exptmod, \hyperpage{31} \item mp\_exptmod, \hyperpage{31}
\item mp\_exteuclid, \hyperpage{39}
\item mp\_gcd, \hyperpage{39} \item mp\_gcd, \hyperpage{39}
\item mp\_grow, \hyperpage{12} \item mp\_grow, \hyperpage{12}
\item MP\_GT, \hyperpage{17} \item MP\_GT, \hyperpage{17}
@ -23,7 +24,7 @@
\item mp\_init\_size, \hyperpage{10} \item mp\_init\_size, \hyperpage{10}
\item mp\_int, \hyperpage{6} \item mp\_int, \hyperpage{6}
\item mp\_invmod, \hyperpage{40} \item mp\_invmod, \hyperpage{40}
\item mp\_jacobi, \hyperpage{39} \item mp\_jacobi, \hyperpage{40}
\item mp\_lcm, \hyperpage{39} \item mp\_lcm, \hyperpage{39}
\item mp\_lshd, \hyperpage{23} \item mp\_lshd, \hyperpage{23}
\item MP\_LT, \hyperpage{17} \item MP\_LT, \hyperpage{17}
@ -43,12 +44,15 @@
\item mp\_prime\_next\_prime, \hyperpage{34} \item mp\_prime\_next\_prime, \hyperpage{34}
\item mp\_prime\_rabin\_miller\_trials, \hyperpage{34} \item mp\_prime\_rabin\_miller\_trials, \hyperpage{34}
\item mp\_prime\_random, \hyperpage{35} \item mp\_prime\_random, \hyperpage{35}
\item mp\_radix\_size, \hyperpage{37}
\item mp\_read\_radix, \hyperpage{37}
\item mp\_rshd, \hyperpage{23} \item mp\_rshd, \hyperpage{23}
\item mp\_set, \hyperpage{15} \item mp\_set, \hyperpage{15}
\item mp\_set\_int, \hyperpage{16} \item mp\_set\_int, \hyperpage{16}
\item mp\_shrink, \hyperpage{11} \item mp\_shrink, \hyperpage{11}
\item mp\_sqr, \hyperpage{25} \item mp\_sqr, \hyperpage{25}
\item mp\_sub, \hyperpage{23} \item mp\_sub, \hyperpage{23}
\item mp\_toradix, \hyperpage{37}
\item MP\_VAL, \hyperpage{5} \item MP\_VAL, \hyperpage{5}
\item mp\_xor, \hyperpage{23} \item mp\_xor, \hyperpage{23}
\item MP\_YES, \hyperpage{5} \item MP\_YES, \hyperpage{5}

BIN
bn.pdf

Binary file not shown.

44
bn.tex
View File

@ -1001,10 +1001,10 @@ algorithms all which can be called from mp\_sqr().
\section{Tuning Polynomial Basis Routines} \section{Tuning Polynomial Basis Routines}
Both Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that Both Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that
the Comba and baseline algorithms use. At $O(n^{1.46})$ and $O(n^{1.58})$ running times respectfully they require the Comba and baseline algorithms use. At $O(n^{1.464973})$ and $O(n^{1.584962})$ running times respectfully they require
considerably less work. For example, a 10000-digit multiplication would take roughly 692,000 single precision considerably less work. For example, a 10000-digit multiplication would take roughly 724,000 single precision
multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor
of 144). of 138).
So why not always use Karatsuba or Toom-Cook? The simple answer is that they have so much overhead that they're not So why not always use Karatsuba or Toom-Cook? The simple answer is that they have so much overhead that they're not
actually faster than Comba until you hit distinct ``cutoff'' points. For Karatsuba with the default configuration, actually faster than Comba until you hit distinct ``cutoff'' points. For Karatsuba with the default configuration,
@ -1175,10 +1175,48 @@ there is no skew on the least significant bits.
\chapter{Input and Output} \chapter{Input and Output}
\section{ASCII Conversions} \section{ASCII Conversions}
\subsection{To ASCII}
\index{mp\_toradix}
\begin{alltt}
int mp_toradix (mp_int * a, char *str, int radix);
\end{alltt}
This still store ``a'' in ``str'' as a base-``radix'' string of ASCII chars. This function appends a NUL character
to terminate the string. Valid values of ``radix'' line in the range $[2, 64]$. To determine the size (exact) required
by the conversion before storing any data use the following function.
\index{mp\_radix\_size}
\begin{alltt}
int mp_radix_size (mp_int * a, int radix, int *size)
\end{alltt}
This stores in ``size'' the number of characters (including space for the NUL terminator) required. Upon error this
function returns an error code and ``size'' will be zero.
\subsection{From ASCII}
\index{mp\_read\_radix}
\begin{alltt}
int mp_read_radix (mp_int * a, char *str, int radix);
\end{alltt}
This will read the base-``radix'' NUL terminated string from ``str'' into ``a''. It will stop reading when it reads a
character it does not recognize (which happens to include th NUL char... imagine that...). A single leading $-$ sign
can be used to denote a negative number.
\section{Binary Conversions} \section{Binary Conversions}
\section{Stream Functions} \section{Stream Functions}
\chapter{Algebraic Functions} \chapter{Algebraic Functions}
\section{Extended Euclidean Algorithm}
\index{mp\_exteuclid}
\begin{alltt}
int mp_exteuclid(mp_int *a, mp_int *b,
mp_int *U1, mp_int *U2, mp_int *U3);
\end{alltt}
This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that the following equation holds.
\begin{equation}
a \cdot U1 + b \cdot U2 = U3
\end{equation}
\section{Greatest Common Divisor} \section{Greatest Common Divisor}
\index{mp\_gcd} \index{mp\_gcd}
\begin{alltt} \begin{alltt}

View File

@ -41,7 +41,7 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
/* now subtract 3 * [w/3] from w, to get the remainder */ /* now subtract 3 * [w/3] from w, to get the remainder */
w -= (t << ((mp_word)1)) + t; w -= t+t+t;
/* fixup the remainder as required since /* fixup the remainder as required since
* the optimization is not exact. * the optimization is not exact.

View File

@ -28,8 +28,7 @@ static int s_is_power_of_two(mp_digit b, int *p)
} }
/* single digit division (based on routine from MPI) */ /* single digit division (based on routine from MPI) */
int int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
{ {
mp_int q; mp_int q;
mp_word w; mp_word w;

69
bn_mp_exteuclid.c Normal file
View File

@ -0,0 +1,69 @@
/* 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 <tommath.h>
/* Extended euclidean algorithm of (a, b) produces
a*u1 + b*u2 = u3
*/
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
int err;
if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
return err;
}
/* initialize, (u1,u2,u3) = (1,0,a) */
mp_set(&u1, 1);
if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
/* initialize, (v1,v2,v3) = (0,1,b) */
mp_set(&v2, 1);
if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
/* loop while v3 != 0 */
while (mp_iszero(&v3) == MP_NO) {
/* q = u3/v3 */
if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
/* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
/* (u1,u2,u3) = (v1,v2,v3) */
if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
/* (v1,v2,v3) = (t1,t2,t3) */
if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
}
/* copy result out */
if (U1 != NULL) { mp_exch(U1, &u1); }
if (U2 != NULL) { mp_exch(U2, &u2); }
if (U3 != NULL) { mp_exch(U3, &u3); }
err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
return err;
}

View File

@ -19,9 +19,8 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream)
char *buf; char *buf;
int err, len, x; int err, len, x;
len = mp_radix_size(a, radix); if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
if (len == 0) { return err;
return MP_VAL;
} }
buf = XMALLOC (len); buf = XMALLOC (len);

View File

@ -42,7 +42,6 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c)
} else { } else {
res = s_mp_mul (a, b, c); res = s_mp_mul (a, b, c);
} }
} }
c->sign = neg; c->sign = neg;
return res; return res;

View File

@ -15,26 +15,28 @@
#include <tommath.h> #include <tommath.h>
/* returns size of ASCII reprensentation */ /* returns size of ASCII reprensentation */
int int mp_radix_size (mp_int * a, int radix, int *size)
mp_radix_size (mp_int * a, int radix)
{ {
int res, digs; int res, digs;
mp_int t; mp_int t;
mp_digit d; mp_digit d;
*size = 0;
/* special case for binary */ /* special case for binary */
if (radix == 2) { if (radix == 2) {
return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
return MP_OKAY;
} }
/* make sure the radix is in range */ /* make sure the radix is in range */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return 0; return MP_VAL;
} }
/* init a copy of the input */ /* init a copy of the input */
if ((res = mp_init_copy (&t, a)) != MP_OKAY) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return 0; return res;
} }
/* digs is the digit count */ /* digs is the digit count */
@ -57,6 +59,7 @@ mp_radix_size (mp_int * a, int radix)
mp_clear (&t); mp_clear (&t);
/* return digs + 1, the 1 is for the NULL byte that would be required. */ /* return digs + 1, the 1 is for the NULL byte that would be required. */
return digs + 1; *size = digs + 1;
return MP_OKAY;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* read a string [ASCII] in a given radix */ /* read a string [ASCII] in a given radix */
int int mp_read_radix (mp_int * a, char *str, int radix)
mp_read_radix (mp_int * a, char *str, int radix)
{ {
int y, res, neg; int y, res, neg;
char ch; char ch;

View File

@ -18,7 +18,7 @@
int mp_shrink (mp_int * a) int mp_shrink (mp_int * a)
{ {
mp_digit *tmp; mp_digit *tmp;
if (a->alloc != a->used) { if (a->alloc != a->used && a->used > 0) {
if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
return MP_MEM; return MP_MEM;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* get the size for an signed equivalent */ /* get the size for an signed equivalent */
int int mp_signed_bin_size (mp_int * a)
mp_signed_bin_size (mp_int * a)
{ {
return 1 + mp_unsigned_bin_size (a); return 1 + mp_unsigned_bin_size (a);
} }

View File

@ -19,6 +19,7 @@ int
mp_sqr (mp_int * a, mp_int * b) mp_sqr (mp_int * a, mp_int * b)
{ {
int res; int res;
/* use Toom-Cook? */ /* use Toom-Cook? */
if (a->used >= TOOM_SQR_CUTOFF) { if (a->used >= TOOM_SQR_CUTOFF) {
res = mp_toom_sqr(a, b); res = mp_toom_sqr(a, b);

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* stores a bignum as a ASCII string in a given radix (2..64) */ /* stores a bignum as a ASCII string in a given radix (2..64) */
int int mp_toradix (mp_int * a, char *str, int radix)
mp_toradix (mp_int * a, char *str, int radix)
{ {
int res, digs; int res, digs;
mp_int t; mp_int t;

View File

@ -31,25 +31,7 @@ static const struct {
{ 1408, 3 }, { 1408, 3 },
{ 1536, 3 }, { 1536, 3 },
{ 1664, 3 }, { 1664, 3 },
{ 1792, 2 }, { 1792, 2 } };
{ 1920, 2 },
{ 2048, 2 },
{ 2176, 2 },
{ 2304, 2 },
{ 2432, 2 },
{ 2560, 2 },
{ 2688, 2 },
{ 2816, 2 },
{ 2944, 2 },
{ 3072, 2 },
{ 3200, 2 },
{ 3328, 2 },
{ 3456, 2 },
{ 3584, 2 },
{ 3712, 2 },
{ 3840, 1 },
{ 3968, 1 },
{ 4096, 1 } };
/* returns # of RM trials required for a given bit size */ /* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size) int mp_prime_rabin_miller_trials(int size)

View File

@ -20,8 +20,7 @@
#define TAB_SIZE 256 #define TAB_SIZE 256
#endif #endif
int int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{ {
mp_int M[TAB_SIZE], res, mu; mp_int M[TAB_SIZE], res, mu;
mp_digit buf; mp_digit buf;
@ -185,10 +184,10 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
/* then multiply */ /* then multiply */
if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
goto __MU; goto __RES;
} }
if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
goto __MU; goto __RES;
} }
/* empty window and reset */ /* empty window and reset */

View File

@ -1,7 +1,18 @@
Jan 25th, 2004
v0.29 ++ Note: "Henrik" from the v0.28 changelog refers to Henrik Goldman ;-)
-- Added fix to mp_shrink to prevent a realloc when used == 0 [e.g. realloc zero bytes???]
-- Made the mp_prime_rabin_miller_trials() function internal table smaller and also
set the minimum number of tests to two (sounds a bit safer).
-- Added a mp_exteuclid() which computes the extended euclidean algorithm.
-- Fixed a memory leak in s_mp_exptmod() [called when Barrett reduction is to be used] which would arise
if a multiplication or subsequent reduction failed [would not free the temp result].
-- Made an API change to mp_radix_size(). It now returns an error code and stores the required size
through an "int star" passed to it.
Dec 24th, 2003 Dec 24th, 2003
v0.28 -- Henrik suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't v0.28 -- Henrik Goldman suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't
spew [erroneous] diagnostics... fixed. spew [erroneous] diagnostics... fixed.
-- Henrik also spotted two typos. One in mp_radix_size() and another in mp_toradix(). -- Henrik Goldman also spotted two typos. One in mp_radix_size() and another in mp_toradix().
-- Added fix to mp_shrink() to avoid a memory leak. -- Added fix to mp_shrink() to avoid a memory leak.
-- Added mp_prime_random() which requires a callback to make truly random primes of a given nature -- Added mp_prime_random() which requires a callback to make truly random primes of a given nature
(idea from chat with Niels Ferguson at Crypto'03) (idea from chat with Niels Ferguson at Crypto'03)

View File

@ -138,15 +138,16 @@ int main(void)
/* test mp_div_3 */ /* test mp_div_3 */
#if 0 #if 0
mp_set(&d, 3);
for (cnt = 0; cnt < 1000000; ) { for (cnt = 0; cnt < 1000000; ) {
mp_digit r1, r2; mp_digit r1, r2;
if (!(++cnt & 127)) printf("%9d\r", cnt); if (!(++cnt & 127)) printf("%9d\r", cnt);
mp_rand(&a, abs(rand()) % 128 + 1); mp_rand(&a, abs(rand()) % 128 + 1);
mp_div_d(&a, 3, &b, &r1); mp_div(&a, &d, &b, &e);
mp_div_3(&a, &c, &r2); mp_div_3(&a, &c, &r2);
if (mp_cmp(&b, &c) || r1 != r2) { if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
printf("\n\nmp_div_3 => Failure\n"); printf("\n\nmp_div_3 => Failure\n");
} }
} }

View File

@ -229,8 +229,8 @@ pprime (int k, int li, mp_int * p, mp_int * q)
/* now loop making the single digit */ /* now loop making the single digit */
while (mp_count_bits (&a) < k) { while (mp_count_bits (&a) < k) {
printf ("prime has %4d bits left\r", k - mp_count_bits (&a)); fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a));
fflush (stdout); fflush (stderr);
top: top:
mp_set (&b, prime_digit ()); mp_set (&b, prime_digit ());
@ -322,7 +322,6 @@ pprime (int k, int li, mp_int * p, mp_int * q)
if (ii == li) if (ii == li)
goto top; goto top;
/*
{ {
char buf[4096]; char buf[4096];
@ -331,10 +330,9 @@ pprime (int k, int li, mp_int * p, mp_int * q)
mp_toradix(&a, buf, 10); mp_toradix(&a, buf, 10);
printf("A == \n%s\n\n", buf); printf("A == \n%s\n\n", buf);
mp_toradix(&b, buf, 10); mp_toradix(&b, buf, 10);
printf("B == \n%s\n", buf); printf("B == \n%s\n\nG == %d\n", buf, bases[ii]);
printf("----------------------------------------------------------------\n"); printf("----------------------------------------------------------------\n");
} }
*/
/* a = n */ /* a = n */
mp_copy (&n, &a); mp_copy (&n, &a);

414
etc/prime.1024 Normal file
View File

@ -0,0 +1,414 @@
Enter # of bits:
Enter number of bases to try (1 to 8):
Certificate of primality for:
36360080703173363
A ==
89963569
B ==
202082249
G == 2
----------------------------------------------------------------
Certificate of primality for:
4851595597739856136987139
A ==
36360080703173363
B ==
66715963
G == 2
----------------------------------------------------------------
Certificate of primality for:
19550639734462621430325731591027
A ==
4851595597739856136987139
B ==
2014867
G == 2
----------------------------------------------------------------
Certificate of primality for:
10409036141344317165691858509923818734539
A ==
19550639734462621430325731591027
B ==
266207047
G == 2
----------------------------------------------------------------
Certificate of primality for:
1049829549988285012736475602118094726647504414203
A ==
10409036141344317165691858509923818734539
B ==
50428759
G == 2
----------------------------------------------------------------
Certificate of primality for:
77194737385528288387712399596835459931920358844586615003
A ==
1049829549988285012736475602118094726647504414203
B ==
36765367
G == 2
----------------------------------------------------------------
Certificate of primality for:
35663756695365208574443215955488689578374232732893628896541201763
A ==
77194737385528288387712399596835459931920358844586615003
B ==
230998627
G == 2
----------------------------------------------------------------
Certificate of primality for:
16711831463502165169495622246023119698415848120292671294127567620396469803
A ==
35663756695365208574443215955488689578374232732893628896541201763
B ==
234297127
G == 2
----------------------------------------------------------------
Certificate of primality for:
6163534781560285962890718925972249753147470953579266394395432475622345597103528739
A ==
16711831463502165169495622246023119698415848120292671294127567620396469803
B ==
184406323
G == 2
----------------------------------------------------------------
Certificate of primality for:
814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787
A ==
6163534781560285962890718925972249753147470953579266394395432475622345597103528739
B ==
66054487
G == 2
----------------------------------------------------------------
Certificate of primality for:
176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187
A ==
814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787
B ==
108362239
G == 2
----------------------------------------------------------------
Certificate of primality for:
44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419
A ==
176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187
B ==
127286707
G == 2
----------------------------------------------------------------
Certificate of primality for:
20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059
A ==
44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419
B ==
229284691
G == 2
----------------------------------------------------------------
Certificate of primality for:
6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979
A ==
20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059
B ==
152800771
G == 2
----------------------------------------------------------------
Certificate of primality for:
3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123
A ==
6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979
B ==
246595759
G == 2
----------------------------------------------------------------
Certificate of primality for:
26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499
A ==
3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123
B ==
4252063
G == 2
----------------------------------------------------------------
Certificate of primality for:
11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163
A ==
26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499
B ==
210605419
G == 2
----------------------------------------------------------------
Certificate of primality for:
1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187
A ==
11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163
B ==
74170111
G == 2
----------------------------------------------------------------
Certificate of primality for:
857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363
A ==
1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187
B ==
260016763
G == 2
----------------------------------------------------------------
Certificate of primality for:
175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283
A ==
857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363
B ==
102563707
G == 2
----------------------------------------------------------------
Certificate of primality for:
48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283
A ==
175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283
B ==
137747527
G == 2
----------------------------------------------------------------
Certificate of primality for:
13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403
A ==
48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283
B ==
135672847
G == 2
----------------------------------------------------------------
Certificate of primality for:
6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123
A ==
13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403
B ==
241523587
G == 2
----------------------------------------------------------------
Certificate of primality for:
3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083
A ==
6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123
B ==
248388667
G == 2
----------------------------------------------------------------
Certificate of primality for:
390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067
A ==
3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083
B ==
61849651
G == 2
----------------------------------------------------------------
Certificate of primality for:
48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739
A ==
390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067
B ==
62201707
G == 2
----------------------------------------------------------------
Certificate of primality for:
25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419
A ==
48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739
B ==
264832231
G == 2
----------------------------------------------------------------
Certificate of primality for:
2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387
A ==
25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419
B ==
54494047
G == 2
----------------------------------------------------------------
Certificate of primality for:
738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547
A ==
2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387
B ==
131594179
G == 2
----------------------------------------------------------------
Certificate of primality for:
392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683
A ==
738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547
B ==
266107603
G == 2
----------------------------------------------------------------
Certificate of primality for:
168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627
A ==
392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683
B ==
214408111
G == 2
----------------------------------------------------------------
Certificate of primality for:
14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643
A ==
168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627
B ==
44122723
G == 2
----------------------------------------------------------------
Certificate of primality for:
1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019
A ==
14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643
B ==
40808563
G == 2
----------------------------------------------------------------
Certificate of primality for:
186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843
A ==
1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019
B ==
77035759
G == 2
----------------------------------------------------------------
Certificate of primality for:
83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683
A ==
186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843
B ==
222383587
G == 2
----------------------------------------------------------------
Certificate of primality for:
3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443
A ==
83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683
B ==
23407687
G == 2
----------------------------------------------------------------
Certificate of primality for:
1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723
A ==
3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443
B ==
213701827
G == 2
----------------------------------------------------------------
Took 33057 ticks, 1048 bits
P == 1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723
Q == 3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443

205
etc/prime.512 Normal file
View File

@ -0,0 +1,205 @@
Enter # of bits:
Enter number of bases to try (1 to 8):
Certificate of primality for:
85933926807634727
A ==
253758023
B ==
169322581
G == 5
----------------------------------------------------------------
Certificate of primality for:
23930198825086241462113799
A ==
85933926807634727
B ==
139236037
G == 11
----------------------------------------------------------------
Certificate of primality for:
6401844647261612602378676572510019
A ==
23930198825086241462113799
B ==
133760791
G == 2
----------------------------------------------------------------
Certificate of primality for:
269731366027728777712034888684015329354259
A ==
6401844647261612602378676572510019
B ==
21066691
G == 2
----------------------------------------------------------------
Certificate of primality for:
37942338209025571690075025099189467992329684223707
A ==
269731366027728777712034888684015329354259
B ==
70333567
G == 2
----------------------------------------------------------------
Certificate of primality for:
15306904714258982484473490774101705363308327436988160248323
A ==
37942338209025571690075025099189467992329684223707
B ==
201712723
G == 2
----------------------------------------------------------------
Certificate of primality for:
1616744757018513392810355191503853040357155275733333124624513530099
A ==
15306904714258982484473490774101705363308327436988160248323
B ==
52810963
G == 2
----------------------------------------------------------------
Certificate of primality for:
464222094814208047161771036072622485188658077940154689939306386289983787983
A ==
1616744757018513392810355191503853040357155275733333124624513530099
B ==
143566909
G == 5
----------------------------------------------------------------
Certificate of primality for:
187429931674053784626487560729643601208757374994177258429930699354770049369025096447
A ==
464222094814208047161771036072622485188658077940154689939306386289983787983
B ==
201875281
G == 5
----------------------------------------------------------------
Certificate of primality for:
100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563
A ==
187429931674053784626487560729643601208757374994177258429930699354770049369025096447
B ==
268311523
G == 2
----------------------------------------------------------------
Certificate of primality for:
1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163
A ==
100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563
B ==
5834287
G == 2
----------------------------------------------------------------
Certificate of primality for:
191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623
A ==
1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163
B ==
81567097
G == 5
----------------------------------------------------------------
Certificate of primality for:
57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519
A ==
191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623
B ==
151095433
G == 7
----------------------------------------------------------------
Certificate of primality for:
13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803
A ==
57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519
B ==
119178679
G == 2
----------------------------------------------------------------
Certificate of primality for:
7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979
A ==
13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803
B ==
256552363
G == 2
----------------------------------------------------------------
Certificate of primality for:
1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463
A ==
7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979
B ==
86720989
G == 5
----------------------------------------------------------------
Certificate of primality for:
446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763
A ==
1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463
B ==
182015287
G == 2
----------------------------------------------------------------
Certificate of primality for:
5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243
A ==
446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763
B ==
5920567
G == 2
----------------------------------------------------------------
Took 3454 ticks, 521 bits
P == 5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243
Q == 446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763

View File

@ -1,12 +1,18 @@
#Makefile for GCC #Makefile for GCC
# #
#Tom St Denis #Tom St Denis
CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops CFLAGS += -I./ -Wall -W -Wshadow
#for speed
CFLAGS += -O3 -funroll-loops
#for size
#CFLAGS += -Os
#x86 optimizations [should be valid for any GCC install though] #x86 optimizations [should be valid for any GCC install though]
CFLAGS += -fomit-frame-pointer CFLAGS += -fomit-frame-pointer
VERSION=0.28 VERSION=0.29
default: libtommath.a default: libtommath.a
@ -44,7 +50,7 @@ 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_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_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_error.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 bn_mp_prime_random.o bn_prime_sizes_tab.o bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_prime_random.o bn_prime_sizes_tab.o bn_mp_exteuclid.o
libtommath.a: $(OBJECTS) libtommath.a: $(OBJECTS)
$(AR) $(ARFLAGS) libtommath.a $(OBJECTS) $(AR) $(ARFLAGS) libtommath.a $(OBJECTS)

View File

@ -29,7 +29,7 @@ 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_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_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_error.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 bn_mp_prime_random.obj bn_prime_sizes_tab.obj bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_prime_random.obj bn_prime_sizes_tab.obj bn_mp_exteuclid.obj
TARGET = libtommath.lib TARGET = libtommath.lib

View File

@ -34,7 +34,7 @@ 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_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_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_error.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 bn_mp_prime_random.o bn_prime_sizes_tab.o bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_prime_random.o bn_prime_sizes_tab.o bn_mp_exteuclid.o
# make a Windows DLL via Cygwin # make a Windows DLL via Cygwin
windll: $(OBJECTS) windll: $(OBJECTS)

View File

@ -28,7 +28,7 @@ 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_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_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_error.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 bn_mp_prime_random.obj bn_prime_sizes_tab.obj bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_prime_random.obj bn_prime_sizes_tab.obj bn_mp_exteuclid.obj
library: $(OBJECTS) library: $(OBJECTS)
lib /out:tommath.lib $(OBJECTS) lib /out:tommath.lib $(OBJECTS)

Binary file not shown.

View File

@ -1902,7 +1902,7 @@ mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
/* now subtract 3 * [w/3] from w, to get the remainder */ /* now subtract 3 * [w/3] from w, to get the remainder */
w -= (t << ((mp_word)1)) + t; w -= t+t+t;
/* fixup the remainder as required since /* fixup the remainder as required since
* the optimization is not exact. * the optimization is not exact.
@ -1966,8 +1966,7 @@ static int s_is_power_of_two(mp_digit b, int *p)
} }
/* single digit division (based on routine from MPI) */ /* single digit division (based on routine from MPI) */
int int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
{ {
mp_int q; mp_int q;
mp_word w; mp_word w;
@ -2665,6 +2664,79 @@ __M:
/* End: bn_mp_exptmod_fast.c */ /* End: bn_mp_exptmod_fast.c */
/* Start: bn_mp_exteuclid.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 <tommath.h>
/* Extended euclidean algorithm of (a, b) produces
a*u1 + b*u2 = u3
*/
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
int err;
if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
return err;
}
/* initialize, (u1,u2,u3) = (1,0,a) */
mp_set(&u1, 1);
if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
/* initialize, (v1,v2,v3) = (0,1,b) */
mp_set(&v2, 1);
if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
/* loop while v3 != 0 */
while (mp_iszero(&v3) == MP_NO) {
/* q = u3/v3 */
if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
/* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
/* (u1,u2,u3) = (v1,v2,v3) */
if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
/* (v1,v2,v3) = (t1,t2,t3) */
if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
}
/* copy result out */
if (U1 != NULL) { mp_exch(U1, &u1); }
if (U2 != NULL) { mp_exch(U2, &u2); }
if (U3 != NULL) { mp_exch(U3, &u3); }
err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
return err;
}
/* End: bn_mp_exteuclid.c */
/* Start: bn_mp_fread.c */ /* Start: bn_mp_fread.c */
/* LibTomMath, multiple-precision integer library -- Tom St Denis /* LibTomMath, multiple-precision integer library -- Tom St Denis
* *
@ -2752,9 +2824,8 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream)
char *buf; char *buf;
int err, len, x; int err, len, x;
len = mp_radix_size(a, radix); if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
if (len == 0) { return err;
return MP_VAL;
} }
buf = XMALLOC (len); buf = XMALLOC (len);
@ -4201,7 +4272,6 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c)
} else { } else {
res = s_mp_mul (a, b, c); res = s_mp_mul (a, b, c);
} }
} }
c->sign = neg; c->sign = neg;
return res; return res;
@ -5251,26 +5321,28 @@ error:
#include <tommath.h> #include <tommath.h>
/* returns size of ASCII reprensentation */ /* returns size of ASCII reprensentation */
int int mp_radix_size (mp_int * a, int radix, int *size)
mp_radix_size (mp_int * a, int radix)
{ {
int res, digs; int res, digs;
mp_int t; mp_int t;
mp_digit d; mp_digit d;
*size = 0;
/* special case for binary */ /* special case for binary */
if (radix == 2) { if (radix == 2) {
return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
return MP_OKAY;
} }
/* make sure the radix is in range */ /* make sure the radix is in range */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return 0; return MP_VAL;
} }
/* init a copy of the input */ /* init a copy of the input */
if ((res = mp_init_copy (&t, a)) != MP_OKAY) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return 0; return res;
} }
/* digs is the digit count */ /* digs is the digit count */
@ -5293,7 +5365,8 @@ mp_radix_size (mp_int * a, int radix)
mp_clear (&t); mp_clear (&t);
/* return digs + 1, the 1 is for the NULL byte that would be required. */ /* return digs + 1, the 1 is for the NULL byte that would be required. */
return digs + 1; *size = digs + 1;
return MP_OKAY;
} }
@ -5392,8 +5465,7 @@ mp_rand (mp_int * a, int digits)
#include <tommath.h> #include <tommath.h>
/* read a string [ASCII] in a given radix */ /* read a string [ASCII] in a given radix */
int int mp_read_radix (mp_int * a, char *str, int radix)
mp_read_radix (mp_int * a, char *str, int radix)
{ {
int y, res, neg; int y, res, neg;
char ch; char ch;
@ -5989,7 +6061,7 @@ int mp_set_int (mp_int * a, unsigned long b)
int mp_shrink (mp_int * a) int mp_shrink (mp_int * a)
{ {
mp_digit *tmp; mp_digit *tmp;
if (a->alloc != a->used) { if (a->alloc != a->used && a->used > 0) {
if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
return MP_MEM; return MP_MEM;
} }
@ -6019,8 +6091,7 @@ int mp_shrink (mp_int * a)
#include <tommath.h> #include <tommath.h>
/* get the size for an signed equivalent */ /* get the size for an signed equivalent */
int int mp_signed_bin_size (mp_int * a)
mp_signed_bin_size (mp_int * a)
{ {
return 1 + mp_unsigned_bin_size (a); return 1 + mp_unsigned_bin_size (a);
} }
@ -6049,6 +6120,7 @@ int
mp_sqr (mp_int * a, mp_int * b) mp_sqr (mp_int * a, mp_int * b)
{ {
int res; int res;
/* use Toom-Cook? */ /* use Toom-Cook? */
if (a->used >= TOOM_SQR_CUTOFF) { if (a->used >= TOOM_SQR_CUTOFF) {
res = mp_toom_sqr(a, b); res = mp_toom_sqr(a, b);
@ -6892,8 +6964,7 @@ ERR:
#include <tommath.h> #include <tommath.h>
/* stores a bignum as a ASCII string in a given radix (2..64) */ /* stores a bignum as a ASCII string in a given radix (2..64) */
int int mp_toradix (mp_int * a, char *str, int radix)
mp_toradix (mp_int * a, char *str, int radix)
{ {
int res, digs; int res, digs;
mp_int t; mp_int t;
@ -7086,25 +7157,7 @@ static const struct {
{ 1408, 3 }, { 1408, 3 },
{ 1536, 3 }, { 1536, 3 },
{ 1664, 3 }, { 1664, 3 },
{ 1792, 2 }, { 1792, 2 } };
{ 1920, 2 },
{ 2048, 2 },
{ 2176, 2 },
{ 2304, 2 },
{ 2432, 2 },
{ 2560, 2 },
{ 2688, 2 },
{ 2816, 2 },
{ 2944, 2 },
{ 3072, 2 },
{ 3200, 2 },
{ 3328, 2 },
{ 3456, 2 },
{ 3584, 2 },
{ 3712, 2 },
{ 3840, 1 },
{ 3968, 1 },
{ 4096, 1 } };
/* returns # of RM trials required for a given bit size */ /* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size) int mp_prime_rabin_miller_trials(int size)
@ -7351,8 +7404,7 @@ s_mp_add (mp_int * a, mp_int * b, mp_int * c)
#define TAB_SIZE 256 #define TAB_SIZE 256
#endif #endif
int int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{ {
mp_int M[TAB_SIZE], res, mu; mp_int M[TAB_SIZE], res, mu;
mp_digit buf; mp_digit buf;
@ -7516,10 +7568,10 @@ s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
/* then multiply */ /* then multiply */
if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
goto __MU; goto __RES;
} }
if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
goto __MU; goto __RES;
} }
/* empty window and reset */ /* empty window and reset */

View File

@ -338,6 +338,9 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
/* c = (a, b) */ /* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c); int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
/* produces value such that U1*a + U2*b = U3 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
/* c = [a, b] or (a*b)/(a, b) */ /* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c); int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
@ -466,7 +469,7 @@ int mp_to_signed_bin(mp_int *a, unsigned char *b);
int mp_read_radix(mp_int *a, char *str, int radix); int mp_read_radix(mp_int *a, char *str, int radix);
int mp_toradix(mp_int *a, char *str, int radix); int mp_toradix(mp_int *a, char *str, int radix);
int mp_radix_size(mp_int *a, int radix); int mp_radix_size(mp_int *a, int radix, int *size);
int mp_fread(mp_int *a, int radix, FILE *stream); int mp_fread(mp_int *a, int radix, FILE *stream);
int mp_fwrite(mp_int *a, int radix, FILE *stream); int mp_fwrite(mp_int *a, int radix, FILE *stream);

View File

@ -1,7 +1,7 @@
\BOOKMARK [0][-]{chapter.1}{Introduction}{} \BOOKMARK [0][-]{chapter.1}{Introduction}{}
\BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1} \BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1}
\BOOKMARK [2][-]{subsection.1.1.1}{The Need for Multiple Precision Arithmetic}{section.1.1} \BOOKMARK [2][-]{subsection.1.1.1}{What is Multiple Precision Arithmetic?}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.2}{What is Multiple Precision Arithmetic?}{section.1.1} \BOOKMARK [2][-]{subsection.1.1.2}{The Need for Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1} \BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1} \BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1}
\BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1} \BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1}
@ -11,129 +11,129 @@
\BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3} \BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3} \BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3}
\BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1} \BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1}
\BOOKMARK [0][-]{chapter.2}{Introduction to LibTomMath}{} \BOOKMARK [1][-]{section.1.5}{Introduction to LibTomMath}{chapter.1}
\BOOKMARK [1][-]{section.2.1}{What is LibTomMath?}{chapter.2} \BOOKMARK [2][-]{subsection.1.5.1}{What is LibTomMath?}{section.1.5}
\BOOKMARK [1][-]{section.2.2}{Goals of LibTomMath}{chapter.2} \BOOKMARK [2][-]{subsection.1.5.2}{Goals of LibTomMath}{section.1.5}
\BOOKMARK [1][-]{section.2.3}{Choice of LibTomMath}{chapter.2} \BOOKMARK [1][-]{section.1.6}{Choice of LibTomMath}{chapter.1}
\BOOKMARK [2][-]{subsection.2.3.1}{Code Base}{section.2.3} \BOOKMARK [2][-]{subsection.1.6.1}{Code Base}{section.1.6}
\BOOKMARK [2][-]{subsection.2.3.2}{API Simplicity}{section.2.3} \BOOKMARK [2][-]{subsection.1.6.2}{API Simplicity}{section.1.6}
\BOOKMARK [2][-]{subsection.2.3.3}{Optimizations}{section.2.3} \BOOKMARK [2][-]{subsection.1.6.3}{Optimizations}{section.1.6}
\BOOKMARK [2][-]{subsection.2.3.4}{Portability and Stability}{section.2.3} \BOOKMARK [2][-]{subsection.1.6.4}{Portability and Stability}{section.1.6}
\BOOKMARK [2][-]{subsection.2.3.5}{Choice}{section.2.3} \BOOKMARK [2][-]{subsection.1.6.5}{Choice}{section.1.6}
\BOOKMARK [0][-]{chapter.3}{Getting Started}{} \BOOKMARK [0][-]{chapter.2}{Getting Started}{}
\BOOKMARK [1][-]{section.3.1}{Library Basics}{chapter.3} \BOOKMARK [1][-]{section.2.1}{Library Basics}{chapter.2}
\BOOKMARK [1][-]{section.3.2}{What is a Multiple Precision Integer?}{chapter.3} \BOOKMARK [1][-]{section.2.2}{What is a Multiple Precision Integer?}{chapter.2}
\BOOKMARK [2][-]{subsection.3.2.1}{The mp\137int Structure}{section.3.2} \BOOKMARK [2][-]{subsection.2.2.1}{The mp\137int Structure}{section.2.2}
\BOOKMARK [1][-]{section.3.3}{Argument Passing}{chapter.3} \BOOKMARK [1][-]{section.2.3}{Argument Passing}{chapter.2}
\BOOKMARK [1][-]{section.3.4}{Return Values}{chapter.3} \BOOKMARK [1][-]{section.2.4}{Return Values}{chapter.2}
\BOOKMARK [1][-]{section.3.5}{Initialization and Clearing}{chapter.3} \BOOKMARK [1][-]{section.2.5}{Initialization and Clearing}{chapter.2}
\BOOKMARK [2][-]{subsection.3.5.1}{Initializing an mp\137int}{section.3.5} \BOOKMARK [2][-]{subsection.2.5.1}{Initializing an mp\137int}{section.2.5}
\BOOKMARK [2][-]{subsection.3.5.2}{Clearing an mp\137int}{section.3.5} \BOOKMARK [2][-]{subsection.2.5.2}{Clearing an mp\137int}{section.2.5}
\BOOKMARK [1][-]{section.3.6}{Maintenance Algorithms}{chapter.3} \BOOKMARK [1][-]{section.2.6}{Maintenance Algorithms}{chapter.2}
\BOOKMARK [2][-]{subsection.3.6.1}{Augmenting an mp\137int's Precision}{section.3.6} \BOOKMARK [2][-]{subsection.2.6.1}{Augmenting an mp\137int's Precision}{section.2.6}
\BOOKMARK [2][-]{subsection.3.6.2}{Initializing Variable Precision mp\137ints}{section.3.6} \BOOKMARK [2][-]{subsection.2.6.2}{Initializing Variable Precision mp\137ints}{section.2.6}
\BOOKMARK [2][-]{subsection.3.6.3}{Multiple Integer Initializations and Clearings}{section.3.6} \BOOKMARK [2][-]{subsection.2.6.3}{Multiple Integer Initializations and Clearings}{section.2.6}
\BOOKMARK [2][-]{subsection.3.6.4}{Clamping Excess Digits}{section.3.6} \BOOKMARK [2][-]{subsection.2.6.4}{Clamping Excess Digits}{section.2.6}
\BOOKMARK [0][-]{chapter.4}{Basic Operations}{} \BOOKMARK [0][-]{chapter.3}{Basic Operations}{}
\BOOKMARK [1][-]{section.3.1}{Introduction}{chapter.3}
\BOOKMARK [1][-]{section.3.2}{Assigning Values to mp\137int Structures}{chapter.3}
\BOOKMARK [2][-]{subsection.3.2.1}{Copying an mp\137int}{section.3.2}
\BOOKMARK [2][-]{subsection.3.2.2}{Creating a Clone}{section.3.2}
\BOOKMARK [1][-]{section.3.3}{Zeroing an Integer}{chapter.3}
\BOOKMARK [1][-]{section.3.4}{Sign Manipulation}{chapter.3}
\BOOKMARK [2][-]{subsection.3.4.1}{Absolute Value}{section.3.4}
\BOOKMARK [2][-]{subsection.3.4.2}{Integer Negation}{section.3.4}
\BOOKMARK [1][-]{section.3.5}{Small Constants}{chapter.3}
\BOOKMARK [2][-]{subsection.3.5.1}{Setting Small Constants}{section.3.5}
\BOOKMARK [2][-]{subsection.3.5.2}{Setting Large Constants}{section.3.5}
\BOOKMARK [1][-]{section.3.6}{Comparisons}{chapter.3}
\BOOKMARK [2][-]{subsection.3.6.1}{Unsigned Comparisions}{section.3.6}
\BOOKMARK [2][-]{subsection.3.6.2}{Signed Comparisons}{section.3.6}
\BOOKMARK [0][-]{chapter.4}{Basic Arithmetic}{}
\BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4} \BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4}
\BOOKMARK [1][-]{section.4.2}{Assigning Values to mp\137int Structures}{chapter.4} \BOOKMARK [1][-]{section.4.2}{Addition and Subtraction}{chapter.4}
\BOOKMARK [2][-]{subsection.4.2.1}{Copying an mp\137int}{section.4.2} \BOOKMARK [2][-]{subsection.4.2.1}{Low Level Addition}{section.4.2}
\BOOKMARK [2][-]{subsection.4.2.2}{Creating a Clone}{section.4.2} \BOOKMARK [2][-]{subsection.4.2.2}{Low Level Subtraction}{section.4.2}
\BOOKMARK [1][-]{section.4.3}{Zeroing an Integer}{chapter.4} \BOOKMARK [2][-]{subsection.4.2.3}{High Level Addition}{section.4.2}
\BOOKMARK [1][-]{section.4.4}{Sign Manipulation}{chapter.4} \BOOKMARK [2][-]{subsection.4.2.4}{High Level Subtraction}{section.4.2}
\BOOKMARK [2][-]{subsection.4.4.1}{Absolute Value}{section.4.4} \BOOKMARK [1][-]{section.4.3}{Bit and Digit Shifting}{chapter.4}
\BOOKMARK [2][-]{subsection.4.4.2}{Integer Negation}{section.4.4} \BOOKMARK [2][-]{subsection.4.3.1}{Multiplication by Two}{section.4.3}
\BOOKMARK [1][-]{section.4.5}{Small Constants}{chapter.4} \BOOKMARK [2][-]{subsection.4.3.2}{Division by Two}{section.4.3}
\BOOKMARK [2][-]{subsection.4.5.1}{Setting Small Constants}{section.4.5} \BOOKMARK [1][-]{section.4.4}{Polynomial Basis Operations}{chapter.4}
\BOOKMARK [2][-]{subsection.4.5.2}{Setting Large Constants}{section.4.5} \BOOKMARK [2][-]{subsection.4.4.1}{Multiplication by x}{section.4.4}
\BOOKMARK [1][-]{section.4.6}{Comparisons}{chapter.4} \BOOKMARK [2][-]{subsection.4.4.2}{Division by x}{section.4.4}
\BOOKMARK [2][-]{subsection.4.6.1}{Unsigned Comparisions}{section.4.6} \BOOKMARK [1][-]{section.4.5}{Powers of Two}{chapter.4}
\BOOKMARK [2][-]{subsection.4.6.2}{Signed Comparisons}{section.4.6} \BOOKMARK [2][-]{subsection.4.5.1}{Multiplication by Power of Two}{section.4.5}
\BOOKMARK [0][-]{chapter.5}{Basic Arithmetic}{} \BOOKMARK [2][-]{subsection.4.5.2}{Division by Power of Two}{section.4.5}
\BOOKMARK [1][-]{section.5.1}{Introduction}{chapter.5} \BOOKMARK [2][-]{subsection.4.5.3}{Remainder of Division by Power of Two}{section.4.5}
\BOOKMARK [1][-]{section.5.2}{Addition and Subtraction}{chapter.5} \BOOKMARK [0][-]{chapter.5}{Multiplication and Squaring}{}
\BOOKMARK [2][-]{subsection.5.2.1}{Low Level Addition}{section.5.2} \BOOKMARK [1][-]{section.5.1}{The Multipliers}{chapter.5}
\BOOKMARK [2][-]{subsection.5.2.2}{Low Level Subtraction}{section.5.2} \BOOKMARK [1][-]{section.5.2}{Multiplication}{chapter.5}
\BOOKMARK [2][-]{subsection.5.2.3}{High Level Addition}{section.5.2} \BOOKMARK [2][-]{subsection.5.2.1}{The Baseline Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.4}{High Level Subtraction}{section.5.2} \BOOKMARK [2][-]{subsection.5.2.2}{Faster Multiplication by the ``Comba'' Method}{section.5.2}
\BOOKMARK [1][-]{section.5.3}{Bit and Digit Shifting}{chapter.5} \BOOKMARK [2][-]{subsection.5.2.3}{Polynomial Basis Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.3.1}{Multiplication by Two}{section.5.3} \BOOKMARK [2][-]{subsection.5.2.4}{Karatsuba Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.3.2}{Division by Two}{section.5.3} \BOOKMARK [2][-]{subsection.5.2.5}{Toom-Cook 3-Way Multiplication}{section.5.2}
\BOOKMARK [1][-]{section.5.4}{Polynomial Basis Operations}{chapter.5} \BOOKMARK [2][-]{subsection.5.2.6}{Signed Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.4.1}{Multiplication by x}{section.5.4} \BOOKMARK [1][-]{section.5.3}{Squaring}{chapter.5}
\BOOKMARK [2][-]{subsection.5.4.2}{Division by x}{section.5.4} \BOOKMARK [2][-]{subsection.5.3.1}{The Baseline Squaring Algorithm}{section.5.3}
\BOOKMARK [1][-]{section.5.5}{Powers of Two}{chapter.5} \BOOKMARK [2][-]{subsection.5.3.2}{Faster Squaring by the ``Comba'' Method}{section.5.3}
\BOOKMARK [2][-]{subsection.5.5.1}{Multiplication by Power of Two}{section.5.5} \BOOKMARK [2][-]{subsection.5.3.3}{Polynomial Basis Squaring}{section.5.3}
\BOOKMARK [2][-]{subsection.5.5.2}{Division by Power of Two}{section.5.5} \BOOKMARK [2][-]{subsection.5.3.4}{Karatsuba Squaring}{section.5.3}
\BOOKMARK [2][-]{subsection.5.5.3}{Remainder of Division by Power of Two}{section.5.5} \BOOKMARK [2][-]{subsection.5.3.5}{Toom-Cook Squaring}{section.5.3}
\BOOKMARK [0][-]{chapter.6}{Multiplication and Squaring}{} \BOOKMARK [2][-]{subsection.5.3.6}{High Level Squaring}{section.5.3}
\BOOKMARK [1][-]{section.6.1}{The Multipliers}{chapter.6} \BOOKMARK [0][-]{chapter.6}{Modular Reduction}{}
\BOOKMARK [1][-]{section.6.2}{Multiplication}{chapter.6} \BOOKMARK [1][-]{section.6.1}{Basics of Modular Reduction}{chapter.6}
\BOOKMARK [2][-]{subsection.6.2.1}{The Baseline Multiplication}{section.6.2} \BOOKMARK [1][-]{section.6.2}{The Barrett Reduction}{chapter.6}
\BOOKMARK [2][-]{subsection.6.2.2}{Faster Multiplication by the ``Comba'' Method}{section.6.2} \BOOKMARK [2][-]{subsection.6.2.1}{Fixed Point Arithmetic}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.3}{Polynomial Basis Multiplication}{section.6.2} \BOOKMARK [2][-]{subsection.6.2.2}{Choosing a Radix Point}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.4}{Karatsuba Multiplication}{section.6.2} \BOOKMARK [2][-]{subsection.6.2.3}{Trimming the Quotient}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.5}{Toom-Cook 3-Way Multiplication}{section.6.2} \BOOKMARK [2][-]{subsection.6.2.4}{Trimming the Residue}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.6}{Signed Multiplication}{section.6.2} \BOOKMARK [2][-]{subsection.6.2.5}{The Barrett Algorithm}{section.6.2}
\BOOKMARK [1][-]{section.6.3}{Squaring}{chapter.6} \BOOKMARK [2][-]{subsection.6.2.6}{The Barrett Setup Algorithm}{section.6.2}
\BOOKMARK [2][-]{subsection.6.3.1}{The Baseline Squaring Algorithm}{section.6.3} \BOOKMARK [1][-]{section.6.3}{The Montgomery Reduction}{chapter.6}
\BOOKMARK [2][-]{subsection.6.3.2}{Faster Squaring by the ``Comba'' Method}{section.6.3} \BOOKMARK [2][-]{subsection.6.3.1}{Digit Based Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.3}{Polynomial Basis Squaring}{section.6.3} \BOOKMARK [2][-]{subsection.6.3.2}{Baseline Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.4}{Karatsuba Squaring}{section.6.3} \BOOKMARK [2][-]{subsection.6.3.3}{Faster ``Comba'' Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.5}{Toom-Cook Squaring}{section.6.3} \BOOKMARK [2][-]{subsection.6.3.4}{Montgomery Setup}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.6}{High Level Squaring}{section.6.3} \BOOKMARK [1][-]{section.6.4}{The Diminished Radix Algorithm}{chapter.6}
\BOOKMARK [0][-]{chapter.7}{Modular Reduction}{} \BOOKMARK [2][-]{subsection.6.4.1}{Choice of Moduli}{section.6.4}
\BOOKMARK [1][-]{section.7.1}{Basics of Modular Reduction}{chapter.7} \BOOKMARK [2][-]{subsection.6.4.2}{Choice of k}{section.6.4}
\BOOKMARK [1][-]{section.7.2}{The Barrett Reduction}{chapter.7} \BOOKMARK [2][-]{subsection.6.4.3}{Restricted Diminished Radix Reduction}{section.6.4}
\BOOKMARK [2][-]{subsection.7.2.1}{Fixed Point Arithmetic}{section.7.2} \BOOKMARK [2][-]{subsection.6.4.4}{Unrestricted Diminished Radix Reduction}{section.6.4}
\BOOKMARK [2][-]{subsection.7.2.2}{Choosing a Radix Point}{section.7.2} \BOOKMARK [1][-]{section.6.5}{Algorithm Comparison}{chapter.6}
\BOOKMARK [2][-]{subsection.7.2.3}{Trimming the Quotient}{section.7.2} \BOOKMARK [0][-]{chapter.7}{Exponentiation}{}
\BOOKMARK [2][-]{subsection.7.2.4}{Trimming the Residue}{section.7.2} \BOOKMARK [1][-]{section.7.1}{Exponentiation Basics}{chapter.7}
\BOOKMARK [2][-]{subsection.7.2.5}{The Barrett Algorithm}{section.7.2} \BOOKMARK [2][-]{subsection.7.1.1}{Single Digit Exponentiation}{section.7.1}
\BOOKMARK [2][-]{subsection.7.2.6}{The Barrett Setup Algorithm}{section.7.2} \BOOKMARK [1][-]{section.7.2}{k-ary Exponentiation}{chapter.7}
\BOOKMARK [1][-]{section.7.3}{The Montgomery Reduction}{chapter.7} \BOOKMARK [2][-]{subsection.7.2.1}{Optimal Values of k}{section.7.2}
\BOOKMARK [2][-]{subsection.7.3.1}{Digit Based Montgomery Reduction}{section.7.3} \BOOKMARK [2][-]{subsection.7.2.2}{Sliding-Window Exponentiation}{section.7.2}
\BOOKMARK [2][-]{subsection.7.3.2}{Baseline Montgomery Reduction}{section.7.3} \BOOKMARK [1][-]{section.7.3}{Modular Exponentiation}{chapter.7}
\BOOKMARK [2][-]{subsection.7.3.3}{Faster ``Comba'' Montgomery Reduction}{section.7.3} \BOOKMARK [2][-]{subsection.7.3.1}{Barrett Modular Exponentiation}{section.7.3}
\BOOKMARK [2][-]{subsection.7.3.4}{Montgomery Setup}{section.7.3} \BOOKMARK [1][-]{section.7.4}{Quick Power of Two}{chapter.7}
\BOOKMARK [1][-]{section.7.4}{The Diminished Radix Algorithm}{chapter.7} \BOOKMARK [0][-]{chapter.8}{Higher Level Algorithms}{}
\BOOKMARK [2][-]{subsection.7.4.1}{Choice of Moduli}{section.7.4} \BOOKMARK [1][-]{section.8.1}{Integer Division with Remainder}{chapter.8}
\BOOKMARK [2][-]{subsection.7.4.2}{Choice of k}{section.7.4} \BOOKMARK [2][-]{subsection.8.1.1}{Quotient Estimation}{section.8.1}
\BOOKMARK [2][-]{subsection.7.4.3}{Restricted Diminished Radix Reduction}{section.7.4} \BOOKMARK [2][-]{subsection.8.1.2}{Normalized Integers}{section.8.1}
\BOOKMARK [2][-]{subsection.7.4.4}{Unrestricted Diminished Radix Reduction}{section.7.4} \BOOKMARK [2][-]{subsection.8.1.3}{Radix- Division with Remainder}{section.8.1}
\BOOKMARK [1][-]{section.7.5}{Algorithm Comparison}{chapter.7} \BOOKMARK [1][-]{section.8.2}{Single Digit Helpers}{chapter.8}
\BOOKMARK [0][-]{chapter.8}{Exponentiation}{} \BOOKMARK [2][-]{subsection.8.2.1}{Single Digit Addition and Subtraction}{section.8.2}
\BOOKMARK [1][-]{section.8.1}{Exponentiation Basics}{chapter.8} \BOOKMARK [2][-]{subsection.8.2.2}{Single Digit Multiplication}{section.8.2}
\BOOKMARK [2][-]{subsection.8.1.1}{Single Digit Exponentiation}{section.8.1} \BOOKMARK [2][-]{subsection.8.2.3}{Single Digit Division}{section.8.2}
\BOOKMARK [1][-]{section.8.2}{k-ary Exponentiation}{chapter.8} \BOOKMARK [2][-]{subsection.8.2.4}{Single Digit Root Extraction}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.1}{Optimal Values of k}{section.8.2} \BOOKMARK [1][-]{section.8.3}{Random Number Generation}{chapter.8}
\BOOKMARK [2][-]{subsection.8.2.2}{Sliding-Window Exponentiation}{section.8.2} \BOOKMARK [1][-]{section.8.4}{Formatted Representations}{chapter.8}
\BOOKMARK [1][-]{section.8.3}{Modular Exponentiation}{chapter.8} \BOOKMARK [2][-]{subsection.8.4.1}{Reading Radix-n Input}{section.8.4}
\BOOKMARK [2][-]{subsection.8.3.1}{Barrett Modular Exponentiation}{section.8.3} \BOOKMARK [2][-]{subsection.8.4.2}{Generating Radix-n Output}{section.8.4}
\BOOKMARK [1][-]{section.8.4}{Quick Power of Two}{chapter.8} \BOOKMARK [0][-]{chapter.9}{Number Theoretic Algorithms}{}
\BOOKMARK [0][-]{chapter.9}{Higher Level Algorithms}{} \BOOKMARK [1][-]{section.9.1}{Greatest Common Divisor}{chapter.9}
\BOOKMARK [1][-]{section.9.1}{Integer Division with Remainder}{chapter.9} \BOOKMARK [2][-]{subsection.9.1.1}{Complete Greatest Common Divisor}{section.9.1}
\BOOKMARK [2][-]{subsection.9.1.1}{Quotient Estimation}{section.9.1} \BOOKMARK [1][-]{section.9.2}{Least Common Multiple}{chapter.9}
\BOOKMARK [2][-]{subsection.9.1.2}{Normalized Integers}{section.9.1} \BOOKMARK [1][-]{section.9.3}{Jacobi Symbol Computation}{chapter.9}
\BOOKMARK [2][-]{subsection.9.1.3}{Radix- Division with Remainder}{section.9.1} \BOOKMARK [2][-]{subsection.9.3.1}{Jacobi Symbol}{section.9.3}
\BOOKMARK [1][-]{section.9.2}{Single Digit Helpers}{chapter.9} \BOOKMARK [1][-]{section.9.4}{Modular Inverse}{chapter.9}
\BOOKMARK [2][-]{subsection.9.2.1}{Single Digit Addition and Subtraction}{section.9.2} \BOOKMARK [2][-]{subsection.9.4.1}{General Case}{section.9.4}
\BOOKMARK [2][-]{subsection.9.2.2}{Single Digit Multiplication}{section.9.2} \BOOKMARK [1][-]{section.9.5}{Primality Tests}{chapter.9}
\BOOKMARK [2][-]{subsection.9.2.3}{Single Digit Division}{section.9.2} \BOOKMARK [2][-]{subsection.9.5.1}{Trial Division}{section.9.5}
\BOOKMARK [2][-]{subsection.9.2.4}{Single Digit Root Extraction}{section.9.2} \BOOKMARK [2][-]{subsection.9.5.2}{The Fermat Test}{section.9.5}
\BOOKMARK [1][-]{section.9.3}{Random Number Generation}{chapter.9} \BOOKMARK [2][-]{subsection.9.5.3}{The Miller-Rabin Test}{section.9.5}
\BOOKMARK [1][-]{section.9.4}{Formatted Representations}{chapter.9}
\BOOKMARK [2][-]{subsection.9.4.1}{Reading Radix-n Input}{section.9.4}
\BOOKMARK [2][-]{subsection.9.4.2}{Generating Radix-n Output}{section.9.4}
\BOOKMARK [0][-]{chapter.10}{Number Theoretic Algorithms}{}
\BOOKMARK [1][-]{section.10.1}{Greatest Common Divisor}{chapter.10}
\BOOKMARK [2][-]{subsection.10.1.1}{Complete Greatest Common Divisor}{section.10.1}
\BOOKMARK [1][-]{section.10.2}{Least Common Multiple}{chapter.10}
\BOOKMARK [1][-]{section.10.3}{Jacobi Symbol Computation}{chapter.10}
\BOOKMARK [2][-]{subsection.10.3.1}{Jacobi Symbol}{section.10.3}
\BOOKMARK [1][-]{section.10.4}{Modular Inverse}{chapter.10}
\BOOKMARK [2][-]{subsection.10.4.1}{General Case}{section.10.4}
\BOOKMARK [1][-]{section.10.5}{Primality Tests}{chapter.10}
\BOOKMARK [2][-]{subsection.10.5.1}{Trial Division}{section.10.5}
\BOOKMARK [2][-]{subsection.10.5.2}{The Fermat Test}{section.10.5}
\BOOKMARK [2][-]{subsection.10.5.3}{The Miller-Rabin Test}{section.10.5}

24275
tommath.pdf

File diff suppressed because one or more lines are too long

View File

@ -201,12 +201,27 @@ Greg Rose, Sydney, Australia, June 2003.
\pagestyle{headings} \pagestyle{headings}
\chapter{Introduction} \chapter{Introduction}
\section{Multiple Precision Arithmetic} \section{Multiple Precision Arithmetic}
\subsection{What is Multiple Precision Arithmetic?}
When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can
reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with.
Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple
precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
of algorithms can be designed to accomodate them.
By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in
the decimal system with fixed precision $6 \cdot 7 = 2$.
Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
schools to manually add, subtract, multiply and divide.
\subsection{The Need for Multiple Precision Arithmetic} \subsection{The Need for Multiple Precision Arithmetic}
The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require
integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a
typical RSA modulus would be at greater than $10^{309}$. However, modern programming languages such as ISO C \ref{ISOC} and typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and
Java \ref{JAVA} only provide instrinsic support for integers which are relatively small and are single precision. Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.
\begin{figure}[!here] \begin{figure}[!here]
\begin{center} \begin{center}
@ -227,9 +242,9 @@ The largest data type guaranteed to be provided by the ISO C programming
language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they
see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is
insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be
trivially factored on the average desktop computer, rendering any protocol based on the algorithm insecure. Multiple trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer,
precision algorithms solve this very problem by extending the range of representable integers while using single precision rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by
data types. extending the range of representable integers while using single precision data types.
Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic
primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in
@ -246,27 +261,16 @@ floating point is meant to be implemented in hardware the precision of the manti
a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where
scientific applications must minimize the total output error over long calculations. scientific applications must minimize the total output error over long calculations.
\subsection{What is Multiple Precision Arithmetic?} Another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
At the heart of all multiple precision integer operations are the ``long-hand'' algorithms taught to children in grade In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.
school. For example, to multiply $1,234$ by $981$ the student is not taught to memorize the times table for
$1,234$. Instead, they are taught how to long-multiply one digit at a time. That is to multiply each column using
simple single digit multiplications, line up the partial results, and add the resulting products by column. The
representation that most are familiar with is known as decimal or more formally as radix-10. A radix-$n$ representation
simply means there are $n$ possible values per digit. For example, binary would be a radix-2 representation.
In essence computer based multiple precision arithmetic is very much the same. In most cases the same algorithms
which seem instinctive are the basis of computer based algorithms. The most notable difference is the usage
of a binary friendly radix, that is, to use a radix of the form $2^k$ where $k$ is typically the size of a computer
machine register\footnote{For example, with an x86 based processor $k$ could be $32$ while on an Alpha it would likely
be $64$.}.
\subsection{Benefits of Multiple Precision Arithmetic} \subsection{Benefits of Multiple Precision Arithmetic}
\index{precision} \index{precision}
The benefit of multiple precision representations over single or fixed precision representations is that The benefit of multiple precision representations over single or fixed precision representations is that
often no precision is lost while representing the result of an operation which requires excess precision. For example, no precision is lost while representing the result of an operation which requires excess precision. For example,
the product of two $n$-bit integers requires at least $2n$ bits of resolution to be precisely represented. the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple
A multiple precision algorithm would augment the precision of the destination to accomodate the result while a single precision algorithm would augment the precision of the destination to accomodate the result while a single precision system
precision system would truncate excess bits to maintain a fixed level of precision. would truncate excess bits to maintain a fixed level of precision.
It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic
curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum
@ -279,11 +283,12 @@ Multiple precision algorithms have the most overhead of any style of arithmetic.
overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the
inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input
without the designer's explicit forethought. without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to
be written and tested once.
\section{Purpose of This Text} \section{Purpose of This Text}
The purpose of this text is to instruct the reader regarding how to implement multiple precision algorithms. That is The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.
to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping''
elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC} elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC}
give considerably detailed explanations of the theoretical aspects of algorithms and often very little information give considerably detailed explanations of the theoretical aspects of algorithms and often very little information
regarding the practical implementation aspects. regarding the practical implementation aspects.
@ -309,6 +314,9 @@ The algorithms that are presented will always include at least one ``pseudo-code
by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same
algorithm in other programming languages as the reader sees fit. algorithm in other programming languages as the reader sees fit.
This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing
the reader how the algorithms fit together as well as where to start on various taskings.
\section{Discussion and Notation} \section{Discussion and Notation}
\subsection{Notation} \subsection{Notation}
A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1} ... x_1 x_0)_{ \beta }$ and represent A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1} ... x_1 x_0)_{ \beta }$ and represent
@ -368,41 +376,36 @@ The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an inte
itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when
the $/$ division symbol is used the intention is to perform an integer division with truncation. For example, the $/$ division symbol is used the intention is to perform an integer division with truncation. For example,
$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When a value is presented as a $5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a
fraction such as $5 \over 2$ a real value division is implied. fraction a real value division is implied, for example ${5 \over 2} = 2.5$.
The norm of a multiple precision integer, for example, $\vert \vert x \vert \vert$ will be used to represent the number of digits in the representation The norm of a multiple precision integer, for example, $\vert \vert x \vert \vert$ will be used to represent the number of digits in the representation
of the integer. For example, $\vert \vert 123 \vert \vert = 3$. of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.
\subsection{Work Effort} \subsection{Work Effort}
\index{big-O} \index{big-Oh}
To measure the efficiency of the specified algorithms, a modified big-O notation is used. In this system all To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all
single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}. single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.
That is a single precision addition, multiplication and division are assumed to take the same time to That is a single precision addition, multiplication and division are assumed to take the same time to
complete. While this is generally not true in practice, it will simplify the discussions considerably. complete. While this is generally not true in practice, it will simplify the discussions considerably.
Some algorithms have slight advantages over others which is why some constants will not be removed in Some algorithms have slight advantages over others which is why some constants will not be removed in
the notation. For example, a normal multiplication requires $O(n^2)$ work while a squaring requires the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a
$O({{n^2 + n}\over 2})$ work. In standard big-O notation these would both be said to be equivalent to $O(n^2)$. However, baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these
would both be said to be equivalent to $O(n^2)$. However,
in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a
result small constant factors in the work effort will make an observable difference in algorithm efficiency. result small constant factors in the work effort will make an observable difference in algorithm efficiency.
Throughout the discussions various ``work levels'' will be discussed. The term work level shall refer to All of the algorithms presented in this text have a polynomial time work level. That is, of the form
the complexity of an algorithm with respect to its time requirements. For example, $O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how
$O(1)$, $O(n)$, $O(n^2)$, ..., $O(n^k)$ are various possible work levels that will be of concern in this text. Any various optimizations will help pay off in the long run.
sequence of operations said to be at the $O(n^k)$ work level will often be nested $k-$deep within loops and are performed
$n^k$ times.
Operations which are deeply nested within algorithms will have a higher big-O rating and be the target of the most
optimizatons. For example, in integer multiplication, by moving the carry propagation from the innermost
$O(n^2)$ nesting to the $O(n)$ nesting level the algorithm becomes vastly more
efficient\footnote{This is known as Comba multiplication.}.
\section{Exercises} \section{Exercises}
Within the more advanced chapters a section will be set aside to give the reader some challenging exercises. These Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
exercises are not designed to be prize winning problems, but instead to be thought provoking. Wherever possible the the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought
problems are forward minded, stating problems that will be answered in subsequent chapters. The reader is encouraged to provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent
finish the exercises as they appear to get a better understanding of the subject material. chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the
subject material.
That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular
are encouraged to verify they can answer the problems correctly before moving on. are encouraged to verify they can answer the problems correctly before moving on.
@ -410,52 +413,60 @@ are encouraged to verify they can answer the problems correctly before moving on
Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these
exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the
scoring. scoring system used.
\begin{tabular}{cl} \begin{figure}[here]
$\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\ \begin{center}
\begin{small}
\begin{tabular}{|c|l|}
\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
& minutes to solve. Usually does not involve much computer time \\ & minutes to solve. Usually does not involve much computer time \\
& to solve. \\ & to solve. \\
& \\ \hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
$\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
& time usage. Usually requires a program to be written to \\ & time usage. Usually requires a program to be written to \\
& solve the problem. \\ & solve the problem. \\
& \\ \hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
$\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
& of work. Usually involves trivial research and development of \\ & of work. Usually involves trivial research and development of \\
& new theory from the perspective of a student. \\ & new theory from the perspective of a student. \\
& \\ \hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
$\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
& of work and research, the solution to which will demonstrate \\ & of work and research, the solution to which will demonstrate \\
& a higher mastery of the subject matter. \\ & a higher mastery of the subject matter. \\
& \\ \hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
$\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
& novice to solve. Solutions to these problems will demonstrate a \\ & novice to solve. Solutions to these problems will demonstrate a \\
& complete mastery of the given subject. \\ & complete mastery of the given subject. \\
& \\ \hline
\end{tabular} \end{tabular}
\end{small}
\end{center}
\caption{Exercise Scoring System}
\end{figure}
Essentially problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level are also devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level
designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These
two levels are essentially entry level questions.
Problems at the third level are meant to be a bit more difficult. Often the answer is fairly obvious but arriving at an exacting solution Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often
requires some thought and skill. These problems will almost always involve devising a new algorithm or implementing a variation of fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always
another algorithm. involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can
answer these questions will feel comfortable with the concepts behind the topic at hand.
Problems at the fourth level are meant to be even more difficult as well as involve some research. The reader will most Problems at the fourth level are meant to be similar to those of the level three questions except they will require
likely not know the answer right away, nor will the text provide the exact details of the answer until a subsequent additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide
chapter. Problems at the fifth level are meant to be the hardest problems relative to all the other problems in the the exact details of the answer until a subsequent chapter.
chapter. People who can correctly answer fifth level problems have a mastery of the subject matter at hand.
Problems at the fifth level are meant to be the hardest
problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a
mastery of the subject matter at hand.
Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader
is encouraged to answer the follow-up problems and try to draw the relevance of problems. is encouraged to answer the follow-up problems and try to draw the relevance of problems.
\chapter{Introduction to LibTomMath} \section{Introduction to LibTomMath}
\section{What is LibTomMath?} \subsection{What is LibTomMath?}
LibTomMath is a free and open source multiple precision library written in portable ISO C. By portable it is LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it
meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on
any given platform. any given platform.
The library has been successfully tested under numerous operating systems including Unix\footnote{All of these The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
@ -463,7 +474,7 @@ trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux,
as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such
as public key cryptosystems and still maintain a relatively small footprint. as public key cryptosystems and still maintain a relatively small footprint.
\section{Goals of LibTomMath} \subsection{Goals of LibTomMath}
Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However, Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However,
even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the
@ -479,13 +490,13 @@ based on the magnitude of the inputs and the configuration of the library.
Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should
be source compatible with another popular library which makes it more attractive for developers to use. In this case the be source compatible with another popular library which makes it more attractive for developers to use. In this case the
MPI library was used as a API template for all the basic functions. MPI was chosen as the template because it is MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits
another library that fits in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument
function names and argument passing conventions, LibTomMath has been written from scratch by Tom St Denis. passing conventions, it has been written from scratch by Tom St Denis.
The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum''
library exists which can be used to teach computer science students how to perform fast and reliable multiple precision library exists which can be used to teach computer science students how to perform fast and reliable multiple precision
arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points. integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points.
\section{Choice of LibTomMath} \section{Choice of LibTomMath}
LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
@ -500,15 +511,13 @@ developer can more readily discern the true intent of a given section of source
what conditional code will be used. what conditional code will be used.
The code base of LibTomMath is also well organized. Each function is in its own separate source code file The code base of LibTomMath is also well organized. Each function is in its own separate source code file
which allows the reader to find a given function very quickly. When compiled with GCC for the x86 processor the entire which allows the reader to find a given function very quickly. On average there are about $76$ lines of code per source
library is a mere 87,760 bytes ($116,182$ bytes for ARMv4 processors). This includes every single function file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing
LibTomMath provides from basic arithmetic to various number theoretic functions such as modular exponentiation, various very hard. GMP has many conditional code segments which also hinder tracing.
reduction algorithms and Jacobi symbol computation.
By comparison MPI, which has fewer functions than LibTomMath, compiled with the same conditions occupied 45,429 bytes When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $66$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
($54,536$ for ARMv4). GMP which has a rather large collection of functions with the default configuration on an which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about
x86 Athlon is 2,950,688 bytes. Note that while LibTomMath has fewer functions than GMP it has been used as the sole basis $50$KiB) but LibTomMath is also much faster and more complete than MPI.
for several public key cryptosystems without having to seek additional outside functions to supplement the library.
\subsection{API Simplicity} \subsection{API Simplicity}
LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build
@ -519,6 +528,11 @@ which is an extremely valuable benefit for the student and developer alike.
The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to
illegible short hand. LibTomMath does not share this characteristic. illegible short hand. LibTomMath does not share this characteristic.
The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In
effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely
undersireable in many situations.
\subsection{Optimizations} \subsection{Optimizations}
While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP
@ -2320,6 +2334,7 @@ This technique led to the discovery of polynomial basis algorithms (\textit{good
\section{Multiplication} \section{Multiplication}
\subsection{The Baseline Multiplication} \subsection{The Baseline Multiplication}
\label{sec:basemult}
\index{baseline multiplication} \index{baseline multiplication}
Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision
@ -2985,6 +3000,7 @@ The implementation is rather simplistic and is not particularly noteworthy. Lin
operator from the C programming language. Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$. operator from the C programming language. Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.
\section{Squaring} \section{Squaring}
\label{sec:basesquare}
Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization
available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications
@ -6261,6 +6277,12 @@ OpenSSL Cryptographic Toolkit, \url{http://openssl.org}
\bibitem[17]{LIP} \bibitem[17]{LIP}
Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip} Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}
\bibitem[18]{ISOC}
JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''
\bibitem[19]{JAVA}
The Sun Java Website, \url{http://java.sun.com/}
\end{thebibliography} \end{thebibliography}
\input{tommath.ind} \input{tommath.ind}

File diff suppressed because it is too large Load Diff