Changes to make mpi use 64-bit digits on machines where unsigned longs

are 64-bits.  Renamed s_mp_invmod_32b to s_mp_invmod_radix since radix
can now exceed 32 bits.  Improved performance on all platforms except
MIPS and X86.
This commit is contained in:
nelsonb%netscape.com 2000-09-14 00:31:01 +00:00
Родитель 0257791053
Коммит c4fe227bb9
8 изменённых файлов: 110 добавлений и 42 удалений

Просмотреть файл

@ -36,7 +36,7 @@
## GPL.
##
##
## $Id: Makefile,v 1.8 2000/08/31 02:43:56 nelsonb%netscape.com Exp $
## $Id: Makefile,v 1.9 2000/09/14 00:30:47 nelsonb%netscape.com Exp $
##
## Define CC to be the C compiler you wish to use. The GNU cc
@ -62,7 +62,6 @@ PERL=perl
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
CFLAGS= -O $(MPICMN)
#CFLAGS=-ansi -fullwarn -woff 1521 -O3 $(MPICMN)
#CFLAGS=-ansi -fullwarn -woff 1521 -L/usr/linguist/lib -g -DMP_DEBUG=1 $(MPICMN)
#CFLAGS=-ansi -pedantic -Wall -O3 $(MPICMN)
#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1 $(MPICMN)
@ -70,20 +69,31 @@ CFLAGS= -O $(MPICMN)
#MPICMN += -DMP_MONT_USE_MP_MUL
#MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
#AS_OBJS = mpi_mips.o
#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions -mips3
#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions
#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
#CFLAGS=-ansi -n32 -O3 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
#CFLAGS=-ansi -n32 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \
$(MPICMN)
#CFLAGS=-ansi -64 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \
$(MPICMN)
#Alpha/OSF1
#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT $(MPICMN)
#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT \
-DMP_NO_MP_WORD $(MPICMN)
#Solaris
#CFLAGS= -O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_8 -D_SVID_GETTOD -xarch=v9 -DXP_UNIX -D_PR_GLOBAL_THREADS_ONLY \
-DNSS_USE_64 $(MPICMN)
#CFLAGS= -g -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_8 -D_SVID_GETTOD -xarch=v9 -DXP_UNIX -D_PR_GLOBAL_THREADS_ONLY \
-DNSS_USE_64 $(MPICMN)
#CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_6 -D_SVID_GETTOD -xarch=v8 -DXP_UNIX -D_PR_GLOBAL_THREADS_ONLY \
-DMP_NO_MP_WORD $(MPICMN)
#CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_6 -D_SVID_GETTOD -xarch=v8 -DXP_UNIX -D_PR_GLOBAL_THREADS_ONLY \
$(MPICMN)
@ -93,7 +103,7 @@ CFLAGS= -O $(MPICMN)
-D_HPUX_SOURCE -Aa +e +DA2.0W +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \
-DNSS_USE_64 $(MPICMN)
#CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN)
-D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX -DMP_NO_MP_WORD $(MPICMN)
#Linux
#AS_OBJS = mpi_x86.o
@ -208,6 +218,8 @@ libmpi.a: $(LIBOBJS)
ar -cvr libmpi.a $(LIBOBJS)
$(RANLIB) libmpi.a
mpi.i: mpi.h
#---------------------------------------
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
@ -279,7 +291,7 @@ doc:
(cd doc; ./build)
clean:
rm -f *.o *.a
rm -f *.o *.a *.i
rm -f core
rm -f *~ .*~
rm -f utils/*.o

Просмотреть файл

@ -38,7 +38,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the GPL.
*
* $Id: mpi-priv.h,v 1.10 2000/08/31 02:51:23 nelsonb%netscape.com Exp $
* $Id: mpi-priv.h,v 1.11 2000/09/14 00:30:48 nelsonb%netscape.com Exp $
*/
#ifndef _MPI_PRIV_H_
#define _MPI_PRIV_H_ 1
@ -223,7 +223,7 @@ int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */
int s_mp_tovalue(char ch, int r); /* convert ch to value */
char s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */
int s_mp_outlen(int bits, int r); /* output length in bytes */
mp_digit s_mp_invmod_32b(mp_digit P); /* returns (P ** -1) mod (2 ** 32) */
mp_digit s_mp_invmod_radix(mp_digit P); /* returns (P ** -1) mod RADIX */
/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */
void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c);

Просмотреть файл

@ -38,7 +38,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the GPL.
*
* $Id: mpi-test.c,v 1.6 2000/09/12 00:41:08 nelsonb%netscape.com Exp $
* $Id: mpi-test.c,v 1.7 2000/09/14 00:30:49 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
@ -371,9 +371,15 @@ char *v_mp9[] = {
};
unsigned char b_mp4[] = {
0x01, 0x63, 0xDB, 0xC2, 0x26, 0x5B, 0x88, 0x26,
0x8D, 0xC8, 0x01, 0xC1, 0x0E, 0xA6, 0x84, 0x76,
0xB7, 0xBD, 0xE0, 0x09, 0x0F
0x01,
#if MP_DIGIT_MAX > MP_32BIT_MAX
0x00, 0x00, 0x00, 0x00,
#endif
0x63, 0xDB, 0xC2, 0x26,
0x5B, 0x88, 0x26, 0x8D,
0xC8, 0x01, 0xC1, 0x0E,
0xA6, 0x84, 0x76, 0xB7,
0xBD, 0xE0, 0x09, 0x0F
};
/* Search for a test suite name in the names table */
@ -990,14 +996,14 @@ int test_div(void)
mp_toradix(&a, g_intbuf, 16);
if(strcmp(g_intbuf, q_mp42) != 0) {
reason("error: computed quot %s, expected %s\n", g_intbuf, q_mp42);
reason("error: test 1 computed quot %s, expected %s\n", g_intbuf, q_mp42);
++err;
}
mp_toradix(&r, g_intbuf, 16);
if(strcmp(g_intbuf, r_mp42) != 0) {
reason("error: computed rem %s, expected %s\n", g_intbuf, r_mp42);
reason("error: test 1 computed rem %s, expected %s\n", g_intbuf, r_mp42);
++err;
}
@ -1006,14 +1012,14 @@ int test_div(void)
mp_toradix(&a, g_intbuf, 16);
if(strcmp(g_intbuf, q_mp45a) != 0) {
reason("error: computed quot %s, expected %s\n", g_intbuf, q_mp45a);
reason("error: test 2 computed quot %s, expected %s\n", g_intbuf, q_mp45a);
++err;
}
mp_toradix(&r, g_intbuf, 16);
if(strcmp(g_intbuf, r_mp45a) != 0) {
reason("error: computed rem %s, expected %s\n", g_intbuf, r_mp45a);
reason("error: test 2 computed rem %s, expected %s\n", g_intbuf, r_mp45a);
++err;
}
@ -1022,14 +1028,14 @@ int test_div(void)
mp_toradix(&a, g_intbuf, 16);
if(strcmp(g_intbuf, q_mp1404) != 0) {
reason("error: computed quot %s, expected %s\n", g_intbuf, q_mp1404);
reason("error: test 3 computed quot %s, expected %s\n", g_intbuf, q_mp1404);
++err;
}
mp_toradix(&r, g_intbuf, 16);
if(strcmp(g_intbuf, r_mp1404) != 0) {
reason("error: computed rem %s, expected %s\n", g_intbuf, r_mp1404);
reason("error: test 3 computed rem %s, expected %s\n", g_intbuf, r_mp1404);
++err;
}
@ -1622,7 +1628,7 @@ int test_raw(void)
len = mp_raw_size(&a);
if(len != sizeof(b_mp4)) {
reason("error: expected length %d, computed %d\n", sizeof(b_mp4),
reason("error: test_raw: expected length %d, computed %d\n", sizeof(b_mp4),
len);
mp_clear(&a);
return 1;
@ -1631,8 +1637,8 @@ int test_raw(void)
buf = calloc(len, sizeof(char));
mp_toraw(&a, buf);
if(memcmp(buf, b_mp4, len) != 0) {
reason("error: binary output does not match test vector\n");
if(memcmp(buf, b_mp4, sizeof(b_mp4)) != 0) {
reason("error: test_raw: binary output does not match test vector\n");
out = 1;
}

Просмотреть файл

@ -35,7 +35,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the GPL.
*
* $Id: mpi.c,v 1.23 2000/09/12 00:41:09 nelsonb%netscape.com Exp $
* $Id: mpi.c,v 1.24 2000/09/14 00:30:49 nelsonb%netscape.com Exp $
*/
#include "mpi-priv.h"
@ -533,7 +533,7 @@ mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
if((pow = s_mp_ispow2d(d)) >= 0) {
mp_digit mask;
mask = (1 << pow) - 1;
mask = ((mp_digit)1 << pow) - 1;
rem = DIGIT(a, 0) & mask;
if(q) {
@ -2021,13 +2021,17 @@ CLEANUP:
** This technique from the paper "Fast Modular Reciprocals" (unpublished)
** by Richard Schroeppel (a.k.a. Captain Nemo).
*/
mp_digit s_mp_invmod_32b(mp_digit P)
mp_digit s_mp_invmod_radix(mp_digit P)
{
mp_digit T = P;
T *= 2 - (P * T);
T *= 2 - (P * T);
T *= 2 - (P * T);
T *= 2 - (P * T);
#if MP_DIGIT_MAX > MP_32BIT_MAX
T *= 2 - (P * T);
T *= 2 - (P * T);
#endif
return T;
}
@ -2054,7 +2058,7 @@ mp_err s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *x
ix = MP_MAX(ix, MP_USED(x));
MP_CHECKOK( s_mp_pad(x, ix) );
r = 0 - s_mp_invmod_32b(MP_DIGIT(p,0));
r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0));
for (ix = 0; k > 0; ix++) {
int j = MP_MIN(k, MP_DIGIT_BIT);
@ -2791,7 +2795,7 @@ void s_mp_mod_2d(mp_int *mp, mp_digit d)
return;
/* Flush all the bits above 2^d in its digit */
dmask = (1 << nbit) - 1;
dmask = ((mp_digit)1 << nbit) - 1;
DIGIT(mp, ndig) &= dmask;
/* Flush all digits above the one with 2^d in it */
@ -2819,7 +2823,7 @@ void s_mp_div_2d(mp_int *mp, mp_digit d)
s_mp_rshd(mp, d / DIGIT_BIT);
d %= DIGIT_BIT;
if (d) {
mask = (1 << d) - 1;
mask = ((mp_digit)1 << d) - 1;
save = 0;
for(ix = USED(mp) - 1; ix >= 0; ix--) {
next = DIGIT(mp, ix) & mask;
@ -3192,7 +3196,8 @@ mp_err s_mp_add(mp_int *a, const mp_int *b) /* magnitude addition */
}
#else
while (carry && ix < used) {
*pa++ = sum = carry + *pa;
sum = carry + *pa;
*pa++ = sum;
carry = !sum;
++ix;
}
@ -3544,7 +3549,7 @@ mp_err s_mp_mul(mp_int *a, const mp_int *b)
/* }}} */
#if defined(SOLARIS)
#if defined(SOLARIS) && (ULONG_MAX == UINT_MAX)
/* This trick works on Sparc V8 CPUs with the Workshop compilers. */
#define MP_MUL_DxD(a, b, Phi, Plo) \
{ unsigned long long product = (unsigned long long)a * b; \
@ -3736,8 +3741,8 @@ void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
a1a1 = a1 * a1;
a0a1 = a0 * a1;
a1a1 += a0a1 >> 15;
a0a1 <<= 17;
a1a1 += a0a1 >> (MP_HALF_DIGIT_BIT - 1);
a0a1 <<= (MP_HALF_DIGIT_BIT + 1);
a0a0 += a0a1;
if (a0a0 < a0a1)
++a1a1;
@ -3985,7 +3990,7 @@ mp_err s_mp_2expt(mp_int *a, mp_digit k)
if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
return res;
DIGIT(a, dig) |= (1 << bit);
DIGIT(a, dig) |= ((mp_digit)1 << bit);
return MP_OKAY;
@ -4162,6 +4167,7 @@ int s_mp_ispow2d(mp_digit d)
{
if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */
int pow = 0;
#if MP_DIGIT_MAX == MP_32BIT_MAX
if (d & 0xffff0000)
pow += 16;
if (d & 0xff00ff00)
@ -4172,6 +4178,20 @@ int s_mp_ispow2d(mp_digit d)
pow += 2;
if (d & 0xaaaaaaaa)
pow += 1;
#else
if (d & 0xffffffff00000000UL)
pow += 32;
if (d & 0xffff0000ffff0000UL)
pow += 16;
if (d & 0xff00ff00ff00ff00UL)
pow += 8;
if (d & 0xf0f0f0f0f0f0f0f0UL)
pow += 4;
if (d & 0xccccccccccccccccUL)
pow += 2;
if (d & 0xaaaaaaaaaaaaaaaaUL)
pow += 1;
#endif
return pow;
}
return -1;

Просмотреть файл

@ -36,7 +36,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: mpi.h,v 1.10 2000/08/31 03:59:48 nelsonb%netscape.com Exp $
* $Id: mpi.h,v 1.11 2000/09/14 00:30:50 nelsonb%netscape.com Exp $
*/
#ifndef _H_MPI_
@ -55,6 +55,7 @@
#endif
#include <limits.h>
#include <sys/types.h>
#define MP_NEG 1
#define MP_ZPOS 0
@ -72,10 +73,30 @@ typedef unsigned int mp_sign;
typedef unsigned int mp_size;
typedef int mp_err;
#define MP_32BIT_MAX 4294967295U
#if !defined(ULONG_MAX)
#error "ULONG_MAX not defined"
#elif !defined(UINT_MAX)
#error "UINT_MAX not defined"
#elif !defined(USHRT_MAX)
#error "USHRT_MAX not defined"
#endif
#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX
typedef unsigned long mp_digit;
#define MP_DIGIT_MAX ULONG_MAX
#define MP_HALF_DIGIT_MAX UINT_MAX
#undef MP_NO_MP_WORD
#define MP_NO_MP_WORD 1
#else
typedef unsigned int mp_digit;
#define MP_DIGIT_MAX UINT_MAX
#define MP_HALF_DIGIT_MAX USHRT_MAX
#endif
#ifndef MP_NO_MP_WORD
#if defined(ULONG_LONG_MAX) /* GCC, HPUX */
#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
#elif defined(ULLONG_MAX) /* Solaris */
@ -84,7 +105,8 @@ typedef unsigned int mp_digit;
#define MP_ULONG_LONG_MAX ULONGLONG_MAX
#endif
#if defined(MP_ULONG_LONG_MAX) && MP_ULONG_LONG_MAX > UINT_MAX
#if defined(MP_ULONG_LONG_MAX)
#if MP_ULONG_LONG_MAX > UINT_MAX
#if MP_ULONG_LONG_MAX == ULONG_MAX
typedef unsigned long mp_word;
typedef long mp_sword;
@ -94,9 +116,13 @@ typedef unsigned long long mp_word;
typedef long long mp_sword;
#define MP_WORD_MAX MP_ULONG_LONG_MAX
#endif
#else /* MP_ULONG_LONG_MAX <= UINT_MAX */
#define MP_NO_MP_WORD 1
#endif
#else /* MP_ULONG_LONG_MAX not defined */
#define MP_NO_MP_WORD 1
#endif
#endif /* !MP_NO_MP_WORD */
#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD)
@ -110,7 +136,6 @@ typedef int mp_sword;
#define MP_RADIX (1+(mp_word)MP_DIGIT_MAX)
#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2)
#define MP_HALF_DIGIT_MAX USHRT_MAX
#define MP_HALF_RADIX (1+(mp_digit)MP_HALF_DIGIT_MAX)
/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named
** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's
@ -119,8 +144,12 @@ typedef int mp_sword;
#if MP_DIGIT_MAX == USHRT_MAX
#define MP_DIGIT_FMT "%04X" /* printf() format for 1 digit */
#else
#elif MP_DIGIT_MAX == UINT_MAX
#define MP_DIGIT_FMT "%08X" /* printf() format for 1 digit */
#elif MP_DIGIT_MAX == ULONG_MAX
#define MP_DIGIT_FMT "%016lX" /* printf() format for 1 digit */
#else
#define MP_DIGIT_FMT "%016llX" /* printf() format for 1 digit */
#endif
/* Macros for accessing the mp_int internals */

Просмотреть файл

@ -34,7 +34,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the GPL.
*
* $Id: mplogic.c,v 1.11 2000/08/09 20:53:25 nelsonb%netscape.com Exp $
* $Id: mplogic.c,v 1.12 2000/09/14 00:30:50 nelsonb%netscape.com Exp $
*/
#include "mpi-priv.h"
@ -439,7 +439,8 @@ mp_err mpl_significant_bits(const mp_int *a)
ix = MP_USED(a);
for (ix = MP_USED(a); ix > 0; ) {
mp_digit d = MP_DIGIT(a, --ix);
mp_digit d;
d = MP_DIGIT(a, --ix);
if (d) {
while (d) {
++bits;

Просмотреть файл

@ -29,7 +29,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
* $Id: mpmontg.c,v 1.7 2000/08/22 01:57:34 nelsonb%netscape.com Exp $
* $Id: mpmontg.c,v 1.8 2000/09/14 00:30:51 nelsonb%netscape.com Exp $
*/
/* This file implements moduluar exponentiation using Montgomery's
@ -225,7 +225,7 @@ mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent,
/* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
** where n0 = least significant mp_digit of N, the modulus.
*/
mmm.n0prime = 0 - s_mp_invmod_32b( MP_DIGIT(modulus, 0) );
mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) );
MP_CHECKOK( s_mp_to_mont(base, &mmm, &square) );

Просмотреть файл

@ -3,7 +3,7 @@
*
* Modular exponentiation timing test
*
* $Id: metime.c,v 1.2 2000/07/17 22:37:55 nelsonb%netscape.com Exp $
* $Id: metime.c,v 1.3 2000/09/14 00:31:01 nelsonb%netscape.com Exp $
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
@ -36,7 +36,7 @@
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the GPL.
*
* $Id: metime.c,v 1.2 2000/07/17 22:37:55 nelsonb%netscape.com Exp $
* $Id: metime.c,v 1.3 2000/09/14 00:31:01 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
@ -103,7 +103,7 @@ int main(int argc, char *argv[])
mpp_random_size(&m, prec);
/* set msb and lsb of m */
DIGIT(&m,0) |= 1;
DIGIT(&m, USED(&m)-1) |= 1L << (DIGIT_BIT - 1);
DIGIT(&m, USED(&m)-1) |= (mp_digit)1 << (DIGIT_BIT - 1);
if (mp_cmp(&a, &m) > 0)
mp_sub(&a, &m, &a);