MPI Arbitrary Precision Integer Arithmetic library.

The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>


git-svn-id: svn://10.0.0.236/trunk@74223 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
nelsonb%netscape.com 2000-07-14 00:45:02 +00:00
parent 02ffe41ed5
commit 4a93e035ae
80 changed files with 21474 additions and 0 deletions

View File

@ -0,0 +1,273 @@
##
## Makefile for MPI library
##
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: Makefile,v 1.1 2000-07-14 00:44:17 nelsonb%netscape.com Exp $
##
## Define CC to be the C compiler you wish to use. The GNU cc
## compiler (gcc) should work, at the very least
#CC=cc
CC=gcc
##
## Define PERL to point to your local Perl interpreter. It
## should be Perl 5.x, although it's conceivable that Perl 4
## might work ... I haven't tested it.
##
PERL=/usr/bin/perl
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
#CFLAGS=-ansi -fullwarn -woff 1521 -O3
#CFLAGS=-ansi -fullwarn -woff 1521 -L/usr/linguist/lib -g -DMP_DEBUG=1
CFLAGS=-ansi -pedantic -Wall -O3
#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1
##
## Define LIBS to include any libraries you need to link against.
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
## necessary to bring in the math library. Otherwise, it can be
## left alone, unless your system has other peculiar requirements.
##
LIBS=#-lmalloc#-lefence#-lm
##
## Define RANLIB to be the library header randomizer; you might not
## need this on some systems (just set it to 'echo' on these systems,
## such as IRIX)
##
RANLIB=echo
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c karatsuba.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h \
mplogic.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc \
utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
basecvt fact exptmod pi makeprime
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "libmpi - arithmetic and prime testing library"
@ echo "tests - test drivers (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.c.o: $*.h $*.c
$(CC) $(CFLAGS) -c $<
mpi.o: mpi-config.h logtab.h mpi.h mpi.c
$(CC) $(CFLAGS) -c mpi.c
libmpi: mpi.o mpprime.o
ar -cvr libmpi.a mpi.o mpprime.o
$(RANLIB) libmpi.a
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mptest1: mpi.o tests/mptest-1.c
$(CC) $(CFLAGS) -o mptest1 mpi.o tests/mptest-1.c $(LIBS)
mptest2: mpi.o tests/mptest-2.c
$(CC) $(CFLAGS) -o mptest2 mpi.o tests/mptest-2.c $(LIBS)
mptest3: mpi.o tests/mptest-3.c
$(CC) $(CFLAGS) -o mptest3 mpi.o tests/mptest-3.c $(LIBS)
mptest3a: mpprime.o mpi.o tests/mptest-3a.c
$(CC) $(CFLAGS) -o mptest3a mpprime.o mpi.o tests/mptest-3a.c $(LIBS)
mptest4: mpi.o tests/mptest-4.c
$(CC) $(CFLAGS) -o mptest4 mpi.o tests/mptest-4.c $(LIBS)
mptest4a: mpi.o mpprime.o tests/mptest-4a.c
$(CC) $(CFLAGS) -o mptest4a mpi.o mpprime.o tests/mptest-4a.c $(LIBS)
mptest4b: mpi.o mpprime.o tests/mptest-4b.c
$(CC) $(CFLAGS) -o mptest4b mpi.o mpprime.o tests/mptest-4b.c $(LIBS)
mptest5: mpi.o tests/mptest-5.c
$(CC) $(CFLAGS) -o mptest5 mpi.o tests/mptest-5.c $(LIBS)
mptest5a: mpprime.o mpi.o tests/mptest-5a.c
$(CC) $(CFLAGS) -o mptest5a mpprime.o mpi.o tests/mptest-5a.c $(LIBS)
mptest6: mpi.o tests/mptest-6.c
$(CC) $(CFLAGS) -o mptest6 mpi.o tests/mptest-6.c $(LIBS)
mptest7: mpprime.o mpi.o tests/mptest-7.c
$(CC) $(CFLAGS) -o mptest7 mpprime.o mpi.o tests/mptest-7.c $(LIBS)
mptest8: mpprime.o mpi.o tests/mptest-8.c
$(CC) $(CFLAGS) -o mptest8 mpprime.o mpi.o tests/mptest-8.c $(LIBS)
mptest9: mplogic.o mpi.o tests/mptest-9.c
$(CC) $(CFLAGS) -o mptest9 mplogic.o mpi.o tests/mptest-9.c $(LIBS)
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test: mpi.o mpprime.o test-info.c mpi-test.c
$(CC) $(CFLAGS) -o mpi-test mpi.o mpprime.o mpi-test.c $(LIBS)
bbsrand: utils/bbs_rand.o mpi.o utils/bbsrand.c
$(CC) $(CFLAGS) -o bbsrand mpi.o bbs_rand.o utils/bbsrand.c $(LIBS)
primegen: mpprime.o mpi.o utils/primegen.c
$(CC) $(CFLAGS) -o primegen mpi.o mpprime.o utils/primegen.c $(LIBS)
metime: mpprime.o mpi.o utils/metime.c
$(CC) $(CFLAGS) -o metime mpi.o mpprime.o utils/metime.c $(LIBS)
mulsqr: logtab.h mpi.h mpi-config.h mpi.c mpprime.h mpprime.c mulsqr.c
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o mulsqr mpi.c mpprime.c mulsqr.c $(LIBS)
karatsuba: logtab.h mpi-config.h mpi.o mpprime.o karatsuba.c
$(CC) $(CFLAGS) -DMP_KARATSUBA=1 -o karatsuba mpi.o mpprime.o \
karatsuba.c $(LIBS)
basecvt: mpi.o utils/basecvt.c
$(CC) $(CFLAGS) -o basecvt mpi.o utils/basecvt.c $(LIBS)
fact: mpi.o utils/fact.c
$(CC) $(CFLAGS) -o fact mpi.o utils/fact.c $(LIBS)
exptmod: mpi.o utils/exptmod.c
$(CC) $(CFLAGS) -o exptmod mpi.o utils/exptmod.c $(LIBS)
pi: mpi.o utils/pi.c
$(CC) $(CFLAGS) -o pi mpi.o utils/pi.c $(LIBS)
makeprime: mpi.o mpprime.o utils/makeprime.c
$(CC) $(CFLAGS) -o makeprime mpi.o mpprime.o utils/makeprime.c $(LIBS)
prng: utils/bbs_rand.o mpi.o utils/prng.c
$(CC) $(CFLAGS) -o prng mpi.o bbs_rand.o utils/prng.c $(LIBS)
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b \
mptest6 bbsrand
utests: mptest7 mptest8 mptest9
alltests: tests utests mpi-test
tools: $(TOOLS)
doc:
(cd doc; ./build)
gcd: mpi.o utils/gcd.c
$(CC) $(CFLAGS) -o gcd mpi.o utils/gcd.c $(LIBS)
invmod: mpi.o utils/invmod.c
$(CC) $(CFLAGS) -o invmod mpi.o utils/invmod.c $(LIBS)
lap: mpi.o utils/lap.c
$(CC) $(CFLAGS) -o lap mpi.o utils/lap.c $(LIBS)
isprime: mpprime.o mpi.o utils/isprime.c
$(CC) $(CFLAGS) -o isprime mpprime.o mpi.o utils/isprime.c $(LIBS)
dec2hex: mpi.o utils/dec2hex.c
$(CC) $(CFLAGS) -o dec2hex mpi.o utils/dec2hex.c $(LIBS)
hex2dec: mpi.o utils/hex2dec.c
$(CC) $(CFLAGS) -o hex2dec mpi.o utils/hex2dec.c $(LIBS)
clean:
rm -f *.o
rm -f core
rm -f *~ .*~
rm -f utils/*.o
rm -f utils/core
rm -f utils/*~ utils/.*~
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f libmpi.a
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
# END

View File

@ -0,0 +1,795 @@
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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.
About the MPI Library
---------------------
The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision
signed integer arithmetic package. The implementation is not the most
efficient possible, but the code is small and should be fairly easily
portable to just about any machine that supports an ANSI C compiler,
as long as it is capable of at least 16-bit arithmetic (but also see
below for more on this).
This library was written with an eye to cryptographic applications;
thus, some care is taken to make sure that temporary values are not
left lying around in memory when they are no longer in use. This adds
some overhead for zeroing buffers before they are released back into
the free pool; however, it gives you the assurance that there is only
one copy of your important values residing in your process's address
space at a time. Obviously, it is difficult to guarantee anything, in
a pre-emptive multitasking environment, but this at least helps you
keep a lid on the more obvious ways your data can get spread around in
memory.
Using the Library
-----------------
To use the MPI library in your program, you must include the header:
#include "mpi.h"
This header provides all the type and function declarations you'll
need to use the library. Almost all the names defined by the library
begin with the prefix 'mp_', so it should be easy to keep them from
clashing with your program's namespace (he says, glibly, knowing full
well there are always pathological cases).
There are a few things you may want to configure about the library.
By default, the MPI library uses an unsigned short for its digit type,
and an unsigned int for its word type. The word type must be big
enough to contain at least two digits, for the primitive arithmetic to
work out. On my machine, a short is 2 bytes and an int is 4 bytes --
but if you have 64-bit ints, you might want to use a 4-byte digit and
an 8-byte word. I have tested the library using 1-byte digits and
2-byte words, as well. Whatever you choose to do, the things you need
to change are:
(1) The type definitions for mp_digit and mp_word.
(2) The macro DIGIT_FMT which tells mp_print() how to display a
single digit. This is just a printf() format string, so you
can adjust it appropriately.
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
largest value expressible in an mp_digit and an mp_word,
respectively.
Both the mp_digit and mp_word should be UNSIGNED integer types. The
code relies on having the full positive precision of the type used for
digits and words.
The remaining type definitions should be left alone, for the most
part. The code in the library does not make any significant
assumptions about the sizes of things, but there is little if any
reason to change the other parameters, so I would recommend you leave
them as you found them.
The library comes with a Perl script, 'types.pl', which will scan your
current Makefile settings, and attempt to find good definitions for
these types. It relies on a Unix sort of build environment, so it
probably won't work under MacOS or Windows, but it can be convenient
if you're porting to a new flavour of Unix. Just run 'types.pl' at
the command line, and it will spit out its results to the standard
output.
Conventions
-----------
Most functions in the library return a value of type mp_err. This
permits the library to communicate success or various kinds of failure
to the calling program. The return values currently defined are:
MP_OKAY - okay, operation succeeded, all's well
MP_YES - okay, the answer is yes (same as MP_OKAY)
MP_NO - okay, but answer is no (not MP_OKAY)
MP_MEM - operation ran out of memory
MP_RANGE - input parameter was out of range
MP_BADARG - an invalid input parameter was provided
MP_UNDEF - no output value is defined for this input
The only function which currently uses MP_UNDEF is mp_invmod().
Division by zero is undefined, but the division functions will return
MP_RANGE for a zero divisor. MP_BADARG usually means you passed a
bogus mp_int structure to the function. MP_YES and MP_NO are not used
by the library itself; they're defined so you can use them in your own
extensions.
If you need a readable interpretation of these error codes in your
program, you may also use the mp_strerror() function. This function
takes an mp_err as input, and returns a pointer to a human-readable
string describing the meaning of the error. These strings are stored
as constants within the library, so the caller should not attempt to
modify or free the memory associated with these strings.
The library represents values in signed-magnitude format. Values
strictly less than zero are negative, all others are considered
positive (zero is positive by fiat). You can access the 'sign' member
of the mp_int structure directly, but better is to use the mp_cmp_z()
function, to find out which side of zero the value lies on.
Most arithmetic functions have a single-digit variant, as well as the
full arbitrary-precision. An mp_digit is an unsigned value between 0
and DIGIT_MAX inclusive. The radix is available as RADIX. The number
of bits in a given digit is given as DIGIT_BIT.
Generally, input parameters are given before output parameters.
Unless otherwise specified, any input parameter can be re-used as an
output parameter, without confusing anything.
The basic numeric type defined by the library is an mp_int. Virtually
all the functions in the library take a pointer to an mp_int as one of
their parameters. An explanation of how to create and use these
<HR>
<A NAME="p23">
<H3>Problem 23:</H3>
structures follows. And so, without further ado...
Initialization and Cleanup
--------------------------
The basic numeric type defined by the library is an 'mp_int'.
However, it is not sufficient to simply declare a variable of type
mp_int in your program. These variables also need to be initialized
before they can be used, to allocate the internal storage they require
for computation.
This is done using one of the following functions:
mp_init(mp_int *mp);
mp_init_copy(mp_int *mp, mp_int *from);
mp_init_size(mp_int *mp, mp_size p);
Each of these requires a pointer to a structure of type mp_int. The
basic mp_init() simply initializes the mp_int to a default size, and
sets its value to zero. If you would like to initialize a copy of an
existing mp_int, use mp_init_copy(), where the 'from' parameter is the
mp_int you'd like to make a copy of. The third function,
mp_init_size(), permits you to specify how many digits of precision
should be preallocated for your mp_int. This can help the library
avoid unnecessary re-allocations later on.
The default precision used by mp_init() can be retrieved using:
precision = mp_get_prec();
This returns the number of digits that will be allocated. You can
change this value by using:
mp_set_prec(unsigned int prec);
Any positive value is acceptable -- if you pass zero, the default
precision will be re-set to the compiled-in library default (this is
specified in the header file 'mpi-config.h', and typically defaults to
8 or 16).
Just as you must allocate an mp_int before you can use it, you must
clean up the structure when you are done with it. This is performed
using the mp_clear() function. Remember that any mp_int that you
create as a local variable in a function must be mp_clear()'d before
that function exits, or else the memory allocated to that mp_int will
be orphaned and unrecoverable.
To set an mp_int to a given value, the following functions are given:
mp_set(mp_int *mp, mp_digit d);
mp_set_int(mp_int *mp, long z);
The mp_set() function sets the mp_int to a single digit value, while
mp_set_int() sets the mp_int to a signed long integer value.
To set an mp_int to zero, use:
mp_zero(mp_int *mp);
Copying and Moving
------------------
If you have two initialized mp_int's, and you want to copy the value
of one into the other, use:
mp_copy(from, to)
This takes care of clearing the old value of 'to', and copies the new
value into it. If 'to' is not yet initialized, use mp_init_copy()
instead (see above).
Note: The library tries, whenever possible, to avoid allocating
---- new memory. Thus, mp_copy() tries first to satisfy the needs
of the copy by re-using the memory already allocated to 'to'.
Only if this proves insufficient will mp_copy() actually
allocate new memory.
For this reason, if you know a priori that 'to' has enough
available space to hold 'from', you don't need to check the
return value of mp_copy() for memory failure. The USED()
macro tells you how many digits are used by an mp_int, and
the ALLOC() macro tells you how many are allocated.
If you have two initialized mp_int's, and you want to exchange their
values, use:
mp_exch(a, b)
This is better than using mp_copy() with a temporary, since it will
not (ever) touch the memory allocator -- it just swaps the exact
contents of the two structures. The mp_exch() function cannot fail;
if you pass it an invalid structure, it just ignores it, and does
nothing.
Basic Arithmetic
----------------
Once you have initialized your integers, you can operate on them. The
basic arithmetic functions on full mp_int values are:
mp_add(a, b, c) - computes c = a + b
mp_sub(a, b, c) - computes c = a - b
mp_mul(a, b, c) - computes c = a * b
mp_sqr(a, b) - computes b = a * a
mp_div(a, b, q, r) - computes q, r such that a = bq + r
mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d
mp_expt(a, b, c) - computes c = a ** b
mp_2expt(a, k) - computes a = 2^k
mp_sqrt(a, c) - computes c = floor(sqrt(a))
The mp_div_2d() function efficiently computes division by powers of
two. Either the q or r parameter may be NULL, in which case that
portion of the computation will be discarded.
The algorithms used for some of the computations here are described in
the following files which are included with this distribution:
mul.txt Describes the multiplication algorithm
div.txt Describes the division algorithm
expt.txt Describes the exponentiation algorithm
sqrt.txt Describes the square-root algorithm
square.txt Describes the squaring algorithm
There are single-digit versions of most of these routines, as well.
In the following prototypes, 'd' is a single mp_digit:
mp_add_d(a, d, c) - computes c = a + d
mp_sub_d(a, d, c) - computes c = a - d
mp_mul_d(a, d, c) - computes c = a * d
mp_mul_2(a, c) - computes c = a * 2
mp_div_d(a, d, q, r) - computes q, r such that a = bq + r
mp_div_2(a, c) - computes c = a / 2
mp_expt_d(a, d, c) - computes c = a ** d
The mp_mul_2() and mp_div_2() functions take advantage of the internal
representation of an mp_int to do multiplication by two more quickly
than mp_mul_d() would. Other basic functions of an arithmetic variety
include:
mp_zero(a) - assign 0 to a
mp_neg(a, c) - negate a: c = -a
mp_abs(a, c) - absolute value: c = |a|
Comparisons
-----------
Several comparison functions are provided. Each of these, unless
otherwise specified, returns zero if the comparands are equal, < 0 if
the first is less than the second, and > 0 if the first is greater
than the second:
mp_cmp_z(a) - compare a <=> 0
mp_cmp_d(a, d) - compare a <=> d, d is a single digit
mp_cmp(a, b) - compare a <=> b
mp_cmp_mag(a, b) - compare |a| <=> |b|
mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer
mp_isodd(a) - return nonzero if odd, zero otherwise
mp_iseven(a) - return nonzero if even, zero otherwise
Modular Arithmetic
------------------
Modular variations of the basic arithmetic functions are also
supported. These are available if the MP_MODARITH parameter in
mpi-config.h is turned on (it is by default). The modular arithmetic
functions are:
mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m
mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below)
mp_addmod(a, b, m, c) - compute c = (a + b) mod m
mp_submod(a, b, m, c) - compute c = (a - b) mod m
mp_mulmod(a, b, m, c) - compute c = (a * b) mod m
mp_sqrmod(a, m, c) - compute c = (a * a) mod m
mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m
mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m
The mp_sqr() function squares its input argument. A call to mp_sqr(a,
c) is identical in meaning to mp_mul(a, a, c); however, if the
MP_SQUARE variable is set true in mpi-config.h (see below), then it
will be implemented with a different algorithm, that is supposed to
take advantage of the redundant computation that takes place during
squaring. Unfortunately, some compilers result in worse performance
on this code, so you can change the behaviour at will. There is a
utility program "mulsqr.c" that lets you test which does better on
your system.
The mp_sqrmod() function is analogous to the mp_sqr() function; it
uses the mp_sqr() function rather than mp_mul(), and then performs the
modular reduction. This probably won't help much unless you are doing
a lot of them.
See the file 'square.txt' for a synopsis of the algorithm used.
Note: The mp_mod_d() function computes a modular reduction around
---- a single digit d. The result is a single digit c.
Because an inverse is defined for a (mod m) if and only if (a, m) = 1
(that is, if a and m are relatively prime), mp_invmod() may not be
able to compute an inverse for the arguments. In this case, it
returns the value MP_UNDEF, and does not modify c. If an inverse is
defined, however, it returns MP_OKAY, and sets c to the value of the
inverse (mod m).
See the file 'redux.txt' for a description of the modular reduction
algorithm used by mp_exptmod().
Greatest Common Divisor
-----------------------
If The greates common divisor of two values can be found using one of the
following functions:
mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm
mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b)
mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b)
Also provided is a function to compute modular inverses, if they
exist:
mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists
The function mp_xgcd() computes the greatest common divisor, and also
returns values of x and y satisfying Bezout's identity. This is used
by mp_invmod() to find modular inverses. However, if you do not need
these values, you will find that mp_gcd() is MUCH more efficient,
since it doesn't need all the intermediate values that mp_xgcd()
requires in order to compute x and y.
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
algorithm due to Josef Stein.
Input & Output Functions
------------------------
The following basic I/O routines are provided. These are present at
all times:
mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
digits
mp_toraw(mp, str) - convert an mp_int to a string of bytes
mp_tovalue(ch, r) - convert ch to its value when taken as
a radix r digit, or -1 if invalid
mp_strerror(err) - get a string describing mp_err value 'err'
If you compile the MPI library with MP_IOFUNC defined, you will also
have access to the following additional I/O function:
mp_print(mp, ofp) - print an mp_int as text to output stream ofp
Note that mp_radix_size() returns a size in bytes guaranteed to be AT
LEAST big enough for the digits output by mp_toradix(). Because it
uses an approximation technique to figure out how many digits will be
needed, it may return a figure which is larger than necessary. Thus,
the caller should not rely on the value to determine how many bytes
will actually be written by mp_toradix(). The string mp_toradix()
creates will be NUL terminated, so the standard C library function
strlen() should be able to ascertain this for you, if you need it.
The mp_read_radix() and mp_toradix() functions support bases from 2 to
64 inclusive. If you require more general radix conversion facilities
than this, you will need to write them yourself (that's why mp_div_d()
is provided, after all).
Note: mp_read_radix() will accept as digits either capital or
---- lower-case letters. However, the current implementation of
mp_toradix() only outputs upper-case letters, when writing
bases betwee 10 and 36. The underlying code supports using
lower-case letters, but the interface stub does not have a
selector for it. You can add one yourself if you think it
is worthwhile -- I do not. Bases from 36 to 64 use lower-
case letters as distinct from upper-case. Bases 63 and
64 use the characters '+' and '/' as digits.
Note also that compiling with MP_IOFUNC defined will cause
inclusion of <stdio.h>, so if you are trying to write code
which does not depend on the standard C library, you will
probably want to avoid this option. This is needed because
the mp_print() function takes a standard library FILE * as
one of its parameters, and uses the fprintf() function.
The mp_toraw() function converts the integer to a sequence of bytes,
in big-endian ordering (most-significant byte first). Assuming your
bytes are 8 bits wide, this corresponds to base 256. The sign is
encoded as a single leading byte, whose value is 0 for zero or
positive values, or 1 for negative values. The mp_read_raw() function
reverses this process -- it takes a buffer of bytes, interprets the
first as a sign indicator (0 = zero/positive, nonzero = negative), and
the rest as a sequence of 1-byte digits in big-endian ordering.
The mp_raw_size() function returns the exact number of bytes required
to store the given integer in "raw" format (as described in the
previous paragraph). Zero is returned in case of error; a valid
integer will require at least three bytes of storage.
In previous versions of the MPI library, an "external representation
format" was supported. This was removed, however, because I found I
was never using it, it was not as portable as I would have liked, and
I decided it was a waste of space.
Other Functions
---------------
The files 'mpprime.h' and 'mpprime.c' define some routines which are
useful for divisibility testing and probabilistic primality testing.
The routines defined are:
mpp_divis(a, b) - is a divisible by b?
mpp_divis_d(a, d) - is a divisible by digit d?
mpp_random(a) - set a to random value at current precision
mpp_random_size(a, prec) - set a to random value at given precision
Note: The mpp_random() and mpp_random_size() functions use the C
---- library's rand() function to generate random values. It is
up to the caller to seed this generator before it is called.
These functions are not suitable for generating quantities
requiring cryptographic-quality randomness; they are intended
primarily for use in primality testing.
Note too that the MPI library does not call srand(), so your
application should do this, if you ever want the sequence
to change.
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
in v? If so, let w be the index of
that digit
mpp_divis_primes(a, np) - is a divisible by any of the first np
primes? If so, set np to the prime
which divided a.
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
returns MP_YES, otherwise MP_NO.
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
Miller probabilistic primality test
on a. Returns MP_YES if all tests
passed, or MP_NO if any test fails.
The mpp_fermat() function works based on Fermat's little theorem, a
consequence of which is that if p is a prime, and (w, p) = 1, then:
w^p = w (mod p)
Put another way, if w^p != w (mod p), then p is not prime. The test
is expensive to compute, but it helps to quickly eliminate an enormous
class of composite numbers prior to Rabin-Miller testing.
Building the Library
--------------------
The MPI library is designed to be as self-contained as possible. You
should be able to compile it with your favourite ANSI C compiler, and
link it into your program directly. If you are on a Unix system using
the GNU C compiler (gcc), the following should work:
% gcc -ansi -pedantic -Wall -O2 -c mpi.c
The file 'mpi-config.h' defines several configurable parameters for
the library, which you can adjust to suit your application. At the
time of this writing, the available options are:
MP_IOFUNC - Define true to include the mp_print() function,
which is moderately useful for debugging. This
implicitly includes <stdio.h>.
MP_MODARITH - Define true to include the modular arithmetic
functions. If you don't need modular arithmetic
in your application, you can set this to zero to
leave out all the modular routines.
MP_NUMTH - Define true to include number theoretic functions
such as mp_gcd(), mp_lcm(), and mp_invmod().
MP_LOGTAB - If true, the file "logtab.h" is included, which
is basically a static table of base 2 logarithms.
These are used to compute how big the buffers for
radix conversion need to be. If you set this false,
the library includes <math.h> and uses log(). This
typically forces you to link against math libraries.
MP_MEMSET - If true, use memset() to zero buffers. If you run
into weird alignment related bugs, set this to zero
and an explicit loop will be used.
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
into weird alignment bugs, set this to zero and an
explicit loop will be used.
MP_CRYPTO - If true, whenever arrays of digits are free'd, they
are zeroed first. This is useful if you're using
the library in a cryptographic environment; however,
it does add overhead to each free operation. For
performance, if you don't care about zeroing your
buffers, set this to false.
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
checking macro, ARGCHK(), gets expanded. If this
is set to zero, ARGCHK() expands to nothing; no
argument checks are performed. If this is 1, the
ARGCHK() macro expands to code that returns MP_BADARG
or similar at runtime. If it is 2, ARGCHK() expands
to an assert() call that aborts the program on a
bad input.
MP_DEBUG - Turns on debugging output. This is probably not at
all useful unless you are debugging the library. It
tends to spit out a LOT of output.
MP_DEFPREC - The default precision of a newly-created mp_int, in
digits. The precision can be changed at runtime by
the mp_set_prec() function, but this is its initial
value.
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
function will use an alternate algorithm that takes
advantage of the redundant inner product computation
when both multiplicands are identical. Unfortunately,
with some compilers this is actually SLOWER than just
calling mp_mul() with the same argument twice. So
if you set MP_SQUARE to zero, mp_sqr() will be expan-
ded into a call to mp_mul(). This applies to all
the uses of mp_sqr(), including mp_sqrmod() and the
internal calls to s_mp_sqr() inside mpi.c
The program 'mulsqr' (mulsqr.c) can be used to test
which works best for your configuration. Set up the
CC and CFLAGS variables in the Makefile, then type:
make mulsqr
Invoke it with arguments similar to the following:
mulsqr 25000 1024
That is, 25000 products computed on 1024-bit values.
The output will compare the two timings, and recommend
a setting for MP_SQUARE. It is off by default.
If you would like to use the mp_print() function (see above), be sure
to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the
'tests' subdirectory expect this to be defined (although the test
driver 'mpi-test' doesn't need it)
The Makefile which comes with the library should take care of building
the library for you, if you have set the CC and CFLAGS variables at
the top of the file appropriately. By default, they are set up to
use the GNU C compiler:
CC=gcc
CFLAGS=-ansi -pedantic -Wall -O2
If all goes well, the library should compile without warnings using
this combination. You should, of course, make whatever adjustments
you find necessary.
The MPI library distribution comes with several additional programs
which are intended to demonstrate the use of the library, and provide
a framework for testing it. There are a handful of test driver
programs, in the files named 'mptest-X.c', where X is a digit. Also,
there are some simple command-line utilities (in the 'utils'
directory) for manipulating large numbers. These include:
basecvt.c A radix-conversion program, supporting bases from
2 to 64 inclusive.
bbsrand.c A BBS (quadratic residue) pseudo-random number
generator. The file 'bbsrand.c' is just the driver
for the program; the real code lives in the files
'bbs_rand.h' and 'bbs_rand.c'
dec2hex.c Converts decimal to hexadecimal
gcd.c Computes the greatest common divisor of two values.
If invoked as 'xgcd', also computes constants x and
y such that (a, b) = ax + by, in accordance with
Bezout's identity.
hex2dec.c Converts hexadecimal to decimal
invmod.c Computes modular inverses
isprime.c Performs the Rabin-Miller probabilistic primality
test on a number. Values which fail this test are
definitely composite, and those which pass are very
likely to be prime (although there are no guarantees)
lap.c Computes the order (least annihilating power) of
a value v modulo m. Very dumb algorithm.
primegen.c Generates large (probable) primes.
prng.c A pseudo-random number generator based on the
BBS generator code in 'bbs_rand.c'
sieve.c Implements the Sieve of Eratosthenes, using a big
bitmap, to generate a list of prime numbers.
fact.c Computes the factorial of an arbitrary precision
integer (iterative).
exptmod.c Computes arbitrary precision modular exponentiation
from the command line (exptmod a b m -> a^b (mod m))
Most of these can be built from the Makefile that comes with the
library. Try 'make tools', if your environment supports it. (If you
are compiling on a Macintosh, I'm afraid you'll have to build them by
hand -- fortunately, this is not difficult -- the library itself
should compile just fine under Metrowerks CodeWarrior).
Testing the Library
-------------------
Automatic test vectors are included, in the form of a program called
'mpi-test'. To build this program and run all the tests, simply
invoke the shell script 'all-tests'. If all the tests pass, you
should see a message:
All tests passed
If something went wrong, you'll get:
One or more tests failed.
If this happens, scan back through the preceding lines, to see which
test failed. Any failure indicates a bug in the library, which needs
to be fixed before it will give accurate results. If you get any such
thing, please let me know, and I'll try to fix it. Please let me know
what platform and compiler you were using, as well as which test
failed. If a reason for failure was given, please send me that text
as well.
If you're on a system such as the Macintosh, where the standard Unix
build tools don't work, you can build the 'mpi-test' program manually,
and run it by hand. This is tedious and obnoxious, sorry.
Further manual testing can be performed by building the manual testing
programs, whose source is found in the 'tests' subdirectory. Each
test is in a source file called 'mptest-X.c'. The Makefile contains a
target to build all of them at once:
make tests
Read the comments at the top of each source file to see what the
driver is supposed to test. You probably don't need to do this; these
programs were only written to help me as I was developing the library.
The relevant files are:
mpi-test.c The source for the test driver
make-test-arrays A Perl script to generate some of the internal
data structures used by mpi-test.c
test-arrays.txt The source file for make-test-arrays
all-tests A Bourne shell script which runs all the
tests in the mpi-test suite
Running 'make mpi-test' should build the mpi-test program. If you
cannot use make, here is what needs to be done:
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
the 'test-arrays.txt' file. Since Perl can be found everywhere,
even on the Macintosh, this should be no trouble. Under Unix,
this looks like:
make-test-arrays test-arrays.txt > test-info.c
(2) Build the MPI library:
gcc -ansi -pedantic -Wall -c mpi.c
(3) Build the mpi-test program:
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
When you've got mpi-test, you can use 'all-tests' to run all the tests
made available by mpi-test. If any of them fail, there should be a
diagnostic indicating what went wrong. These are fairly high-level
diagnostics, and won't really help you debug the problem; they're
simply intended to help you isolate which function caused the problem.
If you encounter a problem of this sort, feel free to e-mail me, and I
will certainly attempt to help you debug it.
Note: Several of the tests hard-wired into 'mpi-test' operate under
---- the assumption that you are using at least a 16-bit mp_digit
type. If that is not true, several tests might fail, because
of range problems with the maximum digit value.
If you are using an 8-bit digit, you will also need to
modify the code for mp_read_raw(), which assumes that
multiplication by 256 can be done with mp_mul_d(), a
fact that fails when DIGIT_MAX is 255. You can replace
the call with s_mp_lshd(), which will give you the same
effect, and without doing as much work. :)
Acknowledgements:
----------------
The algorithms used in this library were drawn primarily from Volume
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
Cryptography_, Chapter 14.
Thanks are due to Tom St. Denis, for finding an obnoxious sign-related
bug in mp_read_raw() that made things break on platforms which use
signed chars.
About the Author
----------------
This software was written by Michael J. Fromberger. You can contact
the author as follows:
E-mail: <sting@linguist.dartmouth.edu>
Postal: 8000 Cummings Hall, Thayer School of Engineering
Dartmouth College, Hanover, New Hampshire, USA
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
Last updated: 16-Jan-2000

View File

@ -0,0 +1,111 @@
#!/bin/sh
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
## All Rights Reserved.
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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.
ECHO=/bin/echo
$ECHO "\n** Running unit tests for MPI library\n"
# Build the mpi-test program, which comprises all the unit tests for
# the MPI library...
$ECHO "Bringing mpi-test up to date ... "
if make mpi-test ; then
:
else
$ECHO " "
$ECHO "Make failed to build mpi-test."
$ECHO " "
exit 1
fi
if [ ! -x mpi-test ] ; then
$ECHO " "
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
$ECHO " "
exit 1
fi
# Get the list of available test suites...
tests=`mpi-test list | awk '{print $1}'`
errs=0
# Run each test suite and check the result code of mpi-test
for test in $tests ; do
$ECHO "$test ... \c"
if mpi-test $test ; then
$ECHO "passed"
else
$ECHO "FAILED"
errs=1
fi
done
# If any tests failed, we'll stop at this point
if [ "$errs" = "0" ] ; then
$ECHO "All unit tests passed"
else
$ECHO "One or more tests failed"
exit 1
fi
# Now try to build the 'pi' program, and see if it can compute the
# first thousand digits of pi correctly
$ECHO "\n** Running other tests\n"
$ECHO "Bringing 'pi' up to date ... "
if make pi ; then
:
else
$ECHO "\nMake failed to build pi.\n"
exit 1
fi
if [ ! -x pi ] ; then
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
exit 1
fi
./pi 2000 > /tmp/pi.tmp.$$
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
$ECHO "Okay! The pi test passes."
else
$ECHO "Oops! The pi test failed. :("
exit 1
fi
rm -f /tmp/pi.tmp.$$
exit 0
# Here there be dragons

View File

@ -0,0 +1,11 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
basecvt.pod
gcd.pod
invmod.pod
isprime.pod
lap.pod
mpi-test.pod
prime.txt
prng.pod

View File

@ -0,0 +1,32 @@
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the Netscape security libraries.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1994-2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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.

View File

@ -0,0 +1,63 @@
=head1 NAME
basecvt - radix conversion for arbitrary precision integers
=head1 SYNOPSIS
basecvt <ibase> <obase> [values]
=head1 DESCRIPTION
The B<basecvt> program is a command-line tool for converting integers
of arbitrary precision from one radix to another. The current version
supports radix values from 2 (binary) to 64, inclusive. The first two
command line arguments specify the input and output radix, in base 10.
Any further arguments are taken to be integers notated in the input
radix, and these are converted to the output radix. The output is
written, one integer per line, to standard output.
When reading integers, only digits considered "valid" for the input
radix are considered. Processing of an integer terminates when an
invalid input digit is encountered. So, for example, if you set the
input radix to 10 and enter '10ACF', B<basecvt> would assume that you
had entered '10' and ignore the rest of the string.
If no values are provided, no output is written, but the program
simply terminates with a zero exit status. Error diagnostics are
written to standard error in the event of out-of-range radix
specifications. Regardless of the actual values of the input and
output radix, the radix arguments are taken to be in base 10 (decimal)
notation.
=head1 DIGITS
For radices from 2-10, standard ASCII decimal digits 0-9 are used for
both input and output. For radices from 11-36, the ASCII letters A-Z
are also included, following the convention used in hexadecimal. In
this range, input is accepted in either upper or lower case, although
on output only lower-case letters are used.
For radices from 37-62, the output includes both upper- and lower-case
ASCII letters, and case matters. In this range, case is distinguished
both for input and for output values.
For radices 63 and 64, the characters '+' (plus) and '/' (forward
solidus) are also used. These are derived from the MIME base64
encoding scheme. The overall encoding is not the same as base64,
because the ASCII digits are used for the bottom of the range, and the
letters are shifted upward; however, the output will consist of the
same character set.
This input and output behaviour is inherited from the MPI library used
by B<basecvt>, and so is not configurable at runtime.
=head1 SEE ALSO
dec2hex(1), hex2dec(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:31 $

View File

@ -0,0 +1,61 @@
#!/bin/sh
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: build,v 1.1 2000-07-14 00:44:31 nelsonb%netscape.com Exp $
##
VERS="1.7p6"
SECT="1"
NAME="MPI Tools"
echo "Building manual pages ..."
case $# in
0)
files=`ls *.pod`
;;
*)
files=$*
;;
esac
for name in $files
do
echo -n "$name ... "
sname=`noext $name`
pod2man --section="$SECT" --center="$NAME" --release="$VERS" $name > $sname.$SECT
echo "(done)"
done
echo "Finished building."

View File

@ -0,0 +1,96 @@
Division
This describes the division algorithm used by the MPI library.
Input: a, b; a > b
Compute: Q, R; a = Qb + R
The input numbers are normalized so that the high-order digit of b is
at least half the radix. This guarantees that we have a reasonable
way to guess at the digits of the quotient (this method was taken from
Knuth, vol. 2, with adaptations).
To normalize, test the high-order digit of b. If it is less than half
the radix, multiply both a and b by d, where:
radix - 1
d = -----------
bmax + 1
...where bmax is the high-order digit of b. Otherwise, set d = 1.
Given normalize values for a and b, let the notation a[n] denote the
nth digit of a. Let #a be the number of significant figures of a (not
including any leading zeroes).
Let R = 0
Let p = #a - 1
while(p >= 0)
do
R = (R * radix) + a[p]
p = p - 1
while(R < b and p >= 0)
if(R < b)
break
q = (R[#R - 1] * radix) + R[#R - 2]
q = q / b[#b - 1]
T = b * q
while(T > L)
q = q - 1
T = T - b
endwhile
L = L - T
Q = (Q * radix) + q
endwhile
At this point, Q is the quotient, and R is the normalized remainder.
To denormalize R, compute:
R = (R / d)
At this point, you are finished.
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: div.txt,v 1.1 2000-07-14 00:44:32 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,127 @@
Exponentiation
For exponentiation, the MPI library uses a simple and fairly standard
square-and-multiply method. The algorithm is this:
Input: a, b
Output: a ** b
s = 1
while(b != 0)
if(b is odd)
s = s * a
endif
b = b / 2
x = x * x
endwhile
return s
The modular exponentiation is done the same way, except replacing:
s = s * a
with
s = (s * a) mod m
and replacing
x = x * x
with
x = (x * x) mod m
Here is a sample exponentiation using the MPI library, as compared to
the same problem solved by the Unix 'bc' program on my system:
Computation of 2,381,283 ** 235
'bc' says:
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
CFFF2E1AC93F3CA264A1B
MPI says:
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
CFFF2E1AC93F3CA264A1B
Diff says:
% diff bc.txt mp.txt
%
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: expt.txt,v 1.1 2000-07-14 00:44:32 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,27 @@
=head1 NAME
gcd - compute greatest common divisor of two integers
=head1 SYNOPSIS
gcd <a> <b>
=head1 DESCRIPTION
The B<gcd> program computes the greatest common divisor of two
arbitrary-precision integers I<a> and I<b>. The result is written in
standard decimal notation to the standard output.
If I<b> is zero, B<gcd> will print an error message and exit.
=head1 SEE ALSO
invmod(1), isprime(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:32 $

View File

@ -0,0 +1,33 @@
=head1 NAME
invmod - compute modular inverse of an integer
=head1 SYNOPSIS
invmod <a> <m>
=head1 DESCRIPTION
The B<invmod> program computes the inverse of I<a>, modulo I<m>, if
that inverse exists. Both I<a> and I<m> are arbitrary-precision
integers in decimal notation. The result is written in standard
decimal notation to the standard output.
If there is no inverse, the message:
No inverse
...will be printed to the standard output (an inverse exists if and
only if the greatest common divisor of I<a> and I<m> is 1).
=head1 SEE ALSO
gcd(1), isprime(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:33 $

View File

@ -0,0 +1,62 @@
=head1 NAME
isprime - probabilistic primality testing
=head1 SYNOPSIS
isprime <a>
=head1 DESCRIPTION
The B<isprime> program attempts to determine whether the arbitrary
precision integer I<a> is prime. It first tests I<a> for divisibility
by the first 170 or so small primes, and assuming I<a> is not
divisible by any of these, applies 15 iterations of the Rabin-Miller
probabilistic primality test.
If the program discovers that the number is composite, it will print:
Not prime (reason)
Where I<reason> is either:
divisible by small prime x
Or:
failed nth pseudoprime test
In the first case, I<x> indicates the first small prime factor that
was found. In the second case, I<n> indicates which of the
pseudoprime tests failed (numbered from 1)
If this happens, the number is definitely not prime. However, if the
number succeeds, this message results:
Probably prime, 1 in 4^15 chance of false positive
If this happens, the number is prime with very high probability, but
its primality has not been absolutely proven, only demonstrated to a
very convincing degree.
The value I<a> can be input in standard decimal notation, or, if it is
prefixed with I<Ox>, it will be read as hexadecimal.
=head1 ENVIRONMENT
You can control how many iterations of Rabin-Miller are performed on
the candidate number by setting the I<RM_TESTS> environment variable
to an integer value before starting up B<isprime>. This will change
the output slightly if the number passes all the tests.
=head1 SEE ALSO
gcd(1), invmod(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:33 $

View File

@ -0,0 +1,35 @@
=head1 NAME
lap - compute least annihilating power of a number
=head1 SYNOPSIS
lap <a> <m>
=head1 DESCRIPTION
The B<lap> program computes the order of I<a> modulo I<m>, for
arbitrary precision integers I<a> and I<m>. The B<order> of I<a>
modulo I<m> is defined as the smallest positive value I<n> for which
I<a> raised to the I<n>th power, modulo I<m>, is equal to 1. The
order may not exist, if I<m> is composite.
=head1 RESTRICTIONS
This program is very slow, especially for large moduli. It is
intended as a way to help find primitive elements in a modular field,
but it does not do so in a particularly inefficient manner. It was
written simply to help verify that a particular candidate does not
have an obviously short cycle mod I<m>.
=head1 SEE ALSO
gcd(1), invmod(1), isprime(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:34 $

View File

@ -0,0 +1,49 @@
=head1 NAME
mpi-test - automated test program for MPI library
=head1 SYNOPSIS
mpi-test <suite-name> [quiet]
mpi-test list
mpi-test help
=head1 DESCRIPTION
The B<mpi-test> program is a general unit test driver for the MPI
library. It is used to verify that the library works as it is
supposed to on your architecture. As with most such things, passing
all the tests in B<mpi-test> does not guarantee the code is correct,
but if any of them fail, there are certainly problems.
Each major function of the library can be tested individually. For a
list of the test suites understood by B<mpi-test>, run it with the
I<list> command line option:
mpi-test list
This will display a list of the available test suites and a brief
synopsis of what each one does. For a brief overview of this
document, run B<mpi-test> I<help>.
B<mpi-test> exits with a zero status if the selected test succeeds, or
a nonzero status if it fails. If a I<suite-name> which is not
understood by B<mpi-test> is given, a diagnostic is printed to the
standard error, and the program exits with a result code of 2. If a
test fails, the result code will be 1, and a diagnostic is ordinarily
printed to the standard error. However, if the I<quiet> option is
provided, these diagnostics will be suppressed.
=head1 RESTRICTIONS
Only a few canned test cases are provided. The solutions have been
verified using the GNU bc(1) program, so bugs there may cause problems
here; however, this is very unlikely, so if a test fails, it is almost
certainly my fault, not bc(1)'s.
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:34 $

View File

@ -0,0 +1,109 @@
Multiplication
This describes the multiplication algorithm used by the MPI library.
This is basically a standard "schoolbook" algorithm. It is slow --
O(mn) for m = #a, n = #b -- but easy to implement and verify.
Basically, we run two nested loops, as illustrated here (R is the
radix):
k = 0
for j <- 0 to (#b - 1)
for i <- 0 to (#a - 1)
w = (a[j] * b[i]) + k + c[i+j]
c[i+j] = w mod R
k = w div R
endfor
c[i+j] = k;
k = 0;
endfor
It is necessary that 'w' have room for at least two radix R digits.
The product of any two digits in radix R is at most:
(R - 1)(R - 1) = R^2 - 2R + 1
Since a two-digit radix-R number can hold R^2 - 1 distinct values,
this insures that the product will fit into the two-digit register.
To insure that two digits is enough for w, we must also show that
there is room for the carry-in from the previous multiplication, and
the current value of the product digit that is being recomputed.
Assuming each of these may be as big as R - 1 (and no larger,
certainly), two digits will be enough if and only if:
(R^2 - 2R + 1) + 2(R - 1) <= R^2 - 1
Solving this equation shows that, indeed, this is the case:
R^2 - 2R + 1 + 2R - 2 <= R^2 - 1
R^2 - 1 <= R^2 - 1
This suggests that a good radix would be one more than the largest
value that can be held in half a machine word -- so, for example, as
in this implementation, where we used a radix of 65536 on a machine
with 4-byte words. Another advantage of a radix of this sort is that
binary-level operations are easy on numbers in this representation.
Here's an example multiplication worked out longhand in radix-10,
using the above algorithm:
a = 999
b = x 999
-------------
p = 98001
w = (a[jx] * b[ix]) + kin + c[ix + jx]
c[ix+jx] = w % RADIX
k = w / RADIX
product
ix jx a[jx] b[ix] kin w c[i+j] kout 000000
0 0 9 9 0 81+0+0 1 8 000001
0 1 9 9 8 81+8+0 9 8 000091
0 2 9 9 8 81+8+0 9 8 000991
8 0 008991
1 0 9 9 0 81+0+9 0 9 008901
1 1 9 9 9 81+9+9 9 9 008901
1 2 9 9 9 81+9+8 8 9 008901
9 0 098901
2 0 9 9 0 81+0+9 0 9 098001
2 1 9 9 9 81+9+8 8 9 098001
2 2 9 9 9 81+9+9 9 9 098001
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: mul.txt,v 1.1 2000-07-14 00:44:35 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,85 @@
This file describes how pi is computed by the program in 'pi.c' (see
the utils subdirectory).
Basically, we use Machin's formula, which is what everyone in the
world uses as a simple method for computing approximations to pi.
This works for up to a few thousand digits without too much effort.
Beyond that, though, it gets too slow.
Machin's formula states:
pi := 16 * arctan(1/5) - 4 * arctan(1/239)
We compute this in integer arithmetic by first multiplying everything
through by 10^d, where 'd' is the number of digits of pi we wanted to
compute. It turns out, the last few digits will be wrong, but the
number that are wrong is usually very small (ordinarly only 2-3).
Having done this, we compute the arctan() function using the formula:
1 1 1 1 1
arctan(1/x) := --- - ----- + ----- - ----- + ----- - ...
x 3 x^3 5 x^5 7 x^7 9 x^9
This is done iteratively by computing the first term manually, and
then iteratively dividing x^2 and k, where k = 3, 5, 7, ... out of the
current figure. This is then added to (or subtracted from) a running
sum, as appropriate. The iteration continues until we overflow our
available precision and the current figure goes to zero under integer
division. At that point, we're finished.
Actually, we get a couple extra bits of precision out of the fact that
we know we're computing y * arctan(1/x), by setting up the multiplier
as:
y * 10^d
... instead of just 10^d. There is also a bit of cleverness in how
the loop is constructed, to avoid special-casing the first term.
Check out the code for arctan() in 'pi.c', if you are interested in
seeing how it is set up.
Thanks to Jason P. for this algorithm, which I assembled from notes
and programs found on his cool "Pile of Pi Programs" page, at:
http://www.isr.umd.edu/~jasonp/pipage.html
Thanks also to Henrik Johansson <Henrik.Johansson@Nexus.Comm.SE>, from
whose pi program I borrowed the clever idea of pre-multiplying by x in
order to avoid a special case on the loop iteration.
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: pi.txt,v 1.1 2000-07-14 00:44:35 nelsonb%netscape.com Exp $

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
=head1 NAME
prng - pseudo-random number generator
=head1 SYNOPSIS
prng [count]
=head1 DESCRIPTION
B<Prng> generates 32-bit pseudo-random integers using the
Blum-Blum-Shub (BBS) quadratic residue generator. It is seeded using
the standard C library's rand() function, which itself seeded from the
system clock and the process ID number. Thus, the values generated
are not particularly useful for cryptographic applications, but they
are in general much better than the typical output of the usual
multiplicative congruency generator used by most runtime libraries.
You may optionally specify how many random values should be generated
by giving a I<count> argument on the command line. If you do not
specify a count, only one random value will be generated. The results
are output to the standard output in decimal notation, one value per
line.
=head1 RESTRICTIONS
As stated above, B<prng> uses the C library's rand() function to seed
the generator, so it is not terribly suitable for cryptographic
applications. Also note that each time you run the program, a new
seed is generated, so it is better to run it once with a I<count>
parameter than it is to run it multiple times to generate several
values.
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
Thayer School of Engineering, Dartmouth College, Hanover, NH USA
$Date: 2000-07-14 00:44:36 $

View File

@ -0,0 +1,118 @@
Modular Reduction
Usually, modular reduction is accomplished by long division, using the
mp_div() or mp_mod() functions. However, when performing modular
exponentiation, you spend a lot of time reducing by the same modulus
again and again. For this purpose, doing a full division for each
multiplication is quite inefficient.
For this reason, the mp_exptmod() function does not perform modular
reductions in the usual way, but instead takes advantage of an
algorithm due to Barrett, as described by Menezes, Oorschot and
VanStone in their book _Handbook of Applied Cryptography_, published
by the CRC Press (see Chapter 14 for details). This method reduces
most of the computation of reduction to efficient shifting and masking
operations, and avoids the multiple-precision division entirely.
Here is a brief synopsis of Barrett reduction, as it is implemented in
this library.
Let b denote the radix of the computation (one more than the maximum
value that can be denoted by an mp_digit). Let m be the modulus, and
let k be the number of significant digits of m. Let x be the value to
be reduced modulo m. By the Division Theorem, there exist unique
integers Q and R such that:
x = Qm + R, 0 <= R < m
Barrett reduction takes advantage of the fact that you can easily
approximate Q to within two, given a value M such that:
2k
b
M = floor( ----- )
m
Computation of M requires a full-precision division step, so if you
are only doing a single reduction by m, you gain no advantage.
However, when multiple reductions by the same m are required, this
division need only be done once, beforehand. Using this, we can use
the following equation to compute Q', an approximation of Q:
x
floor( ------ ) M
k-1
b
Q' = floor( ----------------- )
k+1
b
The divisions by b^(k-1) and b^(k+1) and the floor() functions can be
efficiently implemented with shifts and masks, leaving only a single
multiplication to be performed to get this approximation. It can be
shown that Q - 2 <= Q' <= Q, so in the worst case, we can get out with
two additional subtractions to bring the value into line with the
actual value of Q.
Once we've got Q', we basically multiply that by m and subtract from
x, yielding:
x - Q'm = Qm + R - Q'm
Since we know the constraint on Q', this is one of:
R
m + R
2m + R
Since R < m by the Division Theorem, we can simply subtract off m
until we get a value in the correct range, which will happen with no
more than 2 subtractions:
v = x - Q'm
while(v >= m)
v = v - m
endwhile
In random performance trials, modular exponentiation using this method
of reduction gave around a 40% speedup over using the division for
reduction.
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: redux.txt,v 1.1 2000-07-14 00:44:36 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,82 @@
Square Root
A simple iterative algorithm is used to compute the greatest integer
less than or equal to the square root. Essentially, this is Newton's
linear approximation, computed by finding successive values of the
equation:
x[k]^2 - V
x[k+1] = x[k] - ------------
2 x[k]
...where V is the value for which the square root is being sought. In
essence, what is happening here is that we guess a value for the
square root, then figure out how far off we were by squaring our guess
and subtracting the target. Using this value, we compute a linear
approximation for the error, and adjust the "guess". We keep doing
this until the precision gets low enough that the above equation
yields a quotient of zero. At this point, our last guess is one
greater than the square root we're seeking.
The initial guess is computed by dividing V by 4, which is a heuristic
I have found to be fairly good on average. This also has the
advantage of being very easy to compute efficiently, even for large
values.
So, the resulting algorithm works as follows:
x = V / 4 /* compute initial guess */
loop
t = (x * x) - V /* Compute absolute error */
u = 2 * x /* Adjust by tangent slope */
t = t / u
/* Loop is done if error is zero */
if(t == 0)
break
/* Adjust guess by error term */
x = x - t
end
x = x - 1
The result of the computation is the value of x.
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: sqrt.txt,v 1.1 2000-07-14 00:44:37 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,104 @@
Squaring Algorithm
When you are squaring a value, you can take advantage of the fact that
half the multiplications performed by the more general multiplication
algorithm (see 'mul.txt' for a description) are redundant when the
multiplicand equals the multiplier.
In particular, the modified algorithm is:
k = 0
for j <- 0 to (#a - 1)
w = c[2*j] + (a[j] ^ 2);
k = w div R
for i <- j+1 to (#a - 1)
w = (2 * a[j] * a[i]) + k + c[i+j]
c[i+j] = w mod R
k = w div R
endfor
c[i+j] = k;
k = 0;
endfor
On the surface, this looks identical to the multiplication algorithm;
however, note the following differences:
- precomputation of the leading term in the outer loop
- i runs from j+1 instead of from zero
- doubling of a[i] * a[j] in the inner product
Unfortunately, the construction of the inner product is such that we
need more than two digits to represent the inner product, in some
cases. In a C implementation, this means that some gymnastics must be
performed in order to handle overflow, for which C has no direct
abstraction. We do this by observing the following:
If we have multiplied a[i] and a[j], and the product is more than half
the maximum value expressible in two digits, then doubling this result
will overflow into a third digit. If this occurs, we take note of the
overflow, and double it anyway -- C integer arithmetic ignores
overflow, so the two digits we get back should still be valid, modulo
the overflow.
Having doubled this value, we now have to add in the remainders and
the digits already computed by earlier steps. If we did not overflow
in the previous step, we might still cause an overflow here. That
will happen whenever the maximum value expressible in two digits, less
the amount we have to add, is greater than the result of the previous
step. Thus, the overflow computation is:
u = 0
w = a[i] * a[j]
if(w > (R - 1)/ 2)
u = 1;
w = w * 2
v = c[i + j] + k
if(u == 0 && (R - 1 - v) < w)
u = 1
If there is an overflow, u will be 1, otherwise u will be 0. The rest
of the parameters are the same as they are in the above description.
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: square.txt,v 1.1 2000-07-14 00:44:37 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,245 @@
MPI Library Timing Tests
Hardware/OS
(A) SGI O2 1 x MIPS R10000 250MHz IRIX 6.5.3
(B) IBM RS/6000 43P-240 1 x PowerPC 603e 223MHz AIX 4.3
(C) Dell GX1/L+ 1 x Pentium III 550MHz Linux 2.2.12-20
(D) PowerBook G3 1 x PowerPC 750 266MHz LinuxPPC 2.2.6-15apmac
(E) PowerBook G3 1 x PowerPC 750 266MHz MacOS 8.5.1
(F) PowerBook G3 1 x PowerPC 750 400MHz MacOS 9.0.2
Compiler
(1) MIPSpro C 7.2.1 -O3 optimizations
(2) GCC 2.95.1 -O3 optimizations
(3) IBM AIX xlc -O3 optimizations (version unknown)
(4) EGCS 2.91.66 -O3 optimizations
(5) Metrowerks CodeWarrior 5.0 C, all optimizations
(6) MIPSpro C 7.30 -O3 optimizations
(7) same as (6), with optimized libmalloc.so
Timings are given in seconds, computed using the C library's clock()
function. The first column gives the hardware and compiler
configuration used for the test. The second column indicates the
number of tests that were aggregated to get the statistics for that
size. These were compiled using 16 bit digits.
Source data were generated randomly using a fixed seed, so they should
be internally consistent, but may vary on different systems depending
on the C library. Also, since the resolution of the timer accessed by
clock() varies, there may be some variance in the precision of these
measurements.
Prime Generation (primegen)
128 bits:
A1 200 min=0.03, avg=0.19, max=0.72, sum=38.46
A2 200 min=0.02, avg=0.16, max=0.62, sum=32.55
B3 200 min=0.01, avg=0.07, max=0.22, sum=13.29
C4 200 min=0.00, avg=0.03, max=0.20, sum=6.14
D4 200 min=0.00, avg=0.05, max=0.33, sum=9.70
A6 200 min=0.01, avg=0.09, max=0.36, sum=17.48
A7 200 min=0.00, avg=0.05, max=0.24, sum=10.07
192 bits:
A1 200 min=0.05, avg=0.45, max=3.13, sum=89.96
A2 200 min=0.04, avg=0.39, max=2.61, sum=77.55
B3 200 min=0.02, avg=0.18, max=1.25, sum=36.97
C4 200 min=0.01, avg=0.09, max=0.33, sum=18.24
D4 200 min=0.02, avg=0.15, max=0.54, sum=29.63
A6 200 min=0.02, avg=0.24, max=1.70, sum=47.84
A7 200 min=0.01, avg=0.15, max=1.05, sum=30.88
256 bits:
A1 200 min=0.08, avg=0.92, max=6.13, sum=184.79
A2 200 min=0.06, avg=0.76, max=5.03, sum=151.11
B3 200 min=0.04, avg=0.41, max=2.68, sum=82.35
C4 200 min=0.02, avg=0.19, max=0.69, sum=37.91
D4 200 min=0.03, avg=0.31, max=1.15, sum=63.00
A6 200 min=0.04, avg=0.48, max=3.13, sum=95.46
A7 200 min=0.03, avg=0.37, max=2.36, sum=73.60
320 bits:
A1 200 min=0.11, avg=1.59, max=6.14, sum=318.81
A2 200 min=0.09, avg=1.27, max=4.93, sum=254.03
B3 200 min=0.07, avg=0.82, max=3.13, sum=163.80
C4 200 min=0.04, avg=0.44, max=1.91, sum=87.59
D4 200 min=0.06, avg=0.73, max=3.22, sum=146.73
A6 200 min=0.07, avg=0.93, max=3.50, sum=185.01
A7 200 min=0.05, avg=0.76, max=2.94, sum=151.78
384 bits:
A1 200 min=0.16, avg=2.69, max=11.41, sum=537.89
A2 200 min=0.13, avg=2.15, max=9.03, sum=429.14
B3 200 min=0.11, avg=1.54, max=6.49, sum=307.78
C4 200 min=0.06, avg=0.81, max=4.84, sum=161.13
D4 200 min=0.10, avg=1.38, max=8.31, sum=276.81
A6 200 min=0.11, avg=1.73, max=7.36, sum=345.55
A7 200 min=0.09, avg=1.46, max=6.12, sum=292.02
448 bits:
A1 200 min=0.23, avg=3.36, max=15.92, sum=672.63
A2 200 min=0.17, avg=2.61, max=12.25, sum=522.86
B3 200 min=0.16, avg=2.10, max=9.83, sum=420.86
C4 200 min=0.09, avg=1.44, max=7.64, sum=288.36
D4 200 min=0.16, avg=2.50, max=13.29, sum=500.17
A6 200 min=0.15, avg=2.31, max=10.81, sum=461.58
A7 200 min=0.14, avg=2.03, max=9.53, sum=405.16
512 bits:
A1 200 min=0.30, avg=6.12, max=22.18, sum=1223.35
A2 200 min=0.25, avg=4.67, max=16.90, sum=933.18
B3 200 min=0.23, avg=4.13, max=14.94, sum=825.45
C4 200 min=0.13, avg=2.08, max=9.75, sum=415.22
D4 200 min=0.24, avg=4.04, max=20.18, sum=808.11
A6 200 min=0.22, avg=4.47, max=16.19, sum=893.83
A7 200 min=0.20, avg=4.03, max=14.65, sum=806.02
Modular Exponentation (metime)
The following results are aggregated from 200 pseudo-randomly
generated tests, based on a fixed seed.
base, exponent, and modulus size (bits)
P/C 128 192 256 320 384 448 512 640 768 896 1024
------- -----------------------------------------------------------------
A1 0.015 0.027 0.047 0.069 0.098 0.133 0.176 0.294 0.458 0.680 1.040
A2 0.013 0.024 0.037 0.053 0.077 0.102 0.133 0.214 0.326 0.476 0.668
B3 0.005 0.011 0.021 0.036 0.056 0.084 0.121 0.222 0.370 0.573 0.840
C4 0.002 0.006 0.011 0.020 0.032 0.048 0.069 0.129 0.223 0.344 0.507
D4 0.004 0.010 0.019 0.034 0.056 0.085 0.123 0.232 0.390 0.609 0.899
E5 0.007 0.015 0.031 0.055 0.088 0.133 0.183 0.342 0.574 0.893 1.317
A6 0.008 0.016 0.038 0.042 0.064 0.093 0.133 0.239 0.393 0.604 0.880
A7 0.005 0.011 0.020 0.036 0.056 0.083 0.121 0.223 0.374 0.583 0.855
Multiplication and Squaring tests, (mulsqr)
The following results are aggregated from 500000 pseudo-randomly
generated tests, based on a per-run wall-clock seed. Times are given
in seconds, except where indicated in microseconds (us).
(A1)
bits multiply square ad percent time/mult time/square
64 9.33 9.15 > 1.9 18.7us 18.3us
128 10.88 10.44 > 4.0 21.8us 20.9us
192 13.30 11.89 > 10.6 26.7us 23.8us
256 14.88 12.64 > 15.1 29.8us 25.3us
320 18.64 15.01 > 19.5 37.3us 30.0us
384 23.11 17.70 > 23.4 46.2us 35.4us
448 28.28 20.88 > 26.2 56.6us 41.8us
512 34.09 24.51 > 28.1 68.2us 49.0us
640 47.86 33.25 > 30.5 95.7us 66.5us
768 64.91 43.54 > 32.9 129.8us 87.1us
896 84.49 55.48 > 34.3 169.0us 111.0us
1024 107.25 69.21 > 35.5 214.5us 138.4us
1536 227.97 141.91 > 37.8 456.0us 283.8us
2048 394.05 242.15 > 38.5 788.1us 484.3us
(A2)
bits multiply square ad percent time/mult time/square
64 7.87 7.95 < 1.0 15.7us 15.9us
128 9.40 9.19 > 2.2 18.8us 18.4us
192 11.15 10.59 > 5.0 22.3us 21.2us
256 12.02 11.16 > 7.2 24.0us 22.3us
320 14.62 13.43 > 8.1 29.2us 26.9us
384 17.72 15.80 > 10.8 35.4us 31.6us
448 21.24 18.51 > 12.9 42.5us 37.0us
512 25.36 21.78 > 14.1 50.7us 43.6us
640 34.57 29.00 > 16.1 69.1us 58.0us
768 46.10 37.60 > 18.4 92.2us 75.2us
896 58.94 47.72 > 19.0 117.9us 95.4us
1024 73.76 59.12 > 19.8 147.5us 118.2us
1536 152.00 118.80 > 21.8 304.0us 237.6us
2048 259.41 199.57 > 23.1 518.8us 399.1us
(B3)
bits multiply square ad percent time/mult time/square
64 2.60 2.47 > 5.0 5.20us 4.94us
128 4.43 4.06 > 8.4 8.86us 8.12us
192 7.03 6.10 > 13.2 14.1us 12.2us
256 10.44 8.59 > 17.7 20.9us 17.2us
320 14.44 11.64 > 19.4 28.9us 23.3us
384 19.12 15.08 > 21.1 38.2us 30.2us
448 24.55 19.09 > 22.2 49.1us 38.2us
512 31.03 23.53 > 24.2 62.1us 47.1us
640 45.05 33.80 > 25.0 90.1us 67.6us
768 63.02 46.05 > 26.9 126.0us 92.1us
896 83.74 60.29 > 28.0 167.5us 120.6us
1024 106.73 76.65 > 28.2 213.5us 153.3us
1536 228.94 160.98 > 29.7 457.9us 322.0us
2048 398.08 275.93 > 30.7 796.2us 551.9us
(C4)
bits multiply square ad percent time/mult time/square
64 1.34 1.28 > 4.5 2.68us 2.56us
128 2.76 2.59 > 6.2 5.52us 5.18us
192 4.52 4.16 > 8.0 9.04us 8.32us
256 6.64 5.99 > 9.8 13.3us 12.0us
320 9.20 8.13 > 11.6 18.4us 16.3us
384 12.01 10.58 > 11.9 24.0us 21.2us
448 15.24 13.33 > 12.5 30.5us 26.7us
512 19.02 16.46 > 13.5 38.0us 32.9us
640 27.56 23.54 > 14.6 55.1us 47.1us
768 37.89 31.78 > 16.1 75.8us 63.6us
896 49.24 41.42 > 15.9 98.5us 82.8us
1024 62.59 52.18 > 16.6 125.2us 104.3us
1536 131.66 107.72 > 18.2 263.3us 215.4us
2048 226.45 182.95 > 19.2 453.0us 365.9us
(A7)
bits multiply square ad percent time/mult time/square
64 1.74 1.71 > 1.7 3.48us 3.42us
128 3.48 2.96 > 14.9 6.96us 5.92us
192 5.74 4.60 > 19.9 11.5us 9.20us
256 8.75 6.61 > 24.5 17.5us 13.2us
320 12.5 8.99 > 28.1 25.0us 18.0us
384 16.9 11.9 > 29.6 33.8us 23.8us
448 22.2 15.2 > 31.7 44.4us 30.4us
512 28.3 19.0 > 32.7 56.6us 38.0us
640 42.4 28.0 > 34.0 84.8us 56.0us
768 59.4 38.5 > 35.2 118.8us 77.0us
896 79.5 51.2 > 35.6 159.0us 102.4us
1024 102.6 65.5 > 36.2 205.2us 131.0us
1536 224.3 140.6 > 37.3 448.6us 281.2us
2048 393.4 244.3 > 37.9 786.8us 488.6us
------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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: timing.txt,v 1.1 2000-07-14 00:44:38 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,60 @@
#!/usr/linguist/bin/perl
#
# make-logtab
#
# Generate a table of logarithms of 2 in various bases, for use in
# estimating the output sizes of various bases.
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: make-logtab,v 1.1 2000-07-14 00:44:18 nelsonb%netscape.com Exp $
$ARRAYNAME = $ENV{'ARRAYNAME'} || "s_logv_2";
$ARRAYTYPE = $ENV{'ARRAYTYPE'} || "float";
printf("const %s %s[] = {\n %0.9f, %0.9f, ",
$ARRAYTYPE, $ARRAYNAME, 0, 0);
$brk = 2;
for($ix = 2; $ix < 64; $ix++) {
printf("%0.9f, ", (log(2)/log($ix)));
$brk = ($brk + 1) & 3;
if(!$brk) {
printf("\t/* %2d %2d %2d %2d */\n ",
$ix - 3, $ix - 2, $ix - 1, $ix);
}
}
printf("%0.9f\n};\n\n", (log(2)/log($ix)));
exit 0;

View File

@ -0,0 +1,129 @@
#!/usr/linguist/bin/perl
#
# make-test-arrays
#
# Given a test-arrays file, which specifies the test suite names, the
# names of the functions which perform those test suites, and
# descriptive comments, this script generates C structures for the
# mpi-test program. The input consists of lines of the form:
#
# suite-name:function-name:comment
#
# The output is written to the standard output. Blank lines are
# ignored, and comments beginning with '#' are stripped.
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: make-test-arrays,v 1.1 2000-07-14 00:44:19 nelsonb%netscape.com Exp $
#
# Read parameters from the environment, if available
$NAMEVAR = $ENV{'NAMEVAR'} || "g_names";
$COUNTVAR = $ENV{'COUNTVAR'} || "g_count";
$FUNCVAR = $ENV{'FUNCVAR'} || "g_tests";
$DESCVAR = $ENV{'DESCVAR'} || "g_descs";
$FUNCLEN = 13;
$NAMELEN = 18;
$DESCLEN = 45;
#------------------------------------------------------------------------
# Suck in input from the files on the command line, or standard input
while(<>) {
chomp;
s/\#.*$//;
next if /^\s*$/;
($suite, $func, $desc) = split(/:/, $_);
$tmp = { "suite" => $suite,
"func" => $func,
"desc" => $desc };
push(@item, $tmp);
}
$count = scalar(@item);
$last = pop(@item);
#------------------------------------------------------------------------
# Output the table of names
print "/* Table mapping test suite names to index numbers */\n";
printf("const int %s = %d;\n", $COUNTVAR, $count);
printf("const char *%s[] = {\n", $NAMEVAR);
foreach $elt (@item) {
printf(" \"%s\",%s/* %s%s */\n", $elt->{"suite"},
" " x ($NAMELEN - length($elt->{"suite"})),
$elt->{"desc"},
" " x ($DESCLEN - length($elt->{"desc"})));
}
printf(" \"%s\" %s/* %s%s */\n", $last->{"suite"},
" " x ($NAMELEN - length($last->{"suite"})),
$last->{"desc"},
" " x ($DESCLEN - length($last->{"desc"})));
print "};\n\n";
#------------------------------------------------------------------------
# Output the driver function prototypes
print "/* Test function prototypes */\n";
foreach $elt (@item, $last) {
printf("int %s(void);\n", $elt->{"func"});
}
print "\n";
#------------------------------------------------------------------------
# Output the table of functions
print "/* Table mapping index numbers to functions */\n";
printf("int (*%s[])(void) = {\n ", $FUNCVAR);
$brk = 0;
foreach $elt (@item) {
print($elt->{"func"}, ", ",
" " x ($FUNCLEN - length($elt->{"func"})));
$brk = ($brk + 1) & 3;
print "\n " unless($brk);
}
print $last->{"func"}, "\n};\n\n";
#------------------------------------------------------------------------
# Output the table of descriptions
print "/* Table mapping index numbers to descriptions */\n";
printf("const char *%s[] = {\n", $DESCVAR);
foreach $elt (@item) {
printf(" \"%s\",\n", $elt->{"desc"});
}
printf(" \"%s\"\n};\n\n", $last->{"desc"});
exit 0;

View File

@ -0,0 +1,104 @@
/* Default configuration for MPI library
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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-config.h,v 1.1 2000-07-14 00:44:20 nelsonb%netscape.com Exp $ */
#ifndef MPI_CONFIG_H_
#define MPI_CONFIG_H_
/*
For boolean options,
0 = no
1 = yes
Other options are documented individually.
*/
#ifndef MP_IOFUNC
#define MP_IOFUNC 0 /* include mp_print() ? */
#endif
#ifndef MP_MODARITH
#define MP_MODARITH 1 /* include modular arithmetic ? */
#endif
#ifndef MP_NUMTH
#define MP_NUMTH 1 /* include number theoretic functions? */
#endif
#ifndef MP_LOGTAB
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif
#ifndef MP_MEMSET
#define MP_MEMSET 1 /* use memset() to zero buffers? */
#endif
#ifndef MP_MEMCPY
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
#endif
#ifndef MP_CRYPTO
#define MP_CRYPTO 0 /* erase memory on free? */
#endif
#ifndef MP_ARGCHK
/*
0 = no parameter checks
1 = runtime checks, continue execution and return an error to caller
2 = assertions; dump core on parameter errors
*/
#define MP_ARGCHK 2 /* how to check input arguments */
#endif
#ifndef MP_DEBUG
#define MP_DEBUG 0 /* print diagnostic output? */
#endif
#ifndef MP_DEFPREC
#define MP_DEFPREC 16 /* default precision, in digits */
#endif
#ifndef MP_MACRO
#define MP_MACRO 1 /* use macros for frequent calls? */
#endif
#ifndef MP_SQUARE
#define MP_SQUARE 1 /* use separate squaring code? */
#endif
#endif /* ifndef MPI_CONFIG_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,208 @@
/*
* mpi.h
*
* Arbitrary precision integer arithmetic library
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.h,v 1.1 2000-07-14 00:44:21 nelsonb%netscape.com Exp $
*/
#ifndef _H_MPI_
#define _H_MPI_
#include "mpi-config.h"
#if MP_DEBUG
#undef MP_IOFUNC
#define MP_IOFUNC 1
#endif
#if MP_IOFUNC
#include <stdio.h>
#include <ctype.h>
#endif
#include <limits.h>
#define NEG 1
#define ZPOS 0
#define MP_OKAY 0 /* no error, all is well */
#define MP_YES 0 /* yes (boolean result) */
#define MP_NO -1 /* no (boolean result) */
#define MP_MEM -2 /* out of memory */
#define MP_RANGE -3 /* argument out of range */
#define MP_BADARG -4 /* invalid parameter */
#define MP_UNDEF -5 /* answer is undefined */
#define MP_LAST_CODE MP_UNDEF
typedef char mp_sign;
typedef unsigned short mp_digit;
typedef unsigned int mp_word;
typedef unsigned int mp_size;
typedef int mp_err;
#define DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
#define DIGIT_MAX USHRT_MAX
#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
#define MP_WORD_MAX UINT_MAX
#define RADIX (DIGIT_MAX+1)
#define DIGIT_FMT "%04X" /* printf() format for 1 digit */
/* Macros for accessing the mp_int internals */
#define SIGN(MP) ((MP)->sign)
#define USED(MP) ((MP)->used)
#define ALLOC(MP) ((MP)->alloc)
#define DIGITS(MP) ((MP)->dp)
#define DIGIT(MP,N) (MP)->dp[(N)]
#if MP_ARGCHK == 1
#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
#elif MP_ARGCHK == 2
#include <assert.h>
#define ARGCHK(X,Y) assert(X)
#else
#define ARGCHK(X,Y) /* */
#endif
/* This defines the maximum I/O base (minimum is 2) */
#define MAX_RADIX 64
typedef struct {
mp_sign sign; /* sign of this quantity */
mp_size alloc; /* how many digits allocated */
mp_size used; /* how many digits used */
mp_digit *dp; /* the digits themselves */
} mp_int;
/* Default precision */
unsigned int mp_get_prec(void);
void mp_set_prec(unsigned int prec);
/* Memory management */
mp_err mp_init(mp_int *mp);
mp_err mp_init_size(mp_int *mp, mp_size prec);
mp_err mp_init_copy(mp_int *mp, mp_int *from);
mp_err mp_copy(mp_int *from, mp_int *to);
void mp_exch(mp_int *mp1, mp_int *mp2);
void mp_clear(mp_int *mp);
void mp_zero(mp_int *mp);
void mp_set(mp_int *mp, mp_digit d);
mp_err mp_set_int(mp_int *mp, long z);
/* Single digit arithmetic */
mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_2(mp_int *a, mp_int *c);
mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
mp_err mp_div_2(mp_int *a, mp_int *c);
mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c);
/* Sign manipulations */
mp_err mp_abs(mp_int *a, mp_int *b);
mp_err mp_neg(mp_int *a, mp_int *b);
/* Full arithmetic */
mp_err mp_add(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c);
#if MP_SQUARE
mp_err mp_sqr(mp_int *a, mp_int *b);
#else
#define mp_sqr(a, b) mp_mul(a, a, b)
#endif
mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r);
mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r);
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_2expt(mp_int *a, mp_digit k);
mp_err mp_sqrt(mp_int *a, mp_int *b);
/* Modular arithmetic */
#if MP_MODARITH
mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c);
mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c);
mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
#if MP_SQUARE
mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
#else
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
#endif
mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
#endif /* MP_MODARITH */
/* Comparisons */
int mp_cmp_z(mp_int *a);
int mp_cmp_d(mp_int *a, mp_digit d);
int mp_cmp(mp_int *a, mp_int *b);
int mp_cmp_mag(mp_int *a, mp_int *b);
int mp_cmp_int(mp_int *a, long z);
int mp_isodd(mp_int *a);
int mp_iseven(mp_int *a);
/* Number theoretic */
#if MP_NUMTH
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y);
mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c);
#endif /* end MP_NUMTH */
/* Input and output */
#if MP_IOFUNC
void mp_print(mp_int *mp, FILE *ofp);
#endif /* end MP_IOFUNC */
/* Base conversion */
mp_err mp_read_raw(mp_int *mp, char *str, int len);
int mp_raw_size(mp_int *mp);
mp_err mp_toraw(mp_int *mp, char *str);
mp_err mp_read_radix(mp_int *mp, char *str, int radix);
int mp_radix_size(mp_int *mp, int radix);
mp_err mp_toradix(mp_int *mp, char *str, int radix);
int mp_tovalue(char ch, int r);
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
/* Error strings */
const char *mp_strerror(mp_err ec);
#endif /* end _H_MPI_ */

View File

@ -0,0 +1,410 @@
/*
* mplogic.c
*
* Bitwise logical operations on MPI values
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.1 2000-07-14 00:44:22 nelsonb%netscape.com Exp $
*/
#include "mplogic.h"
#include <stdlib.h>
/* Some things from the guts of the MPI library we make use of... */
extern mp_err s_mp_lshd(mp_int *mp, mp_size p);
extern void s_mp_rshd(mp_int *mp, mp_size p);
#define s_mp_clamp(mp)\
{ while(USED(mp) > 1 && DIGIT((mp), USED(mp) - 1) == 0) USED(mp) -= 1; }
/* {{{ Lookup table for population count */
static unsigned char bitc[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
/* }}} */
/*------------------------------------------------------------------------*/
/*
mpl_not(a, b) - compute b = ~a
mpl_and(a, b, c) - compute c = a & b
mpl_or(a, b, c) - compute c = a | b
mpl_xor(a, b, c) - compute c = a ^ b
*/
/* {{{ mpl_not(a, b) */
mp_err mpl_not(mp_int *a, mp_int *b)
{
mp_err res;
int ix;
ARGCHK(a != NULL && b != NULL, MP_BADARG);
if((res = mp_copy(a, b)) != MP_OKAY)
return res;
/* This relies on the fact that the digit type is unsigned */
for(ix = 0; ix < USED(b); ix++)
DIGIT(b, ix) = ~DIGIT(b, ix);
s_mp_clamp(b);
return MP_OKAY;
} /* end mpl_not() */
/* }}} */
/* {{{ mpl_and(a, b, c) */
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c)
{
mp_int *which, *other;
mp_err res;
int ix;
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
if(USED(a) <= USED(b)) {
which = a;
other = b;
} else {
which = b;
other = a;
}
if((res = mp_copy(which, c)) != MP_OKAY)
return res;
for(ix = 0; ix < USED(which); ix++)
DIGIT(c, ix) &= DIGIT(other, ix);
s_mp_clamp(c);
return MP_OKAY;
} /* end mpl_and() */
/* }}} */
/* {{{ mpl_or(a, b, c) */
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c)
{
mp_int *which, *other;
mp_err res;
int ix;
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
if(USED(a) >= USED(b)) {
which = a;
other = b;
} else {
which = b;
other = a;
}
if((res = mp_copy(which, c)) != MP_OKAY)
return res;
for(ix = 0; ix < USED(which); ix++)
DIGIT(c, ix) |= DIGIT(other, ix);
return MP_OKAY;
} /* end mpl_or() */
/* }}} */
/* {{{ mpl_xor(a, b, c) */
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c)
{
mp_int *which, *other;
mp_err res;
int ix;
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
if(USED(a) >= USED(b)) {
which = a;
other = b;
} else {
which = b;
other = a;
}
if((res = mp_copy(which, c)) != MP_OKAY)
return res;
for(ix = 0; ix < USED(which); ix++)
DIGIT(c, ix) ^= DIGIT(other, ix);
s_mp_clamp(c);
return MP_OKAY;
} /* end mpl_xor() */
/* }}} */
/*------------------------------------------------------------------------*/
/*
mpl_rsh(a, b, d) - b = a >> d
mpl_lsh(a, b, d) - b = a << d
*/
/* {{{ mpl_rsh(a, b, d) */
mp_err mpl_rsh(mp_int *a, mp_int *b, mp_digit d)
{
mp_err res;
mp_digit dshift, bshift;
ARGCHK(a != NULL && b != NULL, MP_BADARG);
dshift = d / DIGIT_BIT; /* How many whole digits to shift by */
bshift = d % DIGIT_BIT; /* How many bits to shift by */
if((res = mp_copy(a, b)) != MP_OKAY)
return res;
/* Shift over as many whole digits as necessary */
if(dshift)
s_mp_rshd(b, dshift);
/* Now handle any remaining bit shifting */
if(bshift)
{
mp_digit prev = 0, next, mask = (1 << bshift) - 1;
int ix;
/*
'mask' is a digit with the lower bshift bits set, the rest
clear. It is used to mask off the bottom bshift bits of each
digit, which are then shifted on to the top of the next lower
digit.
*/
for(ix = USED(b) - 1; ix >= 0; ix--) {
/* Take off the lower bits and shift them up... */
next = (DIGIT(b, ix) & mask) << (DIGIT_BIT - bshift);
/* Shift down the current digit, and mask in the bits saved
from the previous digit
*/
DIGIT(b, ix) = (DIGIT(b, ix) >> bshift) | prev;
prev = next;
}
}
s_mp_clamp(b);
return MP_OKAY;
} /* end mpl_rsh() */
/* }}} */
/* {{{ mpl_lsh(a, b, d) */
mp_err mpl_lsh(mp_int *a, mp_int *b, mp_digit d)
{
mp_err res;
mp_digit dshift, bshift;
ARGCHK(a != NULL && b != NULL, MP_BADARG);
dshift = d / DIGIT_BIT;
bshift = d % DIGIT_BIT;
if((res = mp_copy(a, b)) != MP_OKAY)
return res;
if(dshift)
if((res = s_mp_lshd(b, dshift)) != MP_OKAY)
return res;
if(bshift){
int ix;
mp_digit prev = 0, next, mask = (1 << bshift) - 1;
for(ix = 0; ix < USED(b); ix--) {
next = (DIGIT(b, ix) >> (DIGIT_BIT - bshift)) & mask;
DIGIT(b, ix) = (DIGIT(b, ix) << bshift) | prev;
prev = next;
}
}
s_mp_clamp(b);
return MP_OKAY;
} /* end mpl_lsh() */
/* }}} */
/*------------------------------------------------------------------------*/
/*
mpl_num_set(a, num)
Count the number of set bits in the binary representation of a.
Returns MP_OKAY and sets 'num' to be the number of such bits, if
possible. If num is NULL, the result is thrown away, but it is
not considered an error.
mpl_num_clear() does basically the same thing for clear bits.
*/
/* {{{ mpl_num_set(a, num) */
mp_err mpl_num_set(mp_int *a, int *num)
{
int ix, db, nset = 0;
mp_digit cur;
unsigned char reg;
ARGCHK(a != NULL, MP_BADARG);
for(ix = 0; ix < USED(a); ix++) {
cur = DIGIT(a, ix);
for(db = 0; db < sizeof(mp_digit); db++) {
reg = (cur >> (CHAR_BIT * db)) & UCHAR_MAX;
nset += bitc[reg];
}
}
if(num)
*num = nset;
return MP_OKAY;
} /* end mpl_num_set() */
/* }}} */
/* {{{ mpl_num_clear(a, num) */
mp_err mpl_num_clear(mp_int *a, int *num)
{
int ix, db, nset = 0;
mp_digit cur;
unsigned char reg;
ARGCHK(a != NULL, MP_BADARG);
for(ix = 0; ix < USED(a); ix++) {
cur = DIGIT(a, ix);
for(db = 0; db < sizeof(mp_digit); db++) {
reg = (cur >> (CHAR_BIT * db)) & UCHAR_MAX;
nset += bitc[UCHAR_MAX - reg];
}
}
if(num)
*num = nset;
return MP_OKAY;
} /* end mpl_num_clear() */
/* }}} */
/*------------------------------------------------------------------------*/
/*
mpl_parity(a)
Determines the bitwise parity of the value given. Returns MP_EVEN
if an even number of digits are set, MP_ODD if an odd number are
set.
*/
/* {{{ mpl_parity(a) */
mp_err mpl_parity(mp_int *a)
{
int ix, par = 0;
mp_digit cur;
ARGCHK(a != NULL, MP_BADARG);
for(ix = 0; ix < USED(a); ix++) {
int shft = (sizeof(mp_digit) * CHAR_BIT) / 2;
cur = DIGIT(a, ix);
/* Compute parity for current digit */
while(shft != 0) {
cur ^= (cur >> shft);
shft >>= 1;
}
cur &= 1;
/* XOR with running parity so far */
par ^= cur;
}
if(par)
return MP_ODD;
else
return MP_EVEN;
} /* end mpl_parity() */
/* }}} */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,75 @@
/*
* mplogic.h
*
* Bitwise logical operations on MPI values
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.h,v 1.1 2000-07-14 00:44:23 nelsonb%netscape.com Exp $
*/
#ifndef _H_MPLOGIC_
#define _H_MPLOGIC_
#include "mpi.h"
/*
The logical operations treat an mp_int as if it were a bit vector,
without regard to its sign (an mp_int is represented in a signed
magnitude format). Values are treated as if they had an infinite
string of zeros left of the most-significant bit.
*/
/* Parity results */
#define MP_EVEN MP_YES
#define MP_ODD MP_NO
/* Bitwise functions */
mp_err mpl_not(mp_int *a, mp_int *b); /* one's complement */
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND */
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c); /* bitwise OR */
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR */
/* Shift functions */
mp_err mpl_rsh(mp_int *a, mp_int *b, mp_digit d); /* right shift */
mp_err mpl_lsh(mp_int *a, mp_int *b, mp_digit d); /* left shift */
/* Bit count and parity */
mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */
mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */
mp_err mpl_parity(mp_int *a); /* determine parity */
#endif /* end _H_MPLOGIC_ */

View File

@ -0,0 +1,407 @@
/*
* mpprime.c
*
* Utilities for finding and working with prime and pseudo-prime
* integers
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.
*/
#include "mpprime.h"
#include <stdlib.h>
#define SMALL_TABLE /* determines size of hard-wired prime table */
#define RANDOM() rand()
#include "primes.c" /* pull in the prime digit table */
/*
Test if any of a given vector of digits divides a. If not, MP_NO
is returned; otherwise, MP_YES is returned and 'which' is set to
the index of the integer in the vector which divided a.
*/
mp_err s_mpp_divp(mp_int *a, mp_digit *vec, int size, int *which);
extern mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
/* {{{ mpp_divis(a, b) */
/*
mpp_divis(a, b)
Returns MP_YES if a is divisible by b, or MP_NO if it is not.
*/
mp_err mpp_divis(mp_int *a, mp_int *b)
{
mp_err res;
mp_int rem;
if((res = mp_init(&rem)) != MP_OKAY)
return res;
if((res = mp_mod(a, b, &rem)) != MP_OKAY)
goto CLEANUP;
if(mp_cmp_z(&rem) == 0)
res = MP_YES;
else
res = MP_NO;
CLEANUP:
mp_clear(&rem);
return res;
} /* end mpp_divis() */
/* }}} */
/* {{{ mpp_divis_d(a, d) */
/*
mpp_divis_d(a, d)
Return MP_YES if a is divisible by d, or MP_NO if it is not.
*/
mp_err mpp_divis_d(mp_int *a, mp_digit d)
{
mp_err res;
mp_digit rem;
ARGCHK(a != NULL, MP_BADARG);
if(d == 0)
return MP_NO;
if((res = mp_mod_d(a, d, &rem)) != MP_OKAY)
return res;
if(rem == 0)
return MP_YES;
else
return MP_NO;
} /* end mpp_divis_d() */
/* }}} */
/* {{{ mpp_random(a) */
/*
mpp_random(a)
Assigns a random value to a. This value is generated using the
standard C library's rand() function, so it should not be used for
cryptographic purposes, but it should be fine for primality testing,
since all we really care about there is good statistical properties.
As many digits as a currently has are filled with random digits.
*/
mp_err mpp_random(mp_int *a)
{
mp_digit next = 0;
int ix, jx;
ARGCHK(a != NULL, MP_BADARG);
for(ix = 0; ix < USED(a); ix++) {
for(jx = 0; jx < sizeof(mp_digit); jx++) {
next = (next << CHAR_BIT) | (RANDOM() & UCHAR_MAX);
}
DIGIT(a, ix) = next;
}
return MP_OKAY;
} /* end mpp_random() */
/* }}} */
/* {{{ mpp_random_size(a, prec) */
mp_err mpp_random_size(mp_int *a, mp_size prec)
{
mp_err res;
ARGCHK(a != NULL && prec > 0, MP_BADARG);
if((res = s_mp_pad(a, prec)) != MP_OKAY)
return res;
return mpp_random(a);
} /* end mpp_random_size() */
/* }}} */
/* {{{ mpp_divis_vector(a, vec, size, which) */
/*
mpp_divis_vector(a, vec, size, which)
Determines if a is divisible by any of the 'size' digits in vec.
Returns MP_YES and sets 'which' to the index of the offending digit,
if it is; returns MP_NO if it is not.
*/
mp_err mpp_divis_vector(mp_int *a, mp_digit *vec, int size, int *which)
{
ARGCHK(a != NULL && vec != NULL && size > 0, MP_BADARG);
return s_mpp_divp(a, vec, size, which);
} /* end mpp_divis_vector() */
/* }}} */
/* {{{ mpp_divis_primes(a, np) */
/*
mpp_divis_primes(a, np)
Test whether a is divisible by any of the first 'np' primes. If it
is, returns MP_YES and sets *np to the value of the digit that did
it. If not, returns MP_NO.
*/
mp_err mpp_divis_primes(mp_int *a, mp_digit *np)
{
int size, which;
mp_err res;
ARGCHK(a != NULL && np != NULL, MP_BADARG);
size = *np;
if(size > prime_tab_size)
size = prime_tab_size;
res = mpp_divis_vector(a, prime_tab, size, &which);
if(res == MP_YES)
*np = prime_tab[which];
return res;
} /* end mpp_divis_primes() */
/* }}} */
/* {{{ mpp_fermat(a, w) */
/*
Using w as a witness, try pseudo-primality testing based on Fermat's
little theorem. If a is prime, and (w, a) = 1, then w^a == w (mod
a). So, we compute z = w^a (mod a) and compare z to w; if they are
equal, the test passes and we return MP_YES. Otherwise, we return
MP_NO.
*/
mp_err mpp_fermat(mp_int *a, mp_digit w)
{
mp_int base, test;
mp_err res;
if((res = mp_init(&base)) != MP_OKAY)
return res;
mp_set(&base, w);
if((res = mp_init(&test)) != MP_OKAY)
goto TEST;
/* Compute test = base^a (mod a) */
if((res = mp_exptmod(&base, a, a, &test)) != MP_OKAY)
goto CLEANUP;
if(mp_cmp(&base, &test) == 0)
res = MP_YES;
else
res = MP_NO;
CLEANUP:
mp_clear(&test);
TEST:
mp_clear(&base);
return res;
} /* end mpp_fermat() */
/* }}} */
/* {{{ mpp_pprime(a, nt) */
/*
mpp_pprime(a, nt)
Performs nt iteration of the Miller-Rabin probabilistic primality
test on a. Returns MP_YES if the tests pass, MP_NO if one fails.
If MP_NO is returned, the number is definitely composite. If MP_YES
is returned, it is probably prime (but that is not guaranteed).
*/
mp_err mpp_pprime(mp_int *a, int nt)
{
mp_err res;
mp_int x, amo, m, z;
int iter, jx, b;
ARGCHK(a != NULL, MP_BADARG);
/* Initialize temporaries... */
if((res = mp_init_copy(&amo, a)) != MP_OKAY)
return res;
if((res = mp_init_size(&x, USED(a))) != MP_OKAY)
goto X;
if((res = mp_init(&z)) != MP_OKAY)
goto Z;
/* Compute m = a - 1 for what follows... */
mp_sub_d(&amo, 1, &amo);
if((res = mp_init_copy(&m, &amo)) != MP_OKAY)
goto M;
/* How many times does 2 divide (a - 1)? */
b = 0;
while((DIGIT(&m, 0) & 1) == 0) {
mp_div_2(&m, &m);
++b;
}
/* Do the test nt times... */
for(iter = 0; iter < nt; iter++) {
/* Choose a random value for x < a */
s_mp_pad(&x, USED(a));
mpp_random(&x);
if((res = mp_mod(&x, a, &x)) != MP_OKAY)
goto CLEANUP;
/* Compute z = (x ** m) mod a */
if((res = mp_exptmod(&x, &m, a, &z)) != MP_OKAY)
goto CLEANUP;
jx = 0;
if(mp_cmp_d(&z, 1) == 0 || mp_cmp(&z, &amo) == 0) {
res = MP_YES;
goto CLEANUP;
}
for(;;) {
if(jx > 0 && mp_cmp_d(&z, 1) == 0) {
res = MP_NO;
break;
}
++jx;
if(jx < b && mp_cmp(&z, &amo) != 0) {
/* z = z^2 (mod a) */
if((res = mp_sqrmod(&z, a, &z)) != MP_OKAY)
goto CLEANUP;
} else if(mp_cmp(&z, &amo) == 0) {
res = MP_YES;
break;
} else if(jx == b && mp_cmp(&z, &amo) != 0) {
res = MP_NO;
break;
}
} /* end testing loop */
/* If the test passes, we will continue iterating, but a failed
test means the candidate is definitely NOT prime, so we will
immediately break out of this loop
*/
if(res == MP_NO)
break;
} /* end iterations loop */
CLEANUP:
mp_clear(&m);
M:
mp_clear(&z);
Z:
mp_clear(&x);
X:
mp_clear(&amo);
return res;
} /* end mpp_pprime() */
/* }}} */
/*========================================================================*/
/*------------------------------------------------------------------------*/
/* Static functions visible only to the library internally */
/* {{{ s_mpp_divp(a, vec, size, which) */
/*
Test for divisibility by members of a vector of digits. Returns
MP_NO if a is not divisible by any of them; returns MP_YES and sets
'which' to the index of the offender, if it is. Will stop on the
first digit against which a is divisible.
*/
mp_err s_mpp_divp(mp_int *a, mp_digit *vec, int size, int *which)
{
mp_err res;
mp_digit rem;
int ix;
for(ix = 0; ix < size; ix++) {
if((res = mp_mod_d(a, vec[ix], &rem)) != MP_OKAY)
return res;
if(rem == 0) {
if(which)
*which = ix;
return MP_YES;
}
}
return MP_NO;
} /* end s_mpp_divp() */
/* }}} */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,61 @@
/*
* mpprime.h
*
* Utilities for finding and working with prime and pseudo-prime
* integers
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.
*/
#ifndef _H_MP_PRIME_
#define _H_MP_PRIME_
#include "mpi.h"
extern int prime_tab_size; /* number of primes available */
/* Tests for divisibility */
mp_err mpp_divis(mp_int *a, mp_int *b);
mp_err mpp_divis_d(mp_int *a, mp_digit d);
/* Random selection */
mp_err mpp_random(mp_int *a);
mp_err mpp_random_size(mp_int *a, mp_size prec);
/* Pseudo-primality testing */
mp_err mpp_divis_vector(mp_int *a, mp_digit *vec, int size, int *which);
mp_err mpp_divis_primes(mp_int *a, mp_digit *np);
mp_err mpp_fermat(mp_int *a, mp_digit w);
mp_err mpp_pprime(mp_int *a, int nt);
#endif /* end _H_MP_PRIME_ */

View File

@ -0,0 +1,111 @@
/*
* Test whether to include squaring code given the current settings
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#define MP_SQUARE 1 /* make sure squaring code is included */
#include "mpi.h"
#include "mpprime.h"
int main(int argc, char *argv[])
{
int ntests, prec, ix;
unsigned int seed;
clock_t start, stop;
double multime, sqrtime;
mp_int a, c;
seed = (unsigned int)time(NULL);
if(argc < 3) {
fprintf(stderr, "Usage: %s <ntests> <nbits>\n", argv[0]);
return 1;
}
if((ntests = abs(atoi(argv[1]))) == 0) {
fprintf(stderr, "%s: must request at least 1 test.\n", argv[0]);
return 1;
}
if((prec = abs(atoi(argv[2]))) < CHAR_BIT) {
fprintf(stderr, "%s: must request at least %d bits.\n", argv[0],
CHAR_BIT);
return 1;
}
prec = (prec + (DIGIT_BIT - 1)) / DIGIT_BIT;
mp_init_size(&a, prec);
mp_init_size(&c, 2 * prec);
/* Test multiplication by self */
srand(seed);
start = clock();
for(ix = 0; ix < ntests; ix++) {
mpp_random_size(&a, prec);
mp_mul(&a, &a, &c);
}
stop = clock();
multime = (double)(stop - start) / CLOCKS_PER_SEC;
/* Test squaring */
srand(seed);
start = clock();
for(ix = 0; ix < ntests; ix++) {
mpp_random_size(&a, prec);
mp_sqr(&a, &c);
}
stop = clock();
sqrtime = (double)(stop - start) / CLOCKS_PER_SEC;
printf("Multiply: %.4f\n", multime);
printf("Square: %.4f\n", sqrtime);
if(multime < sqrtime) {
printf("Speedup: %.1f%%\n", 100.0 * (1.0 - multime / sqrtime));
printf("Prefer: multiply\n");
} else {
printf("Speedup: %.1f%%\n", 100.0 * (1.0 - sqrtime / multime));
printf("Prefer: square\n");
}
mp_clear(&a); mp_clear(&c);
return 0;
}

View File

@ -0,0 +1,107 @@
#!/bin/sh
#
# multest
#
# Run multiply and square timing tests, to compute a chart for the
# current processor and compiler combination.
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: multest,v 1.1 2000-07-14 00:44:25 nelsonb%netscape.com Exp $
#
ECHO=/bin/echo
$ECHO "\n** Running multiply and square timing tests\n"
$ECHO "Bringing 'mulsqr' up to date ... "
if make mulsqr ; then
:
else
$ECHO "\nMake failed to build mulsqr.\n"
exit 1
fi
if [ ! -x ./mulsqr ] ; then
$ECHO "\nCannot find 'mulsqr' program, testing cannot continue.\n"
exit 1
fi
sizes='64 128 192 256 320 384 448 512 640 768 896 1024 1536 2048'
ntests=500000
$ECHO "Running timing tests, please wait ... "
trap 'echo "oop!";rm -f tt*.tmp;exit 0' INT HUP
touch tt$$.tmp
$ECHO $ntests tests >> tt$$.tmp
for size in $sizes ; do
$ECHO "$size bits ... \c"
set -A res `./mulsqr $ntests $size|head -3|tr -d '%'|awk '{print $2}'`
$ECHO $size"\t"${res[0]}"\t"${res[1]}"\t"${res[2]} >> tt$$.tmp
$ECHO "(done)"
done
mv tt$$.tmp mulsqr-results.txt
rm -f tt$$.tmp
$ECHO "\n** Running Karatsuba-Ofman multiplication tests\n"
$ECHO "Brining 'karatsuba' up to date ... "
if make karatsuba ; then
:
else
$ECHO "\nMake failed to build karatsuba.\n"
exit 1
fi
if [ ! -x ./karatsuba ] ; then
$ECHO "\nCannot find 'karatsuba' program, testing cannot continue.\n"
exit 1
fi
ntests=100000
trap 'echo "oop!";rm -f tt*.tmp;exit 0' INT HUP
touch tt$$.tmp
for size in $sizes ; do
$ECHO "$size bits ... "
./karatsuba $ntests $size >> tt$$.tmp
tail -2 tt$$.tmp
done
mv tt$$.tmp karatsuba-results.txt
rm -f tt$$.tmp
exit 0

View File

@ -0,0 +1,886 @@
/*
* These tables of primes wwere generated using the 'sieve' program
* (sieve.c) and converted to this format with 'ptab.pl'.
*
* The 'small' table is just the first 128 primes. The 'large' table
* is a table of all the prime values that will fit into a single
* mp_digit (given the current size of an mp_digit, which is two bytes).
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.
*/
#ifdef SMALL_TABLE
int prime_tab_size = 128;
mp_digit prime_tab[] = {
0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF
};
#else
int prime_tab_size = 6542;
mp_digit prime_tab[] = {
0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653,
0x0655, 0x065B, 0x0665, 0x0679, 0x067F, 0x0683, 0x0685, 0x069D,
0x06A1, 0x06A3, 0x06AD, 0x06B9, 0x06BB, 0x06C5, 0x06CD, 0x06D3,
0x06D9, 0x06DF, 0x06F1, 0x06F7, 0x06FB, 0x06FD, 0x0709, 0x0713,
0x071F, 0x0727, 0x0737, 0x0745, 0x074B, 0x074F, 0x0751, 0x0755,
0x0757, 0x0761, 0x076D, 0x0773, 0x0779, 0x078B, 0x078D, 0x079D,
0x079F, 0x07B5, 0x07BB, 0x07C3, 0x07C9, 0x07CD, 0x07CF, 0x07D3,
0x07DB, 0x07E1, 0x07EB, 0x07ED, 0x07F7, 0x0805, 0x080F, 0x0815,
0x0821, 0x0823, 0x0827, 0x0829, 0x0833, 0x083F, 0x0841, 0x0851,
0x0853, 0x0859, 0x085D, 0x085F, 0x0869, 0x0871, 0x0883, 0x089B,
0x089F, 0x08A5, 0x08AD, 0x08BD, 0x08BF, 0x08C3, 0x08CB, 0x08DB,
0x08DD, 0x08E1, 0x08E9, 0x08EF, 0x08F5, 0x08F9, 0x0905, 0x0907,
0x091D, 0x0923, 0x0925, 0x092B, 0x092F, 0x0935, 0x0943, 0x0949,
0x094D, 0x094F, 0x0955, 0x0959, 0x095F, 0x096B, 0x0971, 0x0977,
0x0985, 0x0989, 0x098F, 0x099B, 0x09A3, 0x09A9, 0x09AD, 0x09C7,
0x09D9, 0x09E3, 0x09EB, 0x09EF, 0x09F5, 0x09F7, 0x09FD, 0x0A13,
0x0A1F, 0x0A21, 0x0A31, 0x0A39, 0x0A3D, 0x0A49, 0x0A57, 0x0A61,
0x0A63, 0x0A67, 0x0A6F, 0x0A75, 0x0A7B, 0x0A7F, 0x0A81, 0x0A85,
0x0A8B, 0x0A93, 0x0A97, 0x0A99, 0x0A9F, 0x0AA9, 0x0AAB, 0x0AB5,
0x0ABD, 0x0AC1, 0x0ACF, 0x0AD9, 0x0AE5, 0x0AE7, 0x0AED, 0x0AF1,
0x0AF3, 0x0B03, 0x0B11, 0x0B15, 0x0B1B, 0x0B23, 0x0B29, 0x0B2D,
0x0B3F, 0x0B47, 0x0B51, 0x0B57, 0x0B5D, 0x0B65, 0x0B6F, 0x0B7B,
0x0B89, 0x0B8D, 0x0B93, 0x0B99, 0x0B9B, 0x0BB7, 0x0BB9, 0x0BC3,
0x0BCB, 0x0BCF, 0x0BDD, 0x0BE1, 0x0BE9, 0x0BF5, 0x0BFB, 0x0C07,
0x0C0B, 0x0C11, 0x0C25, 0x0C2F, 0x0C31, 0x0C41, 0x0C5B, 0x0C5F,
0x0C61, 0x0C6D, 0x0C73, 0x0C77, 0x0C83, 0x0C89, 0x0C91, 0x0C95,
0x0C9D, 0x0CB3, 0x0CB5, 0x0CB9, 0x0CBB, 0x0CC7, 0x0CE3, 0x0CE5,
0x0CEB, 0x0CF1, 0x0CF7, 0x0CFB, 0x0D01, 0x0D03, 0x0D0F, 0x0D13,
0x0D1F, 0x0D21, 0x0D2B, 0x0D2D, 0x0D3D, 0x0D3F, 0x0D4F, 0x0D55,
0x0D69, 0x0D79, 0x0D81, 0x0D85, 0x0D87, 0x0D8B, 0x0D8D, 0x0DA3,
0x0DAB, 0x0DB7, 0x0DBD, 0x0DC7, 0x0DC9, 0x0DCD, 0x0DD3, 0x0DD5,
0x0DDB, 0x0DE5, 0x0DE7, 0x0DF3, 0x0DFD, 0x0DFF, 0x0E09, 0x0E17,
0x0E1D, 0x0E21, 0x0E27, 0x0E2F, 0x0E35, 0x0E3B, 0x0E4B, 0x0E57,
0x0E59, 0x0E5D, 0x0E6B, 0x0E71, 0x0E75, 0x0E7D, 0x0E87, 0x0E8F,
0x0E95, 0x0E9B, 0x0EB1, 0x0EB7, 0x0EB9, 0x0EC3, 0x0ED1, 0x0ED5,
0x0EDB, 0x0EED, 0x0EEF, 0x0EF9, 0x0F07, 0x0F0B, 0x0F0D, 0x0F17,
0x0F25, 0x0F29, 0x0F31, 0x0F43, 0x0F47, 0x0F4D, 0x0F4F, 0x0F53,
0x0F59, 0x0F5B, 0x0F67, 0x0F6B, 0x0F7F, 0x0F95, 0x0FA1, 0x0FA3,
0x0FA7, 0x0FAD, 0x0FB3, 0x0FB5, 0x0FBB, 0x0FD1, 0x0FD3, 0x0FD9,
0x0FE9, 0x0FEF, 0x0FFB, 0x0FFD, 0x1003, 0x100F, 0x101F, 0x1021,
0x1025, 0x102B, 0x1039, 0x103D, 0x103F, 0x1051, 0x1069, 0x1073,
0x1079, 0x107B, 0x1085, 0x1087, 0x1091, 0x1093, 0x109D, 0x10A3,
0x10A5, 0x10AF, 0x10B1, 0x10BB, 0x10C1, 0x10C9, 0x10E7, 0x10F1,
0x10F3, 0x10FD, 0x1105, 0x110B, 0x1115, 0x1127, 0x112D, 0x1139,
0x1145, 0x1147, 0x1159, 0x115F, 0x1163, 0x1169, 0x116F, 0x1181,
0x1183, 0x118D, 0x119B, 0x11A1, 0x11A5, 0x11A7, 0x11AB, 0x11C3,
0x11C5, 0x11D1, 0x11D7, 0x11E7, 0x11EF, 0x11F5, 0x11FB, 0x120D,
0x121D, 0x121F, 0x1223, 0x1229, 0x122B, 0x1231, 0x1237, 0x1241,
0x1247, 0x1253, 0x125F, 0x1271, 0x1273, 0x1279, 0x127D, 0x128F,
0x1297, 0x12AF, 0x12B3, 0x12B5, 0x12B9, 0x12BF, 0x12C1, 0x12CD,
0x12D1, 0x12DF, 0x12FD, 0x1307, 0x130D, 0x1319, 0x1327, 0x132D,
0x1337, 0x1343, 0x1345, 0x1349, 0x134F, 0x1357, 0x135D, 0x1367,
0x1369, 0x136D, 0x137B, 0x1381, 0x1387, 0x138B, 0x1391, 0x1393,
0x139D, 0x139F, 0x13AF, 0x13BB, 0x13C3, 0x13D5, 0x13D9, 0x13DF,
0x13EB, 0x13ED, 0x13F3, 0x13F9, 0x13FF, 0x141B, 0x1421, 0x142F,
0x1433, 0x143B, 0x1445, 0x144D, 0x1459, 0x146B, 0x146F, 0x1471,
0x1475, 0x148D, 0x1499, 0x149F, 0x14A1, 0x14B1, 0x14B7, 0x14BD,
0x14CB, 0x14D5, 0x14E3, 0x14E7, 0x1505, 0x150B, 0x1511, 0x1517,
0x151F, 0x1525, 0x1529, 0x152B, 0x1537, 0x153D, 0x1541, 0x1543,
0x1549, 0x155F, 0x1565, 0x1567, 0x156B, 0x157D, 0x157F, 0x1583,
0x158F, 0x1591, 0x1597, 0x159B, 0x15B5, 0x15BB, 0x15C1, 0x15C5,
0x15CD, 0x15D7, 0x15F7, 0x1607, 0x1609, 0x160F, 0x1613, 0x1615,
0x1619, 0x161B, 0x1625, 0x1633, 0x1639, 0x163D, 0x1645, 0x164F,
0x1655, 0x1669, 0x166D, 0x166F, 0x1675, 0x1693, 0x1697, 0x169F,
0x16A9, 0x16AF, 0x16B5, 0x16BD, 0x16C3, 0x16CF, 0x16D3, 0x16D9,
0x16DB, 0x16E1, 0x16E5, 0x16EB, 0x16ED, 0x16F7, 0x16F9, 0x1709,
0x170F, 0x1723, 0x1727, 0x1733, 0x1741, 0x175D, 0x1763, 0x1777,
0x177B, 0x178D, 0x1795, 0x179B, 0x179F, 0x17A5, 0x17B3, 0x17B9,
0x17BF, 0x17C9, 0x17CB, 0x17D5, 0x17E1, 0x17E9, 0x17F3, 0x17F5,
0x17FF, 0x1807, 0x1813, 0x181D, 0x1835, 0x1837, 0x183B, 0x1843,
0x1849, 0x184D, 0x1855, 0x1867, 0x1871, 0x1877, 0x187D, 0x187F,
0x1885, 0x188F, 0x189B, 0x189D, 0x18A7, 0x18AD, 0x18B3, 0x18B9,
0x18C1, 0x18C7, 0x18D1, 0x18D7, 0x18D9, 0x18DF, 0x18E5, 0x18EB,
0x18F5, 0x18FD, 0x1915, 0x191B, 0x1931, 0x1933, 0x1945, 0x1949,
0x1951, 0x195B, 0x1979, 0x1981, 0x1993, 0x1997, 0x1999, 0x19A3,
0x19A9, 0x19AB, 0x19B1, 0x19B5, 0x19C7, 0x19CF, 0x19DB, 0x19ED,
0x19FD, 0x1A03, 0x1A05, 0x1A11, 0x1A17, 0x1A21, 0x1A23, 0x1A2D,
0x1A2F, 0x1A35, 0x1A3F, 0x1A4D, 0x1A51, 0x1A69, 0x1A6B, 0x1A7B,
0x1A7D, 0x1A87, 0x1A89, 0x1A93, 0x1AA7, 0x1AAB, 0x1AAD, 0x1AB1,
0x1AB9, 0x1AC9, 0x1ACF, 0x1AD5, 0x1AD7, 0x1AE3, 0x1AF3, 0x1AFB,
0x1AFF, 0x1B05, 0x1B23, 0x1B25, 0x1B2F, 0x1B31, 0x1B37, 0x1B3B,
0x1B41, 0x1B47, 0x1B4F, 0x1B55, 0x1B59, 0x1B65, 0x1B6B, 0x1B73,
0x1B7F, 0x1B83, 0x1B91, 0x1B9D, 0x1BA7, 0x1BBF, 0x1BC5, 0x1BD1,
0x1BD7, 0x1BD9, 0x1BEF, 0x1BF7, 0x1C09, 0x1C13, 0x1C19, 0x1C27,
0x1C2B, 0x1C2D, 0x1C33, 0x1C3D, 0x1C45, 0x1C4B, 0x1C4F, 0x1C55,
0x1C73, 0x1C81, 0x1C8B, 0x1C8D, 0x1C99, 0x1CA3, 0x1CA5, 0x1CB5,
0x1CB7, 0x1CC9, 0x1CE1, 0x1CF3, 0x1CF9, 0x1D09, 0x1D1B, 0x1D21,
0x1D23, 0x1D35, 0x1D39, 0x1D3F, 0x1D41, 0x1D4B, 0x1D53, 0x1D5D,
0x1D63, 0x1D69, 0x1D71, 0x1D75, 0x1D7B, 0x1D7D, 0x1D87, 0x1D89,
0x1D95, 0x1D99, 0x1D9F, 0x1DA5, 0x1DA7, 0x1DB3, 0x1DB7, 0x1DC5,
0x1DD7, 0x1DDB, 0x1DE1, 0x1DF5, 0x1DF9, 0x1E01, 0x1E07, 0x1E0B,
0x1E13, 0x1E17, 0x1E25, 0x1E2B, 0x1E2F, 0x1E3D, 0x1E49, 0x1E4D,
0x1E4F, 0x1E6D, 0x1E71, 0x1E89, 0x1E8F, 0x1E95, 0x1EA1, 0x1EAD,
0x1EBB, 0x1EC1, 0x1EC5, 0x1EC7, 0x1ECB, 0x1EDD, 0x1EE3, 0x1EEF,
0x1EF7, 0x1EFD, 0x1F01, 0x1F0D, 0x1F0F, 0x1F1B, 0x1F39, 0x1F49,
0x1F4B, 0x1F51, 0x1F67, 0x1F75, 0x1F7B, 0x1F85, 0x1F91, 0x1F97,
0x1F99, 0x1F9D, 0x1FA5, 0x1FAF, 0x1FB5, 0x1FBB, 0x1FD3, 0x1FE1,
0x1FE7, 0x1FEB, 0x1FF3, 0x1FFF, 0x2011, 0x201B, 0x201D, 0x2027,
0x2029, 0x202D, 0x2033, 0x2047, 0x204D, 0x2051, 0x205F, 0x2063,
0x2065, 0x2069, 0x2077, 0x207D, 0x2089, 0x20A1, 0x20AB, 0x20B1,
0x20B9, 0x20C3, 0x20C5, 0x20E3, 0x20E7, 0x20ED, 0x20EF, 0x20FB,
0x20FF, 0x210D, 0x2113, 0x2135, 0x2141, 0x2149, 0x214F, 0x2159,
0x215B, 0x215F, 0x2173, 0x217D, 0x2185, 0x2195, 0x2197, 0x21A1,
0x21AF, 0x21B3, 0x21B5, 0x21C1, 0x21C7, 0x21D7, 0x21DD, 0x21E5,
0x21E9, 0x21F1, 0x21F5, 0x21FB, 0x2203, 0x2209, 0x220F, 0x221B,
0x2221, 0x2225, 0x222B, 0x2231, 0x2239, 0x224B, 0x224F, 0x2263,
0x2267, 0x2273, 0x2275, 0x227F, 0x2285, 0x2287, 0x2291, 0x229D,
0x229F, 0x22A3, 0x22B7, 0x22BD, 0x22DB, 0x22E1, 0x22E5, 0x22ED,
0x22F7, 0x2303, 0x2309, 0x230B, 0x2327, 0x2329, 0x232F, 0x2333,
0x2335, 0x2345, 0x2351, 0x2353, 0x2359, 0x2363, 0x236B, 0x2383,
0x238F, 0x2395, 0x23A7, 0x23AD, 0x23B1, 0x23BF, 0x23C5, 0x23C9,
0x23D5, 0x23DD, 0x23E3, 0x23EF, 0x23F3, 0x23F9, 0x2405, 0x240B,
0x2417, 0x2419, 0x2429, 0x243D, 0x2441, 0x2443, 0x244D, 0x245F,
0x2467, 0x246B, 0x2479, 0x247D, 0x247F, 0x2485, 0x249B, 0x24A1,
0x24AF, 0x24B5, 0x24BB, 0x24C5, 0x24CB, 0x24CD, 0x24D7, 0x24D9,
0x24DD, 0x24DF, 0x24F5, 0x24F7, 0x24FB, 0x2501, 0x2507, 0x2513,
0x2519, 0x2527, 0x2531, 0x253D, 0x2543, 0x254B, 0x254F, 0x2573,
0x2581, 0x258D, 0x2593, 0x2597, 0x259D, 0x259F, 0x25AB, 0x25B1,
0x25BD, 0x25CD, 0x25CF, 0x25D9, 0x25E1, 0x25F7, 0x25F9, 0x2605,
0x260B, 0x260F, 0x2615, 0x2627, 0x2629, 0x2635, 0x263B, 0x263F,
0x264B, 0x2653, 0x2659, 0x2665, 0x2669, 0x266F, 0x267B, 0x2681,
0x2683, 0x268F, 0x269B, 0x269F, 0x26AD, 0x26B3, 0x26C3, 0x26C9,
0x26CB, 0x26D5, 0x26DD, 0x26EF, 0x26F5, 0x2717, 0x2719, 0x2735,
0x2737, 0x274D, 0x2753, 0x2755, 0x275F, 0x276B, 0x276D, 0x2773,
0x2777, 0x277F, 0x2795, 0x279B, 0x279D, 0x27A7, 0x27AF, 0x27B3,
0x27B9, 0x27C1, 0x27C5, 0x27D1, 0x27E3, 0x27EF, 0x2803, 0x2807,
0x280D, 0x2813, 0x281B, 0x281F, 0x2821, 0x2831, 0x283D, 0x283F,
0x2849, 0x2851, 0x285B, 0x285D, 0x2861, 0x2867, 0x2875, 0x2881,
0x2897, 0x289F, 0x28BB, 0x28BD, 0x28C1, 0x28D5, 0x28D9, 0x28DB,
0x28DF, 0x28ED, 0x28F7, 0x2903, 0x2905, 0x2911, 0x2921, 0x2923,
0x293F, 0x2947, 0x295D, 0x2965, 0x2969, 0x296F, 0x2975, 0x2983,
0x2987, 0x298F, 0x299B, 0x29A1, 0x29A7, 0x29AB, 0x29BF, 0x29C3,
0x29D5, 0x29D7, 0x29E3, 0x29E9, 0x29ED, 0x29F3, 0x2A01, 0x2A13,
0x2A1D, 0x2A25, 0x2A2F, 0x2A4F, 0x2A55, 0x2A5F, 0x2A65, 0x2A6B,
0x2A6D, 0x2A73, 0x2A83, 0x2A89, 0x2A8B, 0x2A97, 0x2A9D, 0x2AB9,
0x2ABB, 0x2AC5, 0x2ACD, 0x2ADD, 0x2AE3, 0x2AEB, 0x2AF1, 0x2AFB,
0x2B13, 0x2B27, 0x2B31, 0x2B33, 0x2B3D, 0x2B3F, 0x2B4B, 0x2B4F,
0x2B55, 0x2B69, 0x2B6D, 0x2B6F, 0x2B7B, 0x2B8D, 0x2B97, 0x2B99,
0x2BA3, 0x2BA5, 0x2BA9, 0x2BBD, 0x2BCD, 0x2BE7, 0x2BEB, 0x2BF3,
0x2BF9, 0x2BFD, 0x2C09, 0x2C0F, 0x2C17, 0x2C23, 0x2C2F, 0x2C35,
0x2C39, 0x2C41, 0x2C57, 0x2C59, 0x2C69, 0x2C77, 0x2C81, 0x2C87,
0x2C93, 0x2C9F, 0x2CAD, 0x2CB3, 0x2CB7, 0x2CCB, 0x2CCF, 0x2CDB,
0x2CE1, 0x2CE3, 0x2CE9, 0x2CEF, 0x2CFF, 0x2D07, 0x2D1D, 0x2D1F,
0x2D3B, 0x2D43, 0x2D49, 0x2D4D, 0x2D61, 0x2D65, 0x2D71, 0x2D89,
0x2D9D, 0x2DA1, 0x2DA9, 0x2DB3, 0x2DB5, 0x2DC5, 0x2DC7, 0x2DD3,
0x2DDF, 0x2E01, 0x2E03, 0x2E07, 0x2E0D, 0x2E19, 0x2E1F, 0x2E25,
0x2E2D, 0x2E33, 0x2E37, 0x2E39, 0x2E3F, 0x2E57, 0x2E5B, 0x2E6F,
0x2E79, 0x2E7F, 0x2E85, 0x2E93, 0x2E97, 0x2E9D, 0x2EA3, 0x2EA5,
0x2EB1, 0x2EB7, 0x2EC1, 0x2EC3, 0x2ECD, 0x2ED3, 0x2EE7, 0x2EEB,
0x2F05, 0x2F09, 0x2F0B, 0x2F11, 0x2F27, 0x2F29, 0x2F41, 0x2F45,
0x2F4B, 0x2F4D, 0x2F51, 0x2F57, 0x2F6F, 0x2F75, 0x2F7D, 0x2F81,
0x2F83, 0x2FA5, 0x2FAB, 0x2FB3, 0x2FC3, 0x2FCF, 0x2FD1, 0x2FDB,
0x2FDD, 0x2FE7, 0x2FED, 0x2FF5, 0x2FF9, 0x3001, 0x300D, 0x3023,
0x3029, 0x3037, 0x303B, 0x3055, 0x3059, 0x305B, 0x3067, 0x3071,
0x3079, 0x307D, 0x3085, 0x3091, 0x3095, 0x30A3, 0x30A9, 0x30B9,
0x30BF, 0x30C7, 0x30CB, 0x30D1, 0x30D7, 0x30DF, 0x30E5, 0x30EF,
0x30FB, 0x30FD, 0x3103, 0x3109, 0x3119, 0x3121, 0x3127, 0x312D,
0x3139, 0x3143, 0x3145, 0x314B, 0x315D, 0x3161, 0x3167, 0x316D,
0x3173, 0x317F, 0x3191, 0x3199, 0x319F, 0x31A9, 0x31B1, 0x31C3,
0x31C7, 0x31D5, 0x31DB, 0x31ED, 0x31F7, 0x31FF, 0x3209, 0x3215,
0x3217, 0x321D, 0x3229, 0x3235, 0x3259, 0x325D, 0x3263, 0x326B,
0x326F, 0x3275, 0x3277, 0x327B, 0x328D, 0x3299, 0x329F, 0x32A7,
0x32AD, 0x32B3, 0x32B7, 0x32C9, 0x32CB, 0x32CF, 0x32D1, 0x32E9,
0x32ED, 0x32F3, 0x32F9, 0x3307, 0x3325, 0x332B, 0x332F, 0x3335,
0x3341, 0x3347, 0x335B, 0x335F, 0x3367, 0x336B, 0x3373, 0x3379,
0x337F, 0x3383, 0x33A1, 0x33A3, 0x33AD, 0x33B9, 0x33C1, 0x33CB,
0x33D3, 0x33EB, 0x33F1, 0x33FD, 0x3401, 0x340F, 0x3413, 0x3419,
0x341B, 0x3437, 0x3445, 0x3455, 0x3457, 0x3463, 0x3469, 0x346D,
0x3481, 0x348B, 0x3491, 0x3497, 0x349D, 0x34A5, 0x34AF, 0x34BB,
0x34C9, 0x34D3, 0x34E1, 0x34F1, 0x34FF, 0x3509, 0x3517, 0x351D,
0x352D, 0x3533, 0x353B, 0x3541, 0x3551, 0x3565, 0x356F, 0x3571,
0x3577, 0x357B, 0x357D, 0x3581, 0x358D, 0x358F, 0x3599, 0x359B,
0x35A1, 0x35B7, 0x35BD, 0x35BF, 0x35C3, 0x35D5, 0x35DD, 0x35E7,
0x35EF, 0x3605, 0x3607, 0x3611, 0x3623, 0x3631, 0x3635, 0x3637,
0x363B, 0x364D, 0x364F, 0x3653, 0x3659, 0x3661, 0x366B, 0x366D,
0x368B, 0x368F, 0x36AD, 0x36AF, 0x36B9, 0x36BB, 0x36CD, 0x36D1,
0x36E3, 0x36E9, 0x36F7, 0x3701, 0x3703, 0x3707, 0x371B, 0x373F,
0x3745, 0x3749, 0x374F, 0x375D, 0x3761, 0x3775, 0x377F, 0x378D,
0x37A3, 0x37A9, 0x37AB, 0x37C9, 0x37D5, 0x37DF, 0x37F1, 0x37F3,
0x37F7, 0x3805, 0x380B, 0x3821, 0x3833, 0x3835, 0x3841, 0x3847,
0x384B, 0x3853, 0x3857, 0x385F, 0x3865, 0x386F, 0x3871, 0x387D,
0x388F, 0x3899, 0x38A7, 0x38B7, 0x38C5, 0x38C9, 0x38CF, 0x38D5,
0x38D7, 0x38DD, 0x38E1, 0x38E3, 0x38FF, 0x3901, 0x391D, 0x3923,
0x3925, 0x3929, 0x392F, 0x393D, 0x3941, 0x394D, 0x395B, 0x396B,
0x3979, 0x397D, 0x3983, 0x398B, 0x3991, 0x3995, 0x399B, 0x39A1,
0x39A7, 0x39AF, 0x39B3, 0x39BB, 0x39BF, 0x39CD, 0x39DD, 0x39E5,
0x39EB, 0x39EF, 0x39FB, 0x3A03, 0x3A13, 0x3A15, 0x3A1F, 0x3A27,
0x3A2B, 0x3A31, 0x3A4B, 0x3A51, 0x3A5B, 0x3A63, 0x3A67, 0x3A6D,
0x3A79, 0x3A87, 0x3AA5, 0x3AA9, 0x3AB7, 0x3ACD, 0x3AD5, 0x3AE1,
0x3AE5, 0x3AEB, 0x3AF3, 0x3AFD, 0x3B03, 0x3B11, 0x3B1B, 0x3B21,
0x3B23, 0x3B2D, 0x3B39, 0x3B45, 0x3B53, 0x3B59, 0x3B5F, 0x3B71,
0x3B7B, 0x3B81, 0x3B89, 0x3B9B, 0x3B9F, 0x3BA5, 0x3BA7, 0x3BAD,
0x3BB7, 0x3BB9, 0x3BC3, 0x3BCB, 0x3BD1, 0x3BD7, 0x3BE1, 0x3BE3,
0x3BF5, 0x3BFF, 0x3C01, 0x3C0D, 0x3C11, 0x3C17, 0x3C1F, 0x3C29,
0x3C35, 0x3C43, 0x3C4F, 0x3C53, 0x3C5B, 0x3C65, 0x3C6B, 0x3C71,
0x3C85, 0x3C89, 0x3C97, 0x3CA7, 0x3CB5, 0x3CBF, 0x3CC7, 0x3CD1,
0x3CDD, 0x3CDF, 0x3CF1, 0x3CF7, 0x3D03, 0x3D0D, 0x3D19, 0x3D1B,
0x3D1F, 0x3D21, 0x3D2D, 0x3D33, 0x3D37, 0x3D3F, 0x3D43, 0x3D6F,
0x3D73, 0x3D75, 0x3D79, 0x3D7B, 0x3D85, 0x3D91, 0x3D97, 0x3D9D,
0x3DAB, 0x3DAF, 0x3DB5, 0x3DBB, 0x3DC1, 0x3DC9, 0x3DCF, 0x3DF3,
0x3E05, 0x3E09, 0x3E0F, 0x3E11, 0x3E1D, 0x3E23, 0x3E29, 0x3E2F,
0x3E33, 0x3E41, 0x3E57, 0x3E63, 0x3E65, 0x3E77, 0x3E81, 0x3E87,
0x3EA1, 0x3EB9, 0x3EBD, 0x3EBF, 0x3EC3, 0x3EC5, 0x3EC9, 0x3ED7,
0x3EDB, 0x3EE1, 0x3EE7, 0x3EEF, 0x3EFF, 0x3F0B, 0x3F0D, 0x3F37,
0x3F3B, 0x3F3D, 0x3F41, 0x3F59, 0x3F5F, 0x3F65, 0x3F67, 0x3F79,
0x3F7D, 0x3F8B, 0x3F91, 0x3FAD, 0x3FBF, 0x3FCD, 0x3FD3, 0x3FDD,
0x3FE9, 0x3FEB, 0x3FF1, 0x3FFD, 0x401B, 0x4021, 0x4025, 0x402B,
0x4031, 0x403F, 0x4043, 0x4045, 0x405D, 0x4061, 0x4067, 0x406D,
0x4087, 0x4091, 0x40A3, 0x40A9, 0x40B1, 0x40B7, 0x40BD, 0x40DB,
0x40DF, 0x40EB, 0x40F7, 0x40F9, 0x4109, 0x410B, 0x4111, 0x4115,
0x4121, 0x4133, 0x4135, 0x413B, 0x413F, 0x4159, 0x4165, 0x416B,
0x4177, 0x417B, 0x4193, 0x41AB, 0x41B7, 0x41BD, 0x41BF, 0x41CB,
0x41E7, 0x41EF, 0x41F3, 0x41F9, 0x4205, 0x4207, 0x4219, 0x421F,
0x4223, 0x4229, 0x422F, 0x4243, 0x4253, 0x4255, 0x425B, 0x4261,
0x4273, 0x427D, 0x4283, 0x4285, 0x4289, 0x4291, 0x4297, 0x429D,
0x42B5, 0x42C5, 0x42CB, 0x42D3, 0x42DD, 0x42E3, 0x42F1, 0x4307,
0x430F, 0x431F, 0x4325, 0x4327, 0x4333, 0x4337, 0x4339, 0x434F,
0x4357, 0x4369, 0x438B, 0x438D, 0x4393, 0x43A5, 0x43A9, 0x43AF,
0x43B5, 0x43BD, 0x43C7, 0x43CF, 0x43E1, 0x43E7, 0x43EB, 0x43ED,
0x43F1, 0x43F9, 0x4409, 0x440B, 0x4417, 0x4423, 0x4429, 0x443B,
0x443F, 0x4445, 0x444B, 0x4451, 0x4453, 0x4459, 0x4465, 0x446F,
0x4483, 0x448F, 0x44A1, 0x44A5, 0x44AB, 0x44AD, 0x44BD, 0x44BF,
0x44C9, 0x44D7, 0x44DB, 0x44F9, 0x44FB, 0x4505, 0x4511, 0x4513,
0x452B, 0x4531, 0x4541, 0x4549, 0x4553, 0x4555, 0x4561, 0x4577,
0x457D, 0x457F, 0x458F, 0x45A3, 0x45AD, 0x45AF, 0x45BB, 0x45C7,
0x45D9, 0x45E3, 0x45EF, 0x45F5, 0x45F7, 0x4601, 0x4603, 0x4609,
0x4613, 0x4625, 0x4627, 0x4633, 0x4639, 0x463D, 0x4643, 0x4645,
0x465D, 0x4679, 0x467B, 0x467F, 0x4681, 0x468B, 0x468D, 0x469D,
0x46A9, 0x46B1, 0x46C7, 0x46C9, 0x46CF, 0x46D3, 0x46D5, 0x46DF,
0x46E5, 0x46F9, 0x4705, 0x470F, 0x4717, 0x4723, 0x4729, 0x472F,
0x4735, 0x4739, 0x474B, 0x474D, 0x4751, 0x475D, 0x476F, 0x4771,
0x477D, 0x4783, 0x4787, 0x4789, 0x4799, 0x47A5, 0x47B1, 0x47BF,
0x47C3, 0x47CB, 0x47DD, 0x47E1, 0x47ED, 0x47FB, 0x4801, 0x4807,
0x480B, 0x4813, 0x4819, 0x481D, 0x4831, 0x483D, 0x4847, 0x4855,
0x4859, 0x485B, 0x486B, 0x486D, 0x4879, 0x4897, 0x489B, 0x48A1,
0x48B9, 0x48CD, 0x48E5, 0x48EF, 0x48F7, 0x4903, 0x490D, 0x4919,
0x491F, 0x492B, 0x4937, 0x493D, 0x4945, 0x4955, 0x4963, 0x4969,
0x496D, 0x4973, 0x4997, 0x49AB, 0x49B5, 0x49D3, 0x49DF, 0x49E1,
0x49E5, 0x49E7, 0x4A03, 0x4A0F, 0x4A1D, 0x4A23, 0x4A39, 0x4A41,
0x4A45, 0x4A57, 0x4A5D, 0x4A6B, 0x4A7D, 0x4A81, 0x4A87, 0x4A89,
0x4A8F, 0x4AB1, 0x4AC3, 0x4AC5, 0x4AD5, 0x4ADB, 0x4AED, 0x4AEF,
0x4B07, 0x4B0B, 0x4B0D, 0x4B13, 0x4B1F, 0x4B25, 0x4B31, 0x4B3B,
0x4B43, 0x4B49, 0x4B59, 0x4B65, 0x4B6D, 0x4B77, 0x4B85, 0x4BAD,
0x4BB3, 0x4BB5, 0x4BBB, 0x4BBF, 0x4BCB, 0x4BD9, 0x4BDD, 0x4BDF,
0x4BE3, 0x4BE5, 0x4BE9, 0x4BF1, 0x4BF7, 0x4C01, 0x4C07, 0x4C0D,
0x4C0F, 0x4C15, 0x4C1B, 0x4C21, 0x4C2D, 0x4C33, 0x4C4B, 0x4C55,
0x4C57, 0x4C61, 0x4C67, 0x4C73, 0x4C79, 0x4C7F, 0x4C8D, 0x4C93,
0x4C99, 0x4CCD, 0x4CE1, 0x4CE7, 0x4CF1, 0x4CF3, 0x4CFD, 0x4D05,
0x4D0F, 0x4D1B, 0x4D27, 0x4D29, 0x4D2F, 0x4D33, 0x4D41, 0x4D51,
0x4D59, 0x4D65, 0x4D6B, 0x4D81, 0x4D83, 0x4D8D, 0x4D95, 0x4D9B,
0x4DB1, 0x4DB3, 0x4DC9, 0x4DCF, 0x4DD7, 0x4DE1, 0x4DED, 0x4DF9,
0x4DFB, 0x4E05, 0x4E0B, 0x4E17, 0x4E19, 0x4E1D, 0x4E2B, 0x4E35,
0x4E37, 0x4E3D, 0x4E4F, 0x4E53, 0x4E5F, 0x4E67, 0x4E79, 0x4E85,
0x4E8B, 0x4E91, 0x4E95, 0x4E9B, 0x4EA1, 0x4EAF, 0x4EB3, 0x4EB5,
0x4EC1, 0x4ECD, 0x4ED1, 0x4ED7, 0x4EE9, 0x4EFB, 0x4F07, 0x4F09,
0x4F19, 0x4F25, 0x4F2D, 0x4F3F, 0x4F49, 0x4F63, 0x4F67, 0x4F6D,
0x4F75, 0x4F7B, 0x4F81, 0x4F85, 0x4F87, 0x4F91, 0x4FA5, 0x4FA9,
0x4FAF, 0x4FB7, 0x4FBB, 0x4FCF, 0x4FD9, 0x4FDB, 0x4FFD, 0x4FFF,
0x5003, 0x501B, 0x501D, 0x5029, 0x5035, 0x503F, 0x5045, 0x5047,
0x5053, 0x5071, 0x5077, 0x5083, 0x5093, 0x509F, 0x50A1, 0x50B7,
0x50C9, 0x50D5, 0x50E3, 0x50ED, 0x50EF, 0x50FB, 0x5107, 0x510B,
0x510D, 0x5111, 0x5117, 0x5123, 0x5125, 0x5135, 0x5147, 0x5149,
0x5171, 0x5179, 0x5189, 0x518F, 0x5197, 0x51A1, 0x51A3, 0x51A7,
0x51B9, 0x51C1, 0x51CB, 0x51D3, 0x51DF, 0x51E3, 0x51F5, 0x51F7,
0x5209, 0x5213, 0x5215, 0x5219, 0x521B, 0x521F, 0x5227, 0x5243,
0x5245, 0x524B, 0x5261, 0x526D, 0x5273, 0x5281, 0x5293, 0x5297,
0x529D, 0x52A5, 0x52AB, 0x52B1, 0x52BB, 0x52C3, 0x52C7, 0x52C9,
0x52DB, 0x52E5, 0x52EB, 0x52FF, 0x5315, 0x531D, 0x5323, 0x5341,
0x5345, 0x5347, 0x534B, 0x535D, 0x5363, 0x5381, 0x5383, 0x5387,
0x538F, 0x5395, 0x5399, 0x539F, 0x53AB, 0x53B9, 0x53DB, 0x53E9,
0x53EF, 0x53F3, 0x53F5, 0x53FB, 0x53FF, 0x540D, 0x5411, 0x5413,
0x5419, 0x5435, 0x5437, 0x543B, 0x5441, 0x5449, 0x5453, 0x5455,
0x545F, 0x5461, 0x546B, 0x546D, 0x5471, 0x548F, 0x5491, 0x549D,
0x54A9, 0x54B3, 0x54C5, 0x54D1, 0x54DF, 0x54E9, 0x54EB, 0x54F7,
0x54FD, 0x5507, 0x550D, 0x551B, 0x5527, 0x552B, 0x5539, 0x553D,
0x554F, 0x5551, 0x555B, 0x5563, 0x5567, 0x556F, 0x5579, 0x5585,
0x5597, 0x55A9, 0x55B1, 0x55B7, 0x55C9, 0x55D9, 0x55E7, 0x55ED,
0x55F3, 0x55FD, 0x560B, 0x560F, 0x5615, 0x5617, 0x5623, 0x562F,
0x5633, 0x5639, 0x563F, 0x564B, 0x564D, 0x565D, 0x565F, 0x566B,
0x5671, 0x5675, 0x5683, 0x5689, 0x568D, 0x568F, 0x569B, 0x56AD,
0x56B1, 0x56D5, 0x56E7, 0x56F3, 0x56FF, 0x5701, 0x5705, 0x5707,
0x570B, 0x5713, 0x571F, 0x5723, 0x5747, 0x574D, 0x575F, 0x5761,
0x576D, 0x5777, 0x577D, 0x5789, 0x57A1, 0x57A9, 0x57AF, 0x57B5,
0x57C5, 0x57D1, 0x57D3, 0x57E5, 0x57EF, 0x5803, 0x580D, 0x580F,
0x5815, 0x5827, 0x582B, 0x582D, 0x5855, 0x585B, 0x585D, 0x586D,
0x586F, 0x5873, 0x587B, 0x588D, 0x5897, 0x58A3, 0x58A9, 0x58AB,
0x58B5, 0x58BD, 0x58C1, 0x58C7, 0x58D3, 0x58D5, 0x58DF, 0x58F1,
0x58F9, 0x58FF, 0x5903, 0x5917, 0x591B, 0x5921, 0x5945, 0x594B,
0x594D, 0x5957, 0x595D, 0x5975, 0x597B, 0x5989, 0x5999, 0x599F,
0x59B1, 0x59B3, 0x59BD, 0x59D1, 0x59DB, 0x59E3, 0x59E9, 0x59ED,
0x59F3, 0x59F5, 0x59FF, 0x5A01, 0x5A0D, 0x5A11, 0x5A13, 0x5A17,
0x5A1F, 0x5A29, 0x5A2F, 0x5A3B, 0x5A4D, 0x5A5B, 0x5A67, 0x5A77,
0x5A7F, 0x5A85, 0x5A95, 0x5A9D, 0x5AA1, 0x5AA3, 0x5AA9, 0x5ABB,
0x5AD3, 0x5AE5, 0x5AEF, 0x5AFB, 0x5AFD, 0x5B01, 0x5B0F, 0x5B19,
0x5B1F, 0x5B25, 0x5B2B, 0x5B3D, 0x5B49, 0x5B4B, 0x5B67, 0x5B79,
0x5B87, 0x5B97, 0x5BA3, 0x5BB1, 0x5BC9, 0x5BD5, 0x5BEB, 0x5BF1,
0x5BF3, 0x5BFD, 0x5C05, 0x5C09, 0x5C0B, 0x5C0F, 0x5C1D, 0x5C29,
0x5C2F, 0x5C33, 0x5C39, 0x5C47, 0x5C4B, 0x5C4D, 0x5C51, 0x5C6F,
0x5C75, 0x5C77, 0x5C7D, 0x5C87, 0x5C89, 0x5CA7, 0x5CBD, 0x5CBF,
0x5CC3, 0x5CC9, 0x5CD1, 0x5CD7, 0x5CDD, 0x5CED, 0x5CF9, 0x5D05,
0x5D0B, 0x5D13, 0x5D17, 0x5D19, 0x5D31, 0x5D3D, 0x5D41, 0x5D47,
0x5D4F, 0x5D55, 0x5D5B, 0x5D65, 0x5D67, 0x5D6D, 0x5D79, 0x5D95,
0x5DA3, 0x5DA9, 0x5DAD, 0x5DB9, 0x5DC1, 0x5DC7, 0x5DD3, 0x5DD7,
0x5DDD, 0x5DEB, 0x5DF1, 0x5DFD, 0x5E07, 0x5E0D, 0x5E13, 0x5E1B,
0x5E21, 0x5E27, 0x5E2B, 0x5E2D, 0x5E31, 0x5E39, 0x5E45, 0x5E49,
0x5E57, 0x5E69, 0x5E73, 0x5E75, 0x5E85, 0x5E8B, 0x5E9F, 0x5EA5,
0x5EAF, 0x5EB7, 0x5EBB, 0x5ED9, 0x5EFD, 0x5F09, 0x5F11, 0x5F27,
0x5F33, 0x5F35, 0x5F3B, 0x5F47, 0x5F57, 0x5F5D, 0x5F63, 0x5F65,
0x5F77, 0x5F7B, 0x5F95, 0x5F99, 0x5FA1, 0x5FB3, 0x5FBD, 0x5FC5,
0x5FCF, 0x5FD5, 0x5FE3, 0x5FE7, 0x5FFB, 0x6011, 0x6023, 0x602F,
0x6037, 0x6053, 0x605F, 0x6065, 0x606B, 0x6073, 0x6079, 0x6085,
0x609D, 0x60AD, 0x60BB, 0x60BF, 0x60CD, 0x60D9, 0x60DF, 0x60E9,
0x60F5, 0x6109, 0x610F, 0x6113, 0x611B, 0x612D, 0x6139, 0x614B,
0x6155, 0x6157, 0x615B, 0x616F, 0x6179, 0x6187, 0x618B, 0x6191,
0x6193, 0x619D, 0x61B5, 0x61C7, 0x61C9, 0x61CD, 0x61E1, 0x61F1,
0x61FF, 0x6209, 0x6217, 0x621D, 0x6221, 0x6227, 0x623B, 0x6241,
0x624B, 0x6251, 0x6253, 0x625F, 0x6265, 0x6283, 0x628D, 0x6295,
0x629B, 0x629F, 0x62A5, 0x62AD, 0x62D5, 0x62D7, 0x62DB, 0x62DD,
0x62E9, 0x62FB, 0x62FF, 0x6305, 0x630D, 0x6317, 0x631D, 0x632F,
0x6341, 0x6343, 0x634F, 0x635F, 0x6367, 0x636D, 0x6371, 0x6377,
0x637D, 0x637F, 0x63B3, 0x63C1, 0x63C5, 0x63D9, 0x63E9, 0x63EB,
0x63EF, 0x63F5, 0x6401, 0x6403, 0x6409, 0x6415, 0x6421, 0x6427,
0x642B, 0x6439, 0x6443, 0x6449, 0x644F, 0x645D, 0x6467, 0x6475,
0x6485, 0x648D, 0x6493, 0x649F, 0x64A3, 0x64AB, 0x64C1, 0x64C7,
0x64C9, 0x64DB, 0x64F1, 0x64F7, 0x64F9, 0x650B, 0x6511, 0x6521,
0x652F, 0x6539, 0x653F, 0x654B, 0x654D, 0x6553, 0x6557, 0x655F,
0x6571, 0x657D, 0x658D, 0x658F, 0x6593, 0x65A1, 0x65A5, 0x65AD,
0x65B9, 0x65C5, 0x65E3, 0x65F3, 0x65FB, 0x65FF, 0x6601, 0x6607,
0x661D, 0x6629, 0x6631, 0x663B, 0x6641, 0x6647, 0x664D, 0x665B,
0x6661, 0x6673, 0x667D, 0x6689, 0x668B, 0x6695, 0x6697, 0x669B,
0x66B5, 0x66B9, 0x66C5, 0x66CD, 0x66D1, 0x66E3, 0x66EB, 0x66F5,
0x6703, 0x6713, 0x6719, 0x671F, 0x6727, 0x6731, 0x6737, 0x673F,
0x6745, 0x6751, 0x675B, 0x676F, 0x6779, 0x6781, 0x6785, 0x6791,
0x67AB, 0x67BD, 0x67C1, 0x67CD, 0x67DF, 0x67E5, 0x6803, 0x6809,
0x6811, 0x6817, 0x682D, 0x6839, 0x683B, 0x683F, 0x6845, 0x684B,
0x684D, 0x6857, 0x6859, 0x685D, 0x6863, 0x6869, 0x686B, 0x6871,
0x6887, 0x6899, 0x689F, 0x68B1, 0x68BD, 0x68C5, 0x68D1, 0x68D7,
0x68E1, 0x68ED, 0x68EF, 0x68FF, 0x6901, 0x690B, 0x690D, 0x6917,
0x6929, 0x692F, 0x6943, 0x6947, 0x6949, 0x694F, 0x6965, 0x696B,
0x6971, 0x6983, 0x6989, 0x6997, 0x69A3, 0x69B3, 0x69B5, 0x69BB,
0x69C1, 0x69C5, 0x69D3, 0x69DF, 0x69E3, 0x69E5, 0x69F7, 0x6A07,
0x6A2B, 0x6A37, 0x6A3D, 0x6A4B, 0x6A67, 0x6A69, 0x6A75, 0x6A7B,
0x6A87, 0x6A8D, 0x6A91, 0x6A93, 0x6AA3, 0x6AC1, 0x6AC9, 0x6AE1,
0x6AE7, 0x6B05, 0x6B0F, 0x6B11, 0x6B23, 0x6B27, 0x6B2D, 0x6B39,
0x6B41, 0x6B57, 0x6B59, 0x6B5F, 0x6B75, 0x6B87, 0x6B89, 0x6B93,
0x6B95, 0x6B9F, 0x6BBD, 0x6BBF, 0x6BDB, 0x6BE1, 0x6BEF, 0x6BFF,
0x6C05, 0x6C19, 0x6C29, 0x6C2B, 0x6C31, 0x6C35, 0x6C55, 0x6C59,
0x6C5B, 0x6C5F, 0x6C65, 0x6C67, 0x6C73, 0x6C77, 0x6C7D, 0x6C83,
0x6C8F, 0x6C91, 0x6C97, 0x6C9B, 0x6CA1, 0x6CA9, 0x6CAF, 0x6CB3,
0x6CC7, 0x6CCB, 0x6CEB, 0x6CF5, 0x6CFD, 0x6D0D, 0x6D0F, 0x6D25,
0x6D27, 0x6D2B, 0x6D31, 0x6D39, 0x6D3F, 0x6D4F, 0x6D5D, 0x6D61,
0x6D73, 0x6D7B, 0x6D7F, 0x6D93, 0x6D99, 0x6DA5, 0x6DB1, 0x6DB7,
0x6DC1, 0x6DC3, 0x6DCD, 0x6DCF, 0x6DDB, 0x6DF7, 0x6E03, 0x6E15,
0x6E17, 0x6E29, 0x6E33, 0x6E3B, 0x6E45, 0x6E75, 0x6E77, 0x6E7B,
0x6E81, 0x6E89, 0x6E93, 0x6E95, 0x6E9F, 0x6EBD, 0x6EBF, 0x6EE3,
0x6EE9, 0x6EF3, 0x6EF9, 0x6EFB, 0x6F0D, 0x6F11, 0x6F17, 0x6F1F,
0x6F2F, 0x6F3D, 0x6F4D, 0x6F53, 0x6F61, 0x6F65, 0x6F79, 0x6F7D,
0x6F83, 0x6F85, 0x6F8F, 0x6F9B, 0x6F9D, 0x6FA3, 0x6FAF, 0x6FB5,
0x6FBB, 0x6FBF, 0x6FCB, 0x6FCD, 0x6FD3, 0x6FD7, 0x6FE3, 0x6FE9,
0x6FF1, 0x6FF5, 0x6FF7, 0x6FFD, 0x700F, 0x7019, 0x701F, 0x7027,
0x7033, 0x7039, 0x704F, 0x7051, 0x7057, 0x7063, 0x7075, 0x7079,
0x7087, 0x708D, 0x7091, 0x70A5, 0x70AB, 0x70BB, 0x70C3, 0x70C7,
0x70CF, 0x70E5, 0x70ED, 0x70F9, 0x70FF, 0x7105, 0x7115, 0x7121,
0x7133, 0x7151, 0x7159, 0x715D, 0x715F, 0x7163, 0x7169, 0x7183,
0x7187, 0x7195, 0x71AD, 0x71C3, 0x71C9, 0x71CB, 0x71D1, 0x71DB,
0x71E1, 0x71EF, 0x71F5, 0x71FB, 0x7207, 0x7211, 0x7217, 0x7219,
0x7225, 0x722F, 0x723B, 0x7243, 0x7255, 0x7267, 0x7271, 0x7277,
0x727F, 0x728F, 0x7295, 0x729B, 0x72A3, 0x72B3, 0x72C7, 0x72CB,
0x72CD, 0x72D7, 0x72D9, 0x72E3, 0x72EF, 0x72F5, 0x72FD, 0x7303,
0x730D, 0x7321, 0x732B, 0x733D, 0x7357, 0x735B, 0x7361, 0x737F,
0x7381, 0x7385, 0x738D, 0x7393, 0x739F, 0x73AB, 0x73BD, 0x73C1,
0x73C9, 0x73DF, 0x73E5, 0x73E7, 0x73F3, 0x7415, 0x741B, 0x742D,
0x7439, 0x743F, 0x7441, 0x745D, 0x746B, 0x747B, 0x7489, 0x748D,
0x749B, 0x74A7, 0x74AB, 0x74B1, 0x74B7, 0x74B9, 0x74DD, 0x74E1,
0x74E7, 0x74FB, 0x7507, 0x751F, 0x7525, 0x753B, 0x753D, 0x754D,
0x755F, 0x756B, 0x7577, 0x7589, 0x758B, 0x7591, 0x7597, 0x759D,
0x75A1, 0x75A7, 0x75B5, 0x75B9, 0x75BB, 0x75D1, 0x75D9, 0x75E5,
0x75EB, 0x75F5, 0x75FB, 0x7603, 0x760F, 0x7621, 0x762D, 0x7633,
0x763D, 0x763F, 0x7655, 0x7663, 0x7669, 0x766F, 0x7673, 0x7685,
0x768B, 0x769F, 0x76B5, 0x76B7, 0x76C3, 0x76DB, 0x76DF, 0x76F1,
0x7703, 0x7705, 0x771B, 0x771D, 0x7721, 0x772D, 0x7735, 0x7741,
0x774B, 0x7759, 0x775D, 0x775F, 0x7771, 0x7781, 0x77A7, 0x77AD,
0x77B3, 0x77B9, 0x77C5, 0x77CF, 0x77D5, 0x77E1, 0x77E9, 0x77EF,
0x77F3, 0x77F9, 0x7807, 0x7825, 0x782B, 0x7835, 0x783D, 0x7853,
0x7859, 0x7861, 0x786D, 0x7877, 0x7879, 0x7883, 0x7885, 0x788B,
0x7895, 0x7897, 0x78A1, 0x78AD, 0x78BF, 0x78D3, 0x78D9, 0x78DD,
0x78E5, 0x78FB, 0x7901, 0x7907, 0x7925, 0x792B, 0x7939, 0x793F,
0x794B, 0x7957, 0x795D, 0x7967, 0x7969, 0x7973, 0x7991, 0x7993,
0x79A3, 0x79AB, 0x79AF, 0x79B1, 0x79B7, 0x79C9, 0x79CD, 0x79CF,
0x79D5, 0x79D9, 0x79F3, 0x79F7, 0x79FF, 0x7A05, 0x7A0F, 0x7A11,
0x7A15, 0x7A1B, 0x7A23, 0x7A27, 0x7A2D, 0x7A4B, 0x7A57, 0x7A59,
0x7A5F, 0x7A65, 0x7A69, 0x7A7D, 0x7A93, 0x7A9B, 0x7A9F, 0x7AA1,
0x7AA5, 0x7AED, 0x7AF5, 0x7AF9, 0x7B01, 0x7B17, 0x7B19, 0x7B1D,
0x7B2B, 0x7B35, 0x7B37, 0x7B3B, 0x7B4F, 0x7B55, 0x7B5F, 0x7B71,
0x7B77, 0x7B8B, 0x7B9B, 0x7BA1, 0x7BA9, 0x7BAF, 0x7BB3, 0x7BC7,
0x7BD3, 0x7BE9, 0x7BEB, 0x7BEF, 0x7BF1, 0x7BFD, 0x7C07, 0x7C19,
0x7C1B, 0x7C31, 0x7C37, 0x7C49, 0x7C67, 0x7C69, 0x7C73, 0x7C81,
0x7C8B, 0x7C93, 0x7CA3, 0x7CD5, 0x7CDB, 0x7CE5, 0x7CED, 0x7CF7,
0x7D03, 0x7D09, 0x7D1B, 0x7D1D, 0x7D33, 0x7D39, 0x7D3B, 0x7D3F,
0x7D45, 0x7D4D, 0x7D53, 0x7D59, 0x7D63, 0x7D75, 0x7D77, 0x7D8D,
0x7D8F, 0x7D9F, 0x7DAD, 0x7DB7, 0x7DBD, 0x7DBF, 0x7DCB, 0x7DD5,
0x7DE9, 0x7DED, 0x7DFB, 0x7E01, 0x7E05, 0x7E29, 0x7E2B, 0x7E2F,
0x7E35, 0x7E41, 0x7E43, 0x7E47, 0x7E55, 0x7E61, 0x7E67, 0x7E6B,
0x7E71, 0x7E73, 0x7E79, 0x7E7D, 0x7E91, 0x7E9B, 0x7E9D, 0x7EA7,
0x7EAD, 0x7EB9, 0x7EBB, 0x7ED3, 0x7EDF, 0x7EEB, 0x7EF1, 0x7EF7,
0x7EFB, 0x7F13, 0x7F15, 0x7F19, 0x7F31, 0x7F33, 0x7F39, 0x7F3D,
0x7F43, 0x7F4B, 0x7F5B, 0x7F61, 0x7F63, 0x7F6D, 0x7F79, 0x7F87,
0x7F8D, 0x7FAF, 0x7FB5, 0x7FC3, 0x7FC9, 0x7FCD, 0x7FCF, 0x7FED,
0x8003, 0x800B, 0x800F, 0x8015, 0x801D, 0x8021, 0x8023, 0x803F,
0x8041, 0x8047, 0x804B, 0x8065, 0x8077, 0x808D, 0x808F, 0x8095,
0x80A5, 0x80AB, 0x80AD, 0x80BD, 0x80C9, 0x80CB, 0x80D7, 0x80DB,
0x80E1, 0x80E7, 0x80F5, 0x80FF, 0x8105, 0x810D, 0x8119, 0x811D,
0x812F, 0x8131, 0x813B, 0x8143, 0x8153, 0x8159, 0x815F, 0x817D,
0x817F, 0x8189, 0x819B, 0x819D, 0x81A7, 0x81AF, 0x81B3, 0x81BB,
0x81C7, 0x81DF, 0x8207, 0x8209, 0x8215, 0x821F, 0x8225, 0x8231,
0x8233, 0x823F, 0x8243, 0x8245, 0x8249, 0x824F, 0x8261, 0x826F,
0x827B, 0x8281, 0x8285, 0x8293, 0x82B1, 0x82B5, 0x82BD, 0x82C7,
0x82CF, 0x82D5, 0x82DF, 0x82F1, 0x82F9, 0x82FD, 0x830B, 0x831B,
0x8321, 0x8329, 0x832D, 0x8333, 0x8335, 0x833F, 0x8341, 0x834D,
0x8351, 0x8353, 0x8357, 0x835D, 0x8365, 0x8369, 0x836F, 0x838F,
0x83A7, 0x83B1, 0x83B9, 0x83CB, 0x83D5, 0x83D7, 0x83DD, 0x83E7,
0x83E9, 0x83ED, 0x83FF, 0x8405, 0x8411, 0x8413, 0x8423, 0x8425,
0x843B, 0x8441, 0x8447, 0x844F, 0x8461, 0x8465, 0x8477, 0x8483,
0x848B, 0x8491, 0x8495, 0x84A9, 0x84AF, 0x84CD, 0x84E3, 0x84EF,
0x84F1, 0x84F7, 0x8509, 0x850D, 0x854B, 0x854F, 0x8551, 0x855D,
0x8563, 0x856D, 0x856F, 0x857B, 0x8587, 0x85A3, 0x85A5, 0x85A9,
0x85B7, 0x85CD, 0x85D3, 0x85D5, 0x85DB, 0x85E1, 0x85EB, 0x85F9,
0x85FD, 0x85FF, 0x8609, 0x860F, 0x8617, 0x8621, 0x862F, 0x8639,
0x863F, 0x8641, 0x864D, 0x8663, 0x8675, 0x867D, 0x8687, 0x8699,
0x86A5, 0x86A7, 0x86B3, 0x86B7, 0x86C3, 0x86C5, 0x86CF, 0x86D1,
0x86D7, 0x86E9, 0x86EF, 0x86F5, 0x8717, 0x871D, 0x871F, 0x872B,
0x872F, 0x8735, 0x8747, 0x8759, 0x875B, 0x876B, 0x8771, 0x8777,
0x877F, 0x8785, 0x878F, 0x87A1, 0x87A9, 0x87B3, 0x87BB, 0x87C5,
0x87C7, 0x87CB, 0x87DD, 0x87F7, 0x8803, 0x8819, 0x881B, 0x881F,
0x8821, 0x8837, 0x883D, 0x8843, 0x8851, 0x8861, 0x8867, 0x887B,
0x8885, 0x8891, 0x8893, 0x88A5, 0x88CF, 0x88D3, 0x88EB, 0x88ED,
0x88F3, 0x88FD, 0x8909, 0x890B, 0x8911, 0x891B, 0x8923, 0x8927,
0x892D, 0x8939, 0x8945, 0x894D, 0x8951, 0x8957, 0x8963, 0x8981,
0x8995, 0x899B, 0x89B3, 0x89B9, 0x89C3, 0x89CF, 0x89D1, 0x89DB,
0x89EF, 0x89F5, 0x89FB, 0x89FF, 0x8A0B, 0x8A19, 0x8A23, 0x8A35,
0x8A41, 0x8A49, 0x8A4F, 0x8A5B, 0x8A5F, 0x8A6D, 0x8A77, 0x8A79,
0x8A85, 0x8AA3, 0x8AB3, 0x8AB5, 0x8AC1, 0x8AC7, 0x8ACB, 0x8ACD,
0x8AD1, 0x8AD7, 0x8AF1, 0x8AF5, 0x8B07, 0x8B09, 0x8B0D, 0x8B13,
0x8B21, 0x8B57, 0x8B5D, 0x8B91, 0x8B93, 0x8BA3, 0x8BA9, 0x8BAF,
0x8BBB, 0x8BD5, 0x8BD9, 0x8BDB, 0x8BE1, 0x8BF7, 0x8BFD, 0x8BFF,
0x8C0B, 0x8C17, 0x8C1D, 0x8C27, 0x8C39, 0x8C3B, 0x8C47, 0x8C53,
0x8C5D, 0x8C6F, 0x8C7B, 0x8C81, 0x8C89, 0x8C8F, 0x8C99, 0x8C9F,
0x8CA7, 0x8CAB, 0x8CAD, 0x8CB1, 0x8CC5, 0x8CDD, 0x8CE3, 0x8CE9,
0x8CF3, 0x8D01, 0x8D0B, 0x8D0D, 0x8D23, 0x8D29, 0x8D37, 0x8D41,
0x8D5B, 0x8D5F, 0x8D71, 0x8D79, 0x8D85, 0x8D91, 0x8D9B, 0x8DA7,
0x8DAD, 0x8DB5, 0x8DC5, 0x8DCB, 0x8DD3, 0x8DD9, 0x8DDF, 0x8DF5,
0x8DF7, 0x8E01, 0x8E15, 0x8E1F, 0x8E25, 0x8E51, 0x8E63, 0x8E69,
0x8E73, 0x8E75, 0x8E79, 0x8E7F, 0x8E8D, 0x8E91, 0x8EAB, 0x8EAF,
0x8EB1, 0x8EBD, 0x8EC7, 0x8ECF, 0x8ED3, 0x8EDB, 0x8EE7, 0x8EEB,
0x8EF7, 0x8EFF, 0x8F15, 0x8F1D, 0x8F23, 0x8F2D, 0x8F3F, 0x8F45,
0x8F4B, 0x8F53, 0x8F59, 0x8F65, 0x8F69, 0x8F71, 0x8F83, 0x8F8D,
0x8F99, 0x8F9F, 0x8FAB, 0x8FAD, 0x8FB3, 0x8FB7, 0x8FB9, 0x8FC9,
0x8FD5, 0x8FE1, 0x8FEF, 0x8FF9, 0x9007, 0x900D, 0x9017, 0x9023,
0x9025, 0x9031, 0x9037, 0x903B, 0x9041, 0x9043, 0x904F, 0x9053,
0x906D, 0x9073, 0x9085, 0x908B, 0x9095, 0x909B, 0x909D, 0x90AF,
0x90B9, 0x90C1, 0x90C5, 0x90DF, 0x90E9, 0x90FD, 0x9103, 0x9113,
0x9127, 0x9133, 0x913D, 0x9145, 0x914F, 0x9151, 0x9161, 0x9167,
0x917B, 0x9185, 0x9199, 0x919D, 0x91BB, 0x91BD, 0x91C1, 0x91C9,
0x91D9, 0x91DB, 0x91ED, 0x91F1, 0x91F3, 0x91F9, 0x9203, 0x9215,
0x9221, 0x922F, 0x9241, 0x9247, 0x9257, 0x926B, 0x9271, 0x9275,
0x927D, 0x9283, 0x9287, 0x928D, 0x9299, 0x92A1, 0x92AB, 0x92AD,
0x92B9, 0x92BF, 0x92C3, 0x92C5, 0x92CB, 0x92D5, 0x92D7, 0x92E7,
0x92F3, 0x9301, 0x930B, 0x9311, 0x9319, 0x931F, 0x933B, 0x933D,
0x9343, 0x9355, 0x9373, 0x9395, 0x9397, 0x93A7, 0x93B3, 0x93B5,
0x93C7, 0x93D7, 0x93DD, 0x93E5, 0x93EF, 0x93F7, 0x9401, 0x9409,
0x9413, 0x943F, 0x9445, 0x944B, 0x944F, 0x9463, 0x9467, 0x9469,
0x946D, 0x947B, 0x9497, 0x949F, 0x94A5, 0x94B5, 0x94C3, 0x94E1,
0x94E7, 0x9505, 0x9509, 0x9517, 0x9521, 0x9527, 0x952D, 0x9535,
0x9539, 0x954B, 0x9557, 0x955D, 0x955F, 0x9575, 0x9581, 0x9589,
0x958F, 0x959B, 0x959F, 0x95AD, 0x95B1, 0x95B7, 0x95B9, 0x95BD,
0x95CF, 0x95E3, 0x95E9, 0x95F9, 0x961F, 0x962F, 0x9631, 0x9635,
0x963B, 0x963D, 0x9665, 0x968F, 0x969D, 0x96A1, 0x96A7, 0x96A9,
0x96C1, 0x96CB, 0x96D1, 0x96D3, 0x96E5, 0x96EF, 0x96FB, 0x96FD,
0x970D, 0x970F, 0x9715, 0x9725, 0x972B, 0x9733, 0x9737, 0x9739,
0x9743, 0x9749, 0x9751, 0x975B, 0x975D, 0x976F, 0x977F, 0x9787,
0x9793, 0x97A5, 0x97B1, 0x97B7, 0x97C3, 0x97CD, 0x97D3, 0x97D9,
0x97EB, 0x97F7, 0x9805, 0x9809, 0x980B, 0x9815, 0x9829, 0x982F,
0x983B, 0x9841, 0x9851, 0x986B, 0x986F, 0x9881, 0x9883, 0x9887,
0x98A7, 0x98B1, 0x98B9, 0x98BF, 0x98C3, 0x98C9, 0x98CF, 0x98DD,
0x98E3, 0x98F5, 0x98F9, 0x98FB, 0x990D, 0x9917, 0x991F, 0x9929,
0x9931, 0x993B, 0x993D, 0x9941, 0x9947, 0x9949, 0x9953, 0x997D,
0x9985, 0x9991, 0x9995, 0x999B, 0x99AD, 0x99AF, 0x99BF, 0x99C7,
0x99CB, 0x99CD, 0x99D7, 0x99E5, 0x99F1, 0x99FB, 0x9A0F, 0x9A13,
0x9A1B, 0x9A25, 0x9A4B, 0x9A4F, 0x9A55, 0x9A57, 0x9A61, 0x9A75,
0x9A7F, 0x9A8B, 0x9A91, 0x9A9D, 0x9AB7, 0x9AC3, 0x9AC7, 0x9ACF,
0x9AEB, 0x9AF3, 0x9AF7, 0x9AFF, 0x9B17, 0x9B1D, 0x9B27, 0x9B2F,
0x9B35, 0x9B45, 0x9B51, 0x9B59, 0x9B63, 0x9B6F, 0x9B77, 0x9B8D,
0x9B93, 0x9B95, 0x9B9F, 0x9BA1, 0x9BA7, 0x9BB1, 0x9BB7, 0x9BBD,
0x9BC5, 0x9BCB, 0x9BCF, 0x9BDD, 0x9BF9, 0x9C01, 0x9C11, 0x9C23,
0x9C2B, 0x9C2F, 0x9C35, 0x9C49, 0x9C4D, 0x9C5F, 0x9C65, 0x9C67,
0x9C7F, 0x9C97, 0x9C9D, 0x9CA3, 0x9CAF, 0x9CBB, 0x9CBF, 0x9CC1,
0x9CD7, 0x9CD9, 0x9CE3, 0x9CE9, 0x9CF1, 0x9CFD, 0x9D01, 0x9D15,
0x9D27, 0x9D2D, 0x9D31, 0x9D3D, 0x9D55, 0x9D5B, 0x9D61, 0x9D97,
0x9D9F, 0x9DA5, 0x9DA9, 0x9DC3, 0x9DE7, 0x9DEB, 0x9DED, 0x9DF1,
0x9E0B, 0x9E17, 0x9E23, 0x9E27, 0x9E2D, 0x9E33, 0x9E3B, 0x9E47,
0x9E51, 0x9E53, 0x9E5F, 0x9E6F, 0x9E81, 0x9E87, 0x9E8F, 0x9E95,
0x9EA1, 0x9EB3, 0x9EBD, 0x9EBF, 0x9EF5, 0x9EF9, 0x9EFB, 0x9F05,
0x9F23, 0x9F2F, 0x9F37, 0x9F3B, 0x9F43, 0x9F53, 0x9F61, 0x9F6D,
0x9F73, 0x9F77, 0x9F7D, 0x9F89, 0x9F8F, 0x9F91, 0x9F95, 0x9FA3,
0x9FAF, 0x9FB3, 0x9FC1, 0x9FC7, 0x9FDF, 0x9FE5, 0x9FEB, 0x9FF5,
0xA001, 0xA00D, 0xA021, 0xA033, 0xA039, 0xA03F, 0xA04F, 0xA057,
0xA05B, 0xA061, 0xA075, 0xA079, 0xA099, 0xA09D, 0xA0AB, 0xA0B5,
0xA0B7, 0xA0BD, 0xA0C9, 0xA0D9, 0xA0DB, 0xA0DF, 0xA0E5, 0xA0F1,
0xA0F3, 0xA0FD, 0xA105, 0xA10B, 0xA10F, 0xA111, 0xA11B, 0xA129,
0xA12F, 0xA135, 0xA141, 0xA153, 0xA175, 0xA17D, 0xA187, 0xA18D,
0xA1A5, 0xA1AB, 0xA1AD, 0xA1B7, 0xA1C3, 0xA1C5, 0xA1E3, 0xA1ED,
0xA1FB, 0xA207, 0xA213, 0xA223, 0xA229, 0xA22F, 0xA231, 0xA243,
0xA247, 0xA24D, 0xA26B, 0xA279, 0xA27D, 0xA283, 0xA289, 0xA28B,
0xA291, 0xA295, 0xA29B, 0xA2A9, 0xA2AF, 0xA2B3, 0xA2BB, 0xA2C5,
0xA2D1, 0xA2D7, 0xA2F7, 0xA301, 0xA309, 0xA31F, 0xA321, 0xA32B,
0xA331, 0xA349, 0xA351, 0xA355, 0xA373, 0xA379, 0xA37B, 0xA387,
0xA397, 0xA39F, 0xA3A5, 0xA3A9, 0xA3AF, 0xA3B7, 0xA3C7, 0xA3D5,
0xA3DB, 0xA3E1, 0xA3E5, 0xA3E7, 0xA3F1, 0xA3FD, 0xA3FF, 0xA40F,
0xA41D, 0xA421, 0xA423, 0xA427, 0xA43B, 0xA44D, 0xA457, 0xA459,
0xA463, 0xA469, 0xA475, 0xA493, 0xA49B, 0xA4AD, 0xA4B9, 0xA4C3,
0xA4C5, 0xA4CB, 0xA4D1, 0xA4D5, 0xA4E1, 0xA4ED, 0xA4EF, 0xA4F3,
0xA4FF, 0xA511, 0xA529, 0xA52B, 0xA535, 0xA53B, 0xA543, 0xA553,
0xA55B, 0xA561, 0xA56D, 0xA577, 0xA585, 0xA58B, 0xA597, 0xA59D,
0xA5A3, 0xA5A7, 0xA5A9, 0xA5C1, 0xA5C5, 0xA5CB, 0xA5D3, 0xA5D9,
0xA5DD, 0xA5DF, 0xA5E3, 0xA5E9, 0xA5F7, 0xA5FB, 0xA603, 0xA60D,
0xA625, 0xA63D, 0xA649, 0xA64B, 0xA651, 0xA65D, 0xA673, 0xA691,
0xA693, 0xA699, 0xA6AB, 0xA6B5, 0xA6BB, 0xA6C1, 0xA6C9, 0xA6CD,
0xA6CF, 0xA6D5, 0xA6DF, 0xA6E7, 0xA6F1, 0xA6F7, 0xA6FF, 0xA70F,
0xA715, 0xA723, 0xA729, 0xA72D, 0xA745, 0xA74D, 0xA757, 0xA759,
0xA765, 0xA76B, 0xA76F, 0xA793, 0xA795, 0xA7AB, 0xA7B1, 0xA7B9,
0xA7BF, 0xA7C9, 0xA7D1, 0xA7D7, 0xA7E3, 0xA7ED, 0xA7FB, 0xA805,
0xA80B, 0xA81D, 0xA829, 0xA82B, 0xA837, 0xA83B, 0xA855, 0xA85F,
0xA86D, 0xA87D, 0xA88F, 0xA897, 0xA8A9, 0xA8B5, 0xA8C1, 0xA8C7,
0xA8D7, 0xA8E5, 0xA8FD, 0xA907, 0xA913, 0xA91B, 0xA931, 0xA937,
0xA939, 0xA943, 0xA97F, 0xA985, 0xA987, 0xA98B, 0xA993, 0xA9A3,
0xA9B1, 0xA9BB, 0xA9C1, 0xA9D9, 0xA9DF, 0xA9EB, 0xA9FD, 0xAA15,
0xAA17, 0xAA35, 0xAA39, 0xAA3B, 0xAA47, 0xAA4D, 0xAA57, 0xAA59,
0xAA5D, 0xAA6B, 0xAA71, 0xAA81, 0xAA83, 0xAA8D, 0xAA95, 0xAAAB,
0xAABF, 0xAAC5, 0xAAC9, 0xAAE9, 0xAAEF, 0xAB01, 0xAB05, 0xAB07,
0xAB0B, 0xAB0D, 0xAB11, 0xAB19, 0xAB4D, 0xAB5B, 0xAB71, 0xAB73,
0xAB89, 0xAB9D, 0xABA7, 0xABAF, 0xABB9, 0xABBB, 0xABC1, 0xABC5,
0xABD3, 0xABD7, 0xABDD, 0xABF1, 0xABF5, 0xABFB, 0xABFD, 0xAC09,
0xAC15, 0xAC1B, 0xAC27, 0xAC37, 0xAC39, 0xAC45, 0xAC4F, 0xAC57,
0xAC5B, 0xAC61, 0xAC63, 0xAC7F, 0xAC8B, 0xAC93, 0xAC9D, 0xACA9,
0xACAB, 0xACAF, 0xACBD, 0xACD9, 0xACE1, 0xACE7, 0xACEB, 0xACED,
0xACF1, 0xACF7, 0xACF9, 0xAD05, 0xAD3F, 0xAD45, 0xAD53, 0xAD5D,
0xAD5F, 0xAD65, 0xAD81, 0xADA1, 0xADA5, 0xADC3, 0xADCB, 0xADD1,
0xADD5, 0xADDB, 0xADE7, 0xADF3, 0xADF5, 0xADF9, 0xADFF, 0xAE05,
0xAE13, 0xAE23, 0xAE2B, 0xAE49, 0xAE4D, 0xAE4F, 0xAE59, 0xAE61,
0xAE67, 0xAE6B, 0xAE71, 0xAE8B, 0xAE8F, 0xAE9B, 0xAE9D, 0xAEA7,
0xAEB9, 0xAEC5, 0xAED1, 0xAEE3, 0xAEE5, 0xAEE9, 0xAEF5, 0xAEFD,
0xAF09, 0xAF13, 0xAF27, 0xAF2B, 0xAF33, 0xAF43, 0xAF4F, 0xAF57,
0xAF5D, 0xAF6D, 0xAF75, 0xAF7F, 0xAF8B, 0xAF99, 0xAF9F, 0xAFA3,
0xAFAB, 0xAFB7, 0xAFBB, 0xAFCF, 0xAFD5, 0xAFFD, 0xB005, 0xB015,
0xB01B, 0xB03F, 0xB041, 0xB047, 0xB04B, 0xB051, 0xB053, 0xB069,
0xB07B, 0xB07D, 0xB087, 0xB08D, 0xB0B1, 0xB0BF, 0xB0CB, 0xB0CF,
0xB0E1, 0xB0E9, 0xB0ED, 0xB0FB, 0xB105, 0xB107, 0xB111, 0xB119,
0xB11D, 0xB11F, 0xB131, 0xB141, 0xB14D, 0xB15B, 0xB165, 0xB173,
0xB179, 0xB17F, 0xB1A9, 0xB1B3, 0xB1B9, 0xB1BF, 0xB1D3, 0xB1DD,
0xB1E5, 0xB1F1, 0xB1F5, 0xB201, 0xB213, 0xB215, 0xB21F, 0xB22D,
0xB23F, 0xB249, 0xB25B, 0xB263, 0xB269, 0xB26D, 0xB27B, 0xB281,
0xB28B, 0xB2A9, 0xB2B7, 0xB2BD, 0xB2C3, 0xB2C7, 0xB2D3, 0xB2F9,
0xB2FD, 0xB2FF, 0xB303, 0xB309, 0xB311, 0xB31D, 0xB327, 0xB32D,
0xB33F, 0xB345, 0xB377, 0xB37D, 0xB381, 0xB387, 0xB393, 0xB39B,
0xB3A5, 0xB3C5, 0xB3CB, 0xB3E1, 0xB3E3, 0xB3ED, 0xB3F9, 0xB40B,
0xB40D, 0xB413, 0xB417, 0xB435, 0xB43D, 0xB443, 0xB449, 0xB45B,
0xB465, 0xB467, 0xB46B, 0xB477, 0xB48B, 0xB495, 0xB49D, 0xB4B5,
0xB4BF, 0xB4C1, 0xB4C7, 0xB4DD, 0xB4E3, 0xB4E5, 0xB4F7, 0xB501,
0xB50D, 0xB50F, 0xB52D, 0xB53F, 0xB54B, 0xB567, 0xB569, 0xB56F,
0xB573, 0xB579, 0xB587, 0xB58D, 0xB599, 0xB5A3, 0xB5AB, 0xB5AF,
0xB5BB, 0xB5D5, 0xB5DF, 0xB5E7, 0xB5ED, 0xB5FD, 0xB5FF, 0xB609,
0xB61B, 0xB629, 0xB62F, 0xB633, 0xB639, 0xB647, 0xB657, 0xB659,
0xB65F, 0xB663, 0xB66F, 0xB683, 0xB687, 0xB69B, 0xB69F, 0xB6A5,
0xB6B1, 0xB6B3, 0xB6D7, 0xB6DB, 0xB6E1, 0xB6E3, 0xB6ED, 0xB6EF,
0xB705, 0xB70D, 0xB713, 0xB71D, 0xB729, 0xB735, 0xB747, 0xB755,
0xB76D, 0xB791, 0xB795, 0xB7A9, 0xB7C1, 0xB7CB, 0xB7D1, 0xB7D3,
0xB7EF, 0xB7F5, 0xB807, 0xB80F, 0xB813, 0xB819, 0xB821, 0xB827,
0xB82B, 0xB82D, 0xB839, 0xB855, 0xB867, 0xB875, 0xB885, 0xB893,
0xB8A5, 0xB8AF, 0xB8B7, 0xB8BD, 0xB8C1, 0xB8C7, 0xB8CD, 0xB8D5,
0xB8EB, 0xB8F7, 0xB8F9, 0xB903, 0xB915, 0xB91B, 0xB91D, 0xB92F,
0xB939, 0xB93B, 0xB947, 0xB951, 0xB963, 0xB983, 0xB989, 0xB98D,
0xB993, 0xB999, 0xB9A1, 0xB9A7, 0xB9AD, 0xB9B7, 0xB9CB, 0xB9D1,
0xB9DD, 0xB9E7, 0xB9EF, 0xB9F9, 0xBA07, 0xBA0D, 0xBA17, 0xBA25,
0xBA29, 0xBA2B, 0xBA41, 0xBA53, 0xBA55, 0xBA5F, 0xBA61, 0xBA65,
0xBA79, 0xBA7D, 0xBA7F, 0xBAA1, 0xBAA3, 0xBAAF, 0xBAB5, 0xBABF,
0xBAC1, 0xBACB, 0xBADD, 0xBAE3, 0xBAF1, 0xBAFD, 0xBB09, 0xBB1F,
0xBB27, 0xBB2D, 0xBB3D, 0xBB43, 0xBB4B, 0xBB4F, 0xBB5B, 0xBB61,
0xBB69, 0xBB6D, 0xBB91, 0xBB97, 0xBB9D, 0xBBB1, 0xBBC9, 0xBBCF,
0xBBDB, 0xBBED, 0xBBF7, 0xBBF9, 0xBC03, 0xBC1D, 0xBC23, 0xBC33,
0xBC3B, 0xBC41, 0xBC45, 0xBC5D, 0xBC6F, 0xBC77, 0xBC83, 0xBC8F,
0xBC99, 0xBCAB, 0xBCB7, 0xBCB9, 0xBCD1, 0xBCD5, 0xBCE1, 0xBCF3,
0xBCFF, 0xBD0D, 0xBD17, 0xBD19, 0xBD1D, 0xBD35, 0xBD41, 0xBD4F,
0xBD59, 0xBD5F, 0xBD61, 0xBD67, 0xBD6B, 0xBD71, 0xBD8B, 0xBD8F,
0xBD95, 0xBD9B, 0xBD9D, 0xBDB3, 0xBDBB, 0xBDCD, 0xBDD1, 0xBDE3,
0xBDEB, 0xBDEF, 0xBE07, 0xBE09, 0xBE15, 0xBE21, 0xBE25, 0xBE27,
0xBE5B, 0xBE5D, 0xBE6F, 0xBE75, 0xBE79, 0xBE7F, 0xBE8B, 0xBE8D,
0xBE93, 0xBE9F, 0xBEA9, 0xBEB1, 0xBEB5, 0xBEB7, 0xBECF, 0xBED9,
0xBEDB, 0xBEE5, 0xBEE7, 0xBEF3, 0xBEF9, 0xBF0B, 0xBF33, 0xBF39,
0xBF4D, 0xBF5D, 0xBF5F, 0xBF6B, 0xBF71, 0xBF7B, 0xBF87, 0xBF89,
0xBF8D, 0xBF93, 0xBFA1, 0xBFAD, 0xBFB9, 0xBFCF, 0xBFD5, 0xBFDD,
0xBFE1, 0xBFE3, 0xBFF3, 0xC005, 0xC011, 0xC013, 0xC019, 0xC029,
0xC02F, 0xC031, 0xC037, 0xC03B, 0xC047, 0xC065, 0xC06D, 0xC07D,
0xC07F, 0xC091, 0xC09B, 0xC0B3, 0xC0B5, 0xC0BB, 0xC0D3, 0xC0D7,
0xC0D9, 0xC0EF, 0xC0F1, 0xC101, 0xC103, 0xC109, 0xC115, 0xC119,
0xC12B, 0xC133, 0xC137, 0xC145, 0xC149, 0xC15B, 0xC173, 0xC179,
0xC17B, 0xC181, 0xC18B, 0xC18D, 0xC197, 0xC1BD, 0xC1C3, 0xC1CD,
0xC1DB, 0xC1E1, 0xC1E7, 0xC1FF, 0xC203, 0xC205, 0xC211, 0xC221,
0xC22F, 0xC23F, 0xC24B, 0xC24D, 0xC253, 0xC25D, 0xC277, 0xC27B,
0xC27D, 0xC289, 0xC28F, 0xC293, 0xC29F, 0xC2A7, 0xC2B3, 0xC2BD,
0xC2CF, 0xC2D5, 0xC2E3, 0xC2FF, 0xC301, 0xC307, 0xC311, 0xC313,
0xC317, 0xC325, 0xC347, 0xC349, 0xC34F, 0xC365, 0xC367, 0xC371,
0xC37F, 0xC383, 0xC385, 0xC395, 0xC39D, 0xC3A7, 0xC3AD, 0xC3B5,
0xC3BF, 0xC3C7, 0xC3CB, 0xC3D1, 0xC3D3, 0xC3E3, 0xC3E9, 0xC3EF,
0xC401, 0xC41F, 0xC42D, 0xC433, 0xC437, 0xC455, 0xC457, 0xC461,
0xC46F, 0xC473, 0xC487, 0xC491, 0xC499, 0xC49D, 0xC4A5, 0xC4B7,
0xC4BB, 0xC4C9, 0xC4CF, 0xC4D3, 0xC4EB, 0xC4F1, 0xC4F7, 0xC509,
0xC51B, 0xC51D, 0xC541, 0xC547, 0xC551, 0xC55F, 0xC56B, 0xC56F,
0xC575, 0xC577, 0xC595, 0xC59B, 0xC59F, 0xC5A1, 0xC5A7, 0xC5C3,
0xC5D7, 0xC5DB, 0xC5EF, 0xC5FB, 0xC613, 0xC623, 0xC635, 0xC641,
0xC64F, 0xC655, 0xC659, 0xC665, 0xC685, 0xC691, 0xC697, 0xC6A1,
0xC6A9, 0xC6B3, 0xC6B9, 0xC6CB, 0xC6CD, 0xC6DD, 0xC6EB, 0xC6F1,
0xC707, 0xC70D, 0xC719, 0xC71B, 0xC72D, 0xC731, 0xC739, 0xC757,
0xC763, 0xC767, 0xC773, 0xC775, 0xC77F, 0xC7A5, 0xC7BB, 0xC7BD,
0xC7C1, 0xC7CF, 0xC7D5, 0xC7E1, 0xC7F9, 0xC7FD, 0xC7FF, 0xC803,
0xC811, 0xC81D, 0xC827, 0xC829, 0xC839, 0xC83F, 0xC853, 0xC857,
0xC86B, 0xC881, 0xC88D, 0xC88F, 0xC893, 0xC895, 0xC8A1, 0xC8B7,
0xC8CF, 0xC8D5, 0xC8DB, 0xC8DD, 0xC8E3, 0xC8E7, 0xC8ED, 0xC8EF,
0xC8F9, 0xC905, 0xC911, 0xC917, 0xC919, 0xC91F, 0xC92F, 0xC937,
0xC93D, 0xC941, 0xC953, 0xC95F, 0xC96B, 0xC979, 0xC97D, 0xC989,
0xC98F, 0xC997, 0xC99D, 0xC9AF, 0xC9B5, 0xC9BF, 0xC9CB, 0xC9D9,
0xC9DF, 0xC9E3, 0xC9EB, 0xCA01, 0xCA07, 0xCA09, 0xCA25, 0xCA37,
0xCA39, 0xCA4B, 0xCA55, 0xCA5B, 0xCA69, 0xCA73, 0xCA75, 0xCA7F,
0xCA8D, 0xCA93, 0xCA9D, 0xCA9F, 0xCAB5, 0xCABB, 0xCAC3, 0xCAC9,
0xCAD9, 0xCAE5, 0xCAED, 0xCB03, 0xCB05, 0xCB09, 0xCB17, 0xCB29,
0xCB35, 0xCB3B, 0xCB53, 0xCB59, 0xCB63, 0xCB65, 0xCB71, 0xCB87,
0xCB99, 0xCB9F, 0xCBB3, 0xCBB9, 0xCBC3, 0xCBD1, 0xCBD5, 0xCBD7,
0xCBDD, 0xCBE9, 0xCBFF, 0xCC0D, 0xCC19, 0xCC1D, 0xCC23, 0xCC2B,
0xCC41, 0xCC43, 0xCC4D, 0xCC59, 0xCC61, 0xCC89, 0xCC8B, 0xCC91,
0xCC9B, 0xCCA3, 0xCCA7, 0xCCD1, 0xCCE5, 0xCCE9, 0xCD09, 0xCD15,
0xCD1F, 0xCD25, 0xCD31, 0xCD3D, 0xCD3F, 0xCD49, 0xCD51, 0xCD57,
0xCD5B, 0xCD63, 0xCD67, 0xCD81, 0xCD93, 0xCD97, 0xCD9F, 0xCDBB,
0xCDC1, 0xCDD3, 0xCDD9, 0xCDE5, 0xCDE7, 0xCDF1, 0xCDF7, 0xCDFD,
0xCE0B, 0xCE15, 0xCE21, 0xCE2F, 0xCE47, 0xCE4D, 0xCE51, 0xCE65,
0xCE7B, 0xCE7D, 0xCE8F, 0xCE93, 0xCE99, 0xCEA5, 0xCEA7, 0xCEB7,
0xCEC9, 0xCED7, 0xCEDD, 0xCEE3, 0xCEE7, 0xCEED, 0xCEF5, 0xCF07,
0xCF0B, 0xCF19, 0xCF37, 0xCF3B, 0xCF4D, 0xCF55, 0xCF5F, 0xCF61,
0xCF65, 0xCF6D, 0xCF79, 0xCF7D, 0xCF89, 0xCF9B, 0xCF9D, 0xCFA9,
0xCFB3, 0xCFB5, 0xCFC5, 0xCFCD, 0xCFD1, 0xCFEF, 0xCFF1, 0xCFF7,
0xD013, 0xD015, 0xD01F, 0xD021, 0xD033, 0xD03D, 0xD04B, 0xD04F,
0xD069, 0xD06F, 0xD081, 0xD085, 0xD099, 0xD09F, 0xD0A3, 0xD0AB,
0xD0BD, 0xD0C1, 0xD0CD, 0xD0E7, 0xD0FF, 0xD103, 0xD117, 0xD12D,
0xD12F, 0xD141, 0xD157, 0xD159, 0xD15D, 0xD169, 0xD16B, 0xD171,
0xD177, 0xD17D, 0xD181, 0xD187, 0xD195, 0xD199, 0xD1B1, 0xD1BD,
0xD1C3, 0xD1D5, 0xD1D7, 0xD1E3, 0xD1FF, 0xD20D, 0xD211, 0xD217,
0xD21F, 0xD235, 0xD23B, 0xD247, 0xD259, 0xD261, 0xD265, 0xD279,
0xD27F, 0xD283, 0xD289, 0xD28B, 0xD29D, 0xD2A3, 0xD2A7, 0xD2B3,
0xD2BF, 0xD2C7, 0xD2E3, 0xD2E9, 0xD2F1, 0xD2FB, 0xD2FD, 0xD315,
0xD321, 0xD32B, 0xD343, 0xD34B, 0xD355, 0xD369, 0xD375, 0xD37B,
0xD387, 0xD393, 0xD397, 0xD3A5, 0xD3B1, 0xD3C9, 0xD3EB, 0xD3FD,
0xD405, 0xD40F, 0xD415, 0xD427, 0xD42F, 0xD433, 0xD43B, 0xD44B,
0xD459, 0xD45F, 0xD463, 0xD469, 0xD481, 0xD483, 0xD489, 0xD48D,
0xD493, 0xD495, 0xD4A5, 0xD4AB, 0xD4B1, 0xD4C5, 0xD4DD, 0xD4E1,
0xD4E3, 0xD4E7, 0xD4F5, 0xD4F9, 0xD50B, 0xD50D, 0xD513, 0xD51F,
0xD523, 0xD531, 0xD535, 0xD537, 0xD549, 0xD559, 0xD55F, 0xD565,
0xD567, 0xD577, 0xD58B, 0xD591, 0xD597, 0xD5B5, 0xD5B9, 0xD5C1,
0xD5C7, 0xD5DF, 0xD5EF, 0xD5F5, 0xD5FB, 0xD603, 0xD60F, 0xD62D,
0xD631, 0xD643, 0xD655, 0xD65D, 0xD661, 0xD67B, 0xD685, 0xD687,
0xD69D, 0xD6A5, 0xD6AF, 0xD6BD, 0xD6C3, 0xD6C7, 0xD6D9, 0xD6E1,
0xD6ED, 0xD709, 0xD70B, 0xD711, 0xD715, 0xD721, 0xD727, 0xD73F,
0xD745, 0xD74D, 0xD757, 0xD76B, 0xD77B, 0xD783, 0xD7A1, 0xD7A7,
0xD7AD, 0xD7B1, 0xD7B3, 0xD7BD, 0xD7CB, 0xD7D1, 0xD7DB, 0xD7FB,
0xD811, 0xD823, 0xD825, 0xD829, 0xD82B, 0xD82F, 0xD837, 0xD84D,
0xD855, 0xD867, 0xD873, 0xD88F, 0xD891, 0xD8A1, 0xD8AD, 0xD8BF,
0xD8CD, 0xD8D7, 0xD8E9, 0xD8F5, 0xD8FB, 0xD91B, 0xD925, 0xD933,
0xD939, 0xD943, 0xD945, 0xD94F, 0xD951, 0xD957, 0xD96D, 0xD96F,
0xD973, 0xD979, 0xD981, 0xD98B, 0xD991, 0xD99F, 0xD9A5, 0xD9A9,
0xD9B5, 0xD9D3, 0xD9EB, 0xD9F1, 0xD9F7, 0xD9FF, 0xDA05, 0xDA09,
0xDA0B, 0xDA0F, 0xDA15, 0xDA1D, 0xDA23, 0xDA29, 0xDA3F, 0xDA51,
0xDA59, 0xDA5D, 0xDA5F, 0xDA71, 0xDA77, 0xDA7B, 0xDA7D, 0xDA8D,
0xDA9F, 0xDAB3, 0xDABD, 0xDAC3, 0xDAC9, 0xDAE7, 0xDAE9, 0xDAF5,
0xDB11, 0xDB17, 0xDB1D, 0xDB23, 0xDB25, 0xDB31, 0xDB3B, 0xDB43,
0xDB55, 0xDB67, 0xDB6B, 0xDB73, 0xDB85, 0xDB8F, 0xDB91, 0xDBAD,
0xDBAF, 0xDBB9, 0xDBC7, 0xDBCB, 0xDBCD, 0xDBEB, 0xDBF7, 0xDC0D,
0xDC27, 0xDC31, 0xDC39, 0xDC3F, 0xDC49, 0xDC51, 0xDC61, 0xDC6F,
0xDC75, 0xDC7B, 0xDC85, 0xDC93, 0xDC99, 0xDC9D, 0xDC9F, 0xDCA9,
0xDCB5, 0xDCB7, 0xDCBD, 0xDCC7, 0xDCCF, 0xDCD3, 0xDCD5, 0xDCDF,
0xDCF9, 0xDD0F, 0xDD15, 0xDD17, 0xDD23, 0xDD35, 0xDD39, 0xDD53,
0xDD57, 0xDD5F, 0xDD69, 0xDD6F, 0xDD7D, 0xDD87, 0xDD89, 0xDD9B,
0xDDA1, 0xDDAB, 0xDDBF, 0xDDC5, 0xDDCB, 0xDDCF, 0xDDE7, 0xDDE9,
0xDDED, 0xDDF5, 0xDDFB, 0xDE0B, 0xDE19, 0xDE29, 0xDE3B, 0xDE3D,
0xDE41, 0xDE4D, 0xDE4F, 0xDE59, 0xDE5B, 0xDE61, 0xDE6D, 0xDE77,
0xDE7D, 0xDE83, 0xDE97, 0xDE9D, 0xDEA1, 0xDEA7, 0xDECD, 0xDED1,
0xDED7, 0xDEE3, 0xDEF1, 0xDEF5, 0xDF01, 0xDF09, 0xDF13, 0xDF1F,
0xDF2B, 0xDF33, 0xDF37, 0xDF3D, 0xDF4B, 0xDF55, 0xDF5B, 0xDF67,
0xDF69, 0xDF73, 0xDF85, 0xDF87, 0xDF99, 0xDFA3, 0xDFAB, 0xDFB5,
0xDFB7, 0xDFC3, 0xDFC7, 0xDFD5, 0xDFF1, 0xDFF3, 0xE003, 0xE005,
0xE017, 0xE01D, 0xE027, 0xE02D, 0xE035, 0xE045, 0xE053, 0xE071,
0xE07B, 0xE08F, 0xE095, 0xE09F, 0xE0B7, 0xE0B9, 0xE0D5, 0xE0D7,
0xE0E3, 0xE0F3, 0xE0F9, 0xE101, 0xE125, 0xE129, 0xE131, 0xE135,
0xE143, 0xE14F, 0xE159, 0xE161, 0xE16D, 0xE171, 0xE177, 0xE17F,
0xE183, 0xE189, 0xE197, 0xE1AD, 0xE1B5, 0xE1BB, 0xE1BF, 0xE1C1,
0xE1CB, 0xE1D1, 0xE1E5, 0xE1EF, 0xE1F7, 0xE1FD, 0xE203, 0xE219,
0xE22B, 0xE22D, 0xE23D, 0xE243, 0xE257, 0xE25B, 0xE275, 0xE279,
0xE287, 0xE29D, 0xE2AB, 0xE2AF, 0xE2BB, 0xE2C1, 0xE2C9, 0xE2CD,
0xE2D3, 0xE2D9, 0xE2F3, 0xE2FD, 0xE2FF, 0xE311, 0xE323, 0xE327,
0xE329, 0xE339, 0xE33B, 0xE34D, 0xE351, 0xE357, 0xE35F, 0xE363,
0xE369, 0xE375, 0xE377, 0xE37D, 0xE383, 0xE39F, 0xE3C5, 0xE3C9,
0xE3D1, 0xE3E1, 0xE3FB, 0xE3FF, 0xE401, 0xE40B, 0xE417, 0xE419,
0xE423, 0xE42B, 0xE431, 0xE43B, 0xE447, 0xE449, 0xE453, 0xE455,
0xE46D, 0xE471, 0xE48F, 0xE4A9, 0xE4AF, 0xE4B5, 0xE4C7, 0xE4CD,
0xE4D3, 0xE4E9, 0xE4EB, 0xE4F5, 0xE507, 0xE521, 0xE525, 0xE537,
0xE53F, 0xE545, 0xE54B, 0xE557, 0xE567, 0xE56D, 0xE575, 0xE585,
0xE58B, 0xE593, 0xE5A3, 0xE5A5, 0xE5CF, 0xE609, 0xE611, 0xE615,
0xE61B, 0xE61D, 0xE621, 0xE629, 0xE639, 0xE63F, 0xE653, 0xE657,
0xE663, 0xE66F, 0xE675, 0xE681, 0xE683, 0xE68D, 0xE68F, 0xE695,
0xE6AB, 0xE6AD, 0xE6B7, 0xE6BD, 0xE6C5, 0xE6CB, 0xE6D5, 0xE6E3,
0xE6E9, 0xE6EF, 0xE6F3, 0xE705, 0xE70D, 0xE717, 0xE71F, 0xE72F,
0xE73D, 0xE747, 0xE749, 0xE753, 0xE755, 0xE761, 0xE767, 0xE76B,
0xE77F, 0xE789, 0xE791, 0xE7C5, 0xE7CD, 0xE7D7, 0xE7DD, 0xE7DF,
0xE7E9, 0xE7F1, 0xE7FB, 0xE801, 0xE807, 0xE80F, 0xE819, 0xE81B,
0xE831, 0xE833, 0xE837, 0xE83D, 0xE84B, 0xE84F, 0xE851, 0xE869,
0xE875, 0xE879, 0xE893, 0xE8A5, 0xE8A9, 0xE8AF, 0xE8BD, 0xE8DB,
0xE8E1, 0xE8E5, 0xE8EB, 0xE8ED, 0xE903, 0xE90B, 0xE90F, 0xE915,
0xE917, 0xE92D, 0xE933, 0xE93B, 0xE94B, 0xE951, 0xE95F, 0xE963,
0xE969, 0xE97B, 0xE983, 0xE98F, 0xE995, 0xE9A1, 0xE9B9, 0xE9D7,
0xE9E7, 0xE9EF, 0xEA11, 0xEA19, 0xEA2F, 0xEA35, 0xEA43, 0xEA4D,
0xEA5F, 0xEA6D, 0xEA71, 0xEA7D, 0xEA85, 0xEA89, 0xEAAD, 0xEAB3,
0xEAB9, 0xEABB, 0xEAC5, 0xEAC7, 0xEACB, 0xEADF, 0xEAE5, 0xEAEB,
0xEAF5, 0xEB01, 0xEB07, 0xEB09, 0xEB31, 0xEB39, 0xEB3F, 0xEB5B,
0xEB61, 0xEB63, 0xEB6F, 0xEB81, 0xEB85, 0xEB9D, 0xEBAB, 0xEBB1,
0xEBB7, 0xEBC1, 0xEBD5, 0xEBDF, 0xEBED, 0xEBFD, 0xEC0B, 0xEC1B,
0xEC21, 0xEC29, 0xEC4D, 0xEC51, 0xEC5D, 0xEC69, 0xEC6F, 0xEC7B,
0xECAD, 0xECB9, 0xECBF, 0xECC3, 0xECC9, 0xECCF, 0xECD7, 0xECDD,
0xECE7, 0xECE9, 0xECF3, 0xECF5, 0xED07, 0xED11, 0xED1F, 0xED2F,
0xED37, 0xED3D, 0xED41, 0xED55, 0xED59, 0xED5B, 0xED65, 0xED6B,
0xED79, 0xED8B, 0xED95, 0xEDBB, 0xEDC5, 0xEDD7, 0xEDD9, 0xEDE3,
0xEDE5, 0xEDF1, 0xEDF5, 0xEDF7, 0xEDFB, 0xEE09, 0xEE0F, 0xEE19,
0xEE21, 0xEE49, 0xEE4F, 0xEE63, 0xEE67, 0xEE73, 0xEE7B, 0xEE81,
0xEEA3, 0xEEAB, 0xEEC1, 0xEEC9, 0xEED5, 0xEEDF, 0xEEE1, 0xEEF1,
0xEF1B, 0xEF27, 0xEF2F, 0xEF45, 0xEF4D, 0xEF63, 0xEF6B, 0xEF71,
0xEF93, 0xEF95, 0xEF9B, 0xEF9F, 0xEFAD, 0xEFB3, 0xEFC3, 0xEFC5,
0xEFDB, 0xEFE1, 0xEFE9, 0xF001, 0xF017, 0xF01D, 0xF01F, 0xF02B,
0xF02F, 0xF035, 0xF043, 0xF047, 0xF04F, 0xF067, 0xF06B, 0xF071,
0xF077, 0xF079, 0xF08F, 0xF0A3, 0xF0A9, 0xF0AD, 0xF0BB, 0xF0BF,
0xF0C5, 0xF0CB, 0xF0D3, 0xF0D9, 0xF0E3, 0xF0E9, 0xF0F1, 0xF0F7,
0xF107, 0xF115, 0xF11B, 0xF121, 0xF137, 0xF13D, 0xF155, 0xF175,
0xF17B, 0xF18D, 0xF193, 0xF1A5, 0xF1AF, 0xF1B7, 0xF1D5, 0xF1E7,
0xF1ED, 0xF1FD, 0xF209, 0xF20F, 0xF21B, 0xF21D, 0xF223, 0xF227,
0xF233, 0xF23B, 0xF241, 0xF257, 0xF25F, 0xF265, 0xF269, 0xF277,
0xF281, 0xF293, 0xF2A7, 0xF2B1, 0xF2B3, 0xF2B9, 0xF2BD, 0xF2BF,
0xF2DB, 0xF2ED, 0xF2EF, 0xF2F9, 0xF2FF, 0xF305, 0xF30B, 0xF319,
0xF341, 0xF359, 0xF35B, 0xF35F, 0xF367, 0xF373, 0xF377, 0xF38B,
0xF38F, 0xF3AF, 0xF3C1, 0xF3D1, 0xF3D7, 0xF3FB, 0xF403, 0xF409,
0xF40D, 0xF413, 0xF421, 0xF425, 0xF42B, 0xF445, 0xF44B, 0xF455,
0xF463, 0xF475, 0xF47F, 0xF485, 0xF48B, 0xF499, 0xF4A3, 0xF4A9,
0xF4AF, 0xF4BD, 0xF4C3, 0xF4DB, 0xF4DF, 0xF4ED, 0xF503, 0xF50B,
0xF517, 0xF521, 0xF529, 0xF535, 0xF547, 0xF551, 0xF563, 0xF56B,
0xF583, 0xF58D, 0xF595, 0xF599, 0xF5B1, 0xF5B7, 0xF5C9, 0xF5CF,
0xF5D1, 0xF5DB, 0xF5F9, 0xF5FB, 0xF605, 0xF607, 0xF60B, 0xF60D,
0xF635, 0xF637, 0xF653, 0xF65B, 0xF661, 0xF667, 0xF679, 0xF67F,
0xF689, 0xF697, 0xF69B, 0xF6AD, 0xF6CB, 0xF6DD, 0xF6DF, 0xF6EB,
0xF709, 0xF70F, 0xF72D, 0xF731, 0xF743, 0xF74F, 0xF751, 0xF755,
0xF763, 0xF769, 0xF773, 0xF779, 0xF781, 0xF787, 0xF791, 0xF79D,
0xF79F, 0xF7A5, 0xF7B1, 0xF7BB, 0xF7BD, 0xF7CF, 0xF7D3, 0xF7E7,
0xF7EB, 0xF7F1, 0xF7FF, 0xF805, 0xF80B, 0xF821, 0xF827, 0xF82D,
0xF835, 0xF847, 0xF859, 0xF863, 0xF865, 0xF86F, 0xF871, 0xF877,
0xF87B, 0xF881, 0xF88D, 0xF89F, 0xF8A1, 0xF8AB, 0xF8B3, 0xF8B7,
0xF8C9, 0xF8CB, 0xF8D1, 0xF8D7, 0xF8DD, 0xF8E7, 0xF8EF, 0xF8F9,
0xF8FF, 0xF911, 0xF91D, 0xF925, 0xF931, 0xF937, 0xF93B, 0xF941,
0xF94F, 0xF95F, 0xF961, 0xF96D, 0xF971, 0xF977, 0xF99D, 0xF9A3,
0xF9A9, 0xF9B9, 0xF9CD, 0xF9E9, 0xF9FD, 0xFA07, 0xFA0D, 0xFA13,
0xFA21, 0xFA25, 0xFA3F, 0xFA43, 0xFA51, 0xFA5B, 0xFA6D, 0xFA7B,
0xFA97, 0xFA99, 0xFA9D, 0xFAAB, 0xFABB, 0xFABD, 0xFAD9, 0xFADF,
0xFAE7, 0xFAED, 0xFB0F, 0xFB17, 0xFB1B, 0xFB2D, 0xFB2F, 0xFB3F,
0xFB47, 0xFB4D, 0xFB75, 0xFB7D, 0xFB8F, 0xFB93, 0xFBB1, 0xFBB7,
0xFBC3, 0xFBC5, 0xFBE3, 0xFBE9, 0xFBF3, 0xFC01, 0xFC29, 0xFC37,
0xFC41, 0xFC43, 0xFC4F, 0xFC59, 0xFC61, 0xFC65, 0xFC6D, 0xFC73,
0xFC79, 0xFC95, 0xFC97, 0xFC9B, 0xFCA7, 0xFCB5, 0xFCC5, 0xFCCD,
0xFCEB, 0xFCFB, 0xFD0D, 0xFD0F, 0xFD19, 0xFD2B, 0xFD31, 0xFD51,
0xFD55, 0xFD67, 0xFD6D, 0xFD6F, 0xFD7B, 0xFD85, 0xFD97, 0xFD99,
0xFD9F, 0xFDA9, 0xFDB7, 0xFDC9, 0xFDE5, 0xFDEB, 0xFDF3, 0xFE03,
0xFE05, 0xFE09, 0xFE1D, 0xFE27, 0xFE2F, 0xFE41, 0xFE4B, 0xFE4D,
0xFE57, 0xFE5F, 0xFE63, 0xFE69, 0xFE75, 0xFE7B, 0xFE8F, 0xFE93,
0xFE95, 0xFE9B, 0xFE9F, 0xFEB3, 0xFEBD, 0xFED7, 0xFEE9, 0xFEF3,
0xFEF5, 0xFF07, 0xFF0D, 0xFF1D, 0xFF2B, 0xFF2F, 0xFF49, 0xFF4D,
0xFF5B, 0xFF65, 0xFF71, 0xFF7F, 0xFF85, 0xFF8B, 0xFF8F, 0xFF9D,
0xFFA7, 0xFFA9, 0xFFC7, 0xFFD9, 0xFFEF, 0xFFF1,
};
#endif

View File

@ -0,0 +1,70 @@
#!/usr/bin/perl
#
# Treat each line as a sequence of comma and/or space delimited
# floating point numbers, and compute basic statistics on them.
# These are written to standard output
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: stats,v 1.1 2000-07-14 00:44:26 nelsonb%netscape.com Exp $
#
$min = 1.7976931348623157E+308;
$max = 2.2250738585072014E-308;
$sum = $num = 0;
while(<>) {
chomp;
@nums = split(/[\s,]+/, $_);
next if($#nums < 0);
$num += scalar @nums;
foreach (@nums) {
$min = $_ if($_ < $min);
$max = $_ if($_ > $max);
$sum += $_;
}
}
if($num) {
$avg = $sum / $num;
} else {
$min = $max = 0;
}
printf "%d\tmin=%.2f, avg=%.2f, max=%.2f, sum=%.2f\n",
$num, $min, $avg, $max, $sum;
# end

View File

@ -0,0 +1,86 @@
#
# Test suite table for MPI library
#
# Format of entries:
# suite-name:function-name:description
#
# suite-name The name used to identify this test in mpi-test
# function-name The function called to perform this test in mpi-test.c
# description A brief description of what the suite tests
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: test-arrays.txt,v 1.1 2000-07-14 00:44:26 nelsonb%netscape.com Exp $
#
list:test_list:print out a list of the available test suites
copy:test_copy:test assignment of mp-int structures
exchange:test_exch:test exchange of mp-int structures
zero:test_zero:test zeroing of an mp-int
set:test_set:test setting an mp-int to a small constant
absolute-value:test_abs:test the absolute value function
negate:test_neg:test the arithmetic negation function
add-digit:test_add_d:test digit addition
add:test_add:test full addition
subtract-digit:test_sub_d:test digit subtraction
subtract:test_sub:test full subtraction
multiply-digit:test_mul_d:test digit multiplication
multiply:test_mul:test full multiplication
square:test_sqr:test full squaring function
divide-digit:test_div_d:test digit division
divide-2:test_div_2:test division by two
divide-2d:test_div_2d:test division & remainder by 2^d
divide:test_div:test full division
expt-digit:test_expt_d:test digit exponentiation
expt:test_expt:test full exponentiation
expt-2:test_2expt:test power-of-two exponentiation
square-root:test_sqrt:test integer square root function
modulo-digit:test_mod_d:test digit modular reduction
modulo:test_mod:test full modular reduction
mod-add:test_addmod:test modular addition
mod-subtract:test_submod:test modular subtraction
mod-multiply:test_mulmod:test modular multiplication
mod-square:test_sqrmod:test modular squaring function
mod-expt:test_exptmod:test full modular exponentiation
mod-expt-digit:test_exptmod_d:test digit modular exponentiation
mod-inverse:test_invmod:test modular inverse function
compare-digit:test_cmp_d:test digit comparison function
compare-zero:test_cmp_z:test zero comparison function
compare:test_cmp:test general signed comparison
compare-magnitude:test_cmp_mag:test general magnitude comparison
parity:test_parity:test parity comparison functions
gcd:test_gcd:test greatest common divisor functions
lcm:test_lcm:test least common multiple function
conversion:test_convert:test general radix conversion facilities
binary:test_raw:test raw output format
pprime:test_pprime:test probabilistic primality tester
fermat:test_fermat:test Fermat pseudoprimality tester

View File

@ -0,0 +1,6 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
pi1k.txt
pi2k.txt
pi5k.txt

View File

@ -0,0 +1,32 @@
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the Netscape security libraries.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1994-2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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.

View File

@ -0,0 +1,72 @@
/*
* Simple test driver for MPI library
*
* Test 1: Simple input test (drives single-digit multiply and add,
* as well as I/O routines)
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-1.c,v 1.1 2000-07-14 00:44:41 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#ifdef MAC_CW_SIOUX
#include <console.h>
#endif
#include "mpi.h"
int main(int argc, char *argv[])
{
int ix;
mp_int mp;
#ifdef MAC_CW_SIOUX
argc = ccommand(&argv);
#endif
mp_init(&mp);
for(ix = 1; ix < argc; ix++) {
mp_read_radix(&mp, argv[ix], 10);
mp_print(&mp, stdout);
fputc('\n', stdout);
}
mp_clear(&mp);
return 0;
}

View File

@ -0,0 +1,83 @@
/*
* Simple test driver for MPI library
*
* Test 2: Basic addition and subtraction test
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-2.c,v 1.1 2000-07-14 00:44:42 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a, b, c;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 2: Basic addition and subtraction\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mp_init(&c);
printf("c = a + b\n");
mp_add(&a, &b, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("c = a - b\n");
mp_sub(&a, &b, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,128 @@
/*
* Simple test driver for MPI library
*
* Test 3: Multiplication, division, and exponentiation test
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-3.c,v 1.1 2000-07-14 00:44:42 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#define SQRT 1 /* define nonzero to get square-root test */
#define EXPT 0 /* define nonzero to get exponentiate test */
int main(int argc, char *argv[])
{
int ix;
mp_int a, b, c, d;
mp_digit r;
mp_err res;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 3: Multiplication and division\n\n");
srand(time(NULL));
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mp_init(&c);
printf("\nc = a * b\n");
mp_mul(&a, &b, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = b * 32523\n");
mp_mul_d(&b, 32523, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
mp_init(&d);
printf("\nc = a / b, d = a mod b\n");
mp_div(&a, &b, &c, &d);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("d = "); mp_print(&d, stdout); fputc('\n', stdout);
ix = rand() % 256;
printf("\nc = a / %d, r = a mod %d\n", ix, ix);
mp_div_d(&a, (mp_digit)ix, &c, &r);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("r = %04X\n", r);
#if EXPT
printf("\nc = a ** b\n");
mp_expt(&a, &b, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
#endif
ix = rand() % 256;
printf("\nc = 2^%d\n", ix);
mp_2expt(&c, ix);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
#if SQRT
printf("\nc = sqrt(a)\n");
if((res = mp_sqrt(&a, &c)) != MP_OKAY) {
printf("mp_sqrt: %s\n", mp_strerror(res));
} else {
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
mp_sqr(&c, &c);
printf("c^2 = "); mp_print(&c, stdout); fputc('\n', stdout);
}
#endif
mp_clear(&d);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,141 @@
/*
* Simple test driver for MPI library
*
* Test 3a: Multiplication vs. squaring timing test
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-3a.c,v 1.1 2000-07-14 00:44:43 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mpprime.h"
int main(int argc, char *argv[])
{
int ix, num, prec = 8;
double d1, d2;
clock_t start, finish;
time_t seed;
mp_int a, c, d;
seed = time(NULL);
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-tests> [<precision>]\n", argv[0]);
return 1;
}
if((num = atoi(argv[1])) < 0)
num = -num;
if(!num) {
fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
return 1;
}
if(argc > 2) {
if((prec = atoi(argv[2])) <= 0)
prec = 8;
else
prec = (prec + (DIGIT_BIT - 1)) / DIGIT_BIT;
}
printf("Test 3a: Multiplication vs squaring timing test\n"
"Precision: %d digits (%u bits)\n"
"# of tests: %d\n\n", prec, prec * DIGIT_BIT, num);
mp_init_size(&a, prec);
mp_init(&c); mp_init(&d);
printf("Verifying accuracy ... \n");
srand((unsigned int)seed);
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mp_mul(&a, &a, &c);
mp_sqr(&a, &d);
if(mp_cmp(&c, &d) != 0) {
printf("Error! Results not accurate:\n");
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("d = "); mp_print(&d, stdout); fputc('\n', stdout);
mp_sub(&c, &d, &d);
printf("dif "); mp_print(&d, stdout); fputc('\n', stdout);
mp_clear(&c); mp_clear(&d);
mp_clear(&a);
return 1;
}
}
printf("Accuracy is confirmed for the %d test samples\n", num);
mp_clear(&d);
printf("Testing squaring ... \n");
srand((unsigned int)seed);
start = clock();
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mp_sqr(&a, &c);
}
finish = clock();
d2 = (double)(finish - start) / CLOCKS_PER_SEC;
printf("Testing multiplication ... \n");
srand((unsigned int)seed);
start = clock();
for(ix = 0; ix < num; ix++) {
mpp_random(&a);
mp_mul(&a, &a, &c);
}
finish = clock();
d1 = (double)(finish - start) / CLOCKS_PER_SEC;
printf("Multiplication time: %.3f sec (%.3f each)\n", d1, d1 / num);
printf("Squaring time: %.3f sec (%.3f each)\n", d2, d2 / num);
printf("Improvement: %.2f%%\n", (1.0 - (d2 / d1)) * 100.0);
mp_clear(&c);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,123 @@
/*
* Simple test driver for MPI library
*
* Test 4: Modular arithmetic tests
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-4.c,v 1.1 2000-07-14 00:44:43 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
int ix;
mp_int a, b, c, m;
mp_digit r;
if(argc < 4) {
fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]);
return 1;
}
printf("Test 4: Modular arithmetic\n\n");
mp_init(&a);
mp_init(&b);
mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
mp_read_radix(&m, argv[3], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
printf("m = "); mp_print(&m, stdout); fputc('\n', stdout);
mp_init(&c);
printf("\nc = a (mod m)\n");
mp_mod(&a, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = b (mod m)\n");
mp_mod(&b, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = b (mod 1853)\n");
mp_mod_d(&b, 1853, &r);
printf("c = %04X\n", r);
printf("\nc = (a + b) mod m\n");
mp_addmod(&a, &b, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = (a - b) mod m\n");
mp_submod(&a, &b, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = (a * b) mod m\n");
mp_mulmod(&a, &b, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nc = (a ** b) mod m\n");
mp_exptmod(&a, &b, &m, &c);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("\nIn-place modular squaring test:\n");
for(ix = 0; ix < 5; ix++) {
printf("a = (a * a) mod m a = ");
mp_sqrmod(&a, &m, &a);
mp_print(&a, stdout);
fputc('\n', stdout);
}
mp_clear(&c);
mp_clear(&m);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,135 @@
/*
* mptest4a - modular exponentiation speed test
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-4a.c,v 1.1 2000-07-14 00:44:43 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if(gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
extern mp_err s_mp_pad();
int main(int argc, char *argv[])
{
int ix, num, prec = 8;
unsigned int d;
instant_t start, finish;
time_t seed;
mp_int a, m, c;
seed = time(NULL);
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-tests> [<precision>]\n", argv[0]);
return 1;
}
if((num = atoi(argv[1])) < 0)
num = -num;
if(!num) {
fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
return 1;
}
if(argc > 2) {
if((prec = atoi(argv[2])) <= 0)
prec = 8;
}
printf("Test 3a: Modular exponentiation timing test\n"
"Precision: %d digits (%d bits)\n"
"# of tests: %d\n\n", prec, prec * DIGIT_BIT, num);
mp_init_size(&a, prec);
mp_init_size(&m, prec);
mp_init_size(&c, prec);
s_mp_pad(&a, prec);
s_mp_pad(&m, prec);
s_mp_pad(&c, prec);
printf("Testing modular exponentiation ... \n");
srand((unsigned int)seed);
start = now();
for(ix = 0; ix < num; ix++) {
mpp_random(&a);
mpp_random(&c);
mpp_random(&m);
mp_exptmod(&a, &c, &m, &c);
}
finish = now();
d = (finish.sec - start.sec) * 1000000;
d -= start.usec; d += finish.usec;
printf("Total time elapsed: %u usec\n", d);
printf("Time per exponentiation: %u usec (%.3f sec)\n",
(d / num), (double)(d / num) / 1000000);
mp_clear(&c);
mp_clear(&a);
mp_clear(&m);
return 0;
}

View File

@ -0,0 +1,132 @@
/*
* mptest-4b.c
*
* Test speed of a large modular exponentiation of a primitive element
* modulo a prime.
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-4b.c,v 1.1 2000-07-14 00:44:44 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
char *g_prime =
"34BD53C07350E817CCD49721020F1754527959C421C1533244769D4CF060A8B1C3DA"
"25094BE723FB1E2369B55FEEBBE0FAC16425161BF82684062B5EC5D7D47D1B23C117"
"0FA19745E44A55E148314E582EB813AC9EE5126295E2E380CACC2F6D206B293E5ED9"
"23B54EE961A8C69CD625CE4EC38B70C649D7F014432AEF3A1C93";
char *g_gen = "5";
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if(gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
extern mp_err s_mp_pad();
int main(int argc, char *argv[])
{
instant_t start, finish;
mp_int prime, gen, expt, res;
unsigned int ix, diff;
int num;
srand(time(NULL));
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
return 1;
}
if((num = atoi(argv[1])) < 0)
num = -num;
if(num == 0)
++num;
mp_init(&prime); mp_init(&gen); mp_init(&res);
mp_read_radix(&prime, g_prime, 16);
mp_read_radix(&gen, g_gen, 16);
mp_init_size(&expt, USED(&prime) - 1);
s_mp_pad(&expt, USED(&prime) - 1);
printf("Testing %d modular exponentations ... \n", num);
start = now();
for(ix = 0; ix < num; ix++) {
mpp_random(&expt);
mp_exptmod(&gen, &expt, &prime, &res);
}
finish = now();
diff = (finish.sec - start.sec) * 1000000;
diff += finish.usec; diff -= start.usec;
printf("%d operations took %u usec (%.3f sec)\n",
num, diff, (double)diff / 1000000.0);
printf("That is %.3f sec per operation.\n",
((double)diff / 1000000.0) / num);
mp_clear(&expt);
mp_clear(&res);
mp_clear(&gen);
mp_clear(&prime);
return 0;
}

View File

@ -0,0 +1,99 @@
/*
* Simple test driver for MPI library
*
* Test 5: Other number theoretic functions
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-5.c,v 1.1 2000-07-14 00:44:44 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a, b, c, x, y;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 5: Number theoretic functions\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mp_init(&c);
printf("\nc = (a, b)\n");
mp_gcd(&a, &b, &c);
printf("Euclid: c = "); mp_print(&c, stdout); fputc('\n', stdout);
mp_bgcd(&a, &b, &c);
printf("Binary: c = "); mp_print(&c, stdout); fputc('\n', stdout);
mp_init(&x);
mp_init(&y);
printf("\nc = (a, b) = ax + by\n");
mp_xgcd(&a, &b, &c, &x, &y);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("x = "); mp_print(&x, stdout); fputc('\n', stdout);
printf("y = "); mp_print(&y, stdout); fputc('\n', stdout);
printf("\nc = a^-1 (mod b)\n");
if(mp_invmod(&a, &b, &c) == MP_UNDEF) {
printf("a has no inverse mod b\n");
} else {
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
}
mp_clear(&y);
mp_clear(&x);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,162 @@
/*
* Simple test driver for MPI library
*
* Test 5a: Greatest common divisor speed test, binary vs. Euclid
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-5a.c,v 1.1 2000-07-14 00:44:45 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if(gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
#define PRECISION 16
int main(int argc, char *argv[])
{
int ix, num, prec = PRECISION;
mp_int a, b, c, d;
instant_t start, finish;
time_t seed;
unsigned int d1, d2;
seed = time(NULL);
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
return 1;
}
if((num = atoi(argv[1])) < 0)
num = -num;
printf("Test 5a: Euclid vs. Binary, a GCD speed test\n\n"
"Number of tests: %d\n"
"Precision: %d digits\n\n", num, prec);
mp_init_size(&a, prec);
mp_init_size(&b, prec);
mp_init(&c);
mp_init(&d);
printf("Verifying accuracy ... \n");
srand((unsigned int)seed);
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_gcd(&a, &b, &c);
mp_bgcd(&a, &b, &d);
if(mp_cmp(&c, &d) != 0) {
printf("Error! Results not accurate:\n");
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
printf("d = "); mp_print(&d, stdout); fputc('\n', stdout);
mp_clear(&a); mp_clear(&b); mp_clear(&c); mp_clear(&d);
return 1;
}
}
mp_clear(&d);
printf("Accuracy confirmed for the %d test samples\n", num);
printf("Testing Euclid ... \n");
srand((unsigned int)seed);
start = now();
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_gcd(&a, &b, &c);
}
finish = now();
d1 = (finish.sec - start.sec) * 1000000;
d1 -= start.usec; d1 += finish.usec;
printf("Testing binary ... \n");
srand((unsigned int)seed);
start = now();
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_bgcd(&a, &b, &c);
}
finish = now();
d2 = (finish.sec - start.sec) * 1000000;
d2 -= start.usec; d2 += finish.usec;
printf("Euclidean algorithm time: %u usec\n", d1);
printf("Binary algorithm time: %u usec\n", d2);
printf("Improvement: %.2f%%\n",
(1.0 - ((double)d2 / (double)d1)) * 100.0);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,108 @@
/*
* Simple test driver for MPI library
*
* Test 6: Output functions
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-6.c,v 1.1 2000-07-14 00:44:45 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
void print_buf(FILE *ofp, char *buf, int len)
{
int ix, brk = 0;
for(ix = 0; ix < len; ix++) {
fprintf(ofp, "%02X ", buf[ix]);
brk = (brk + 1) & 0xF;
if(!brk)
fputc('\n', ofp);
}
if(brk)
fputc('\n', ofp);
}
int main(int argc, char *argv[])
{
int ix, size;
mp_int a;
char *buf;
if(argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
printf("Test 6: Output functions\n\n");
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
printf("\nConverting to a string:\n");
printf("Rx Size Representation\n");
for(ix = 2; ix <= MAX_RADIX; ix++) {
size = mp_radix_size(&a, ix);
buf = calloc(size, sizeof(char));
mp_toradix(&a, buf, ix);
printf("%2d: %3d: %s\n", ix, size, buf);
free(buf);
}
printf("\nRaw output:\n");
size = mp_raw_size(&a);
buf = calloc(size, sizeof(char));
printf("Size: %d bytes\n", size);
mp_toraw(&a, buf);
print_buf(stdout, buf, size);
free(buf);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,103 @@
/*
* Simple test driver for MPI library
*
* Test 7: Random and divisibility tests
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-7.c,v 1.1 2000-07-14 00:44:46 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#define MP_IOFUNC
#include "mpi.h"
#include "mpprime.h"
int main(int argc, char *argv[])
{
int ix, size;
mp_int a, b;
srand(time(NULL));
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 7: Random & divisibility tests\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
if(mpp_divis(&a, &b) == MP_YES)
printf("a is divisible by b\n");
else
printf("a is not divisible by b\n");
if(mpp_divis(&b, &a) == MP_YES)
printf("b is divisible by a\n");
else
printf("b is not divisible by a\n");
printf("\nb = mpp_random()\n");
mpp_random(&b);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mpp_random(&b);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mpp_random(&b);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
printf("\nTesting a for divisibility by first 170 primes\n");
if(mpp_divis_primes(&a, 170) == MP_YES)
printf("It is divisible by at least one of them\n");
else
printf("It is not divisible by any of them\n");
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,93 @@
/*
* Simple test driver for MPI library
*
* Test 8: Probabilistic primality tester
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-8.c,v 1.1 2000-07-14 00:44:46 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#define MP_IOFUNC
#include "mpi.h"
#include "mpprime.h"
int main(int argc, char *argv[])
{
int ix, size;
mp_int a, b;
srand(time(NULL));
if(argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
printf("Test 8: Probabilistic primality testing\n\n");
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("\nChecking for divisibility by small primes ... \n");
if(mpp_divis_primes(&a, 170) == MP_YES) {
printf("it is not prime\n");
goto CLEANUP;
}
printf("Passed that test (not divisible by any small primes).\n");
for(ix = 0; ix < 10; ix++) {
printf("\nPerforming Rabin-Miller test, iteration %d\n", ix + 1);
if(mpp_pprime(&a) == MP_NO) {
printf("it is not prime\n");
goto CLEANUP;
}
}
printf("All tests passed; a is probably prime\n");
CLEANUP:
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,113 @@
/*
* mptest-9.c
*
* Test logical functions
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: mptest-9.c,v 1.1 2000-07-14 00:44:47 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mplogic.h"
int main(int argc, char *argv[])
{
mp_int a, b, c;
int pco;
mp_err res;
printf("Test 9: Logical functions\n\n");
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
mp_init(&a); mp_init(&b); mp_init(&c);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
mpl_not(&a, &c);
printf("~a = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_and(&a, &b, &c);
printf("a & b = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_or(&a, &b, &c);
printf("a | b = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_xor(&a, &b, &c);
printf("a ^ b = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_rsh(&a, &c, 1);
printf("a >> 1 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_rsh(&a, &c, 5);
printf("a >> 5 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_rsh(&a, &c, 16);
printf("a >> 16 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_lsh(&a, &c, 1);
printf("a << 1 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_lsh(&a, &c, 5);
printf("a << 5 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_lsh(&a, &c, 16);
printf("a << 16 = "); mp_print(&c, stdout); fputc('\n', stdout);
mpl_num_set(&a, &pco);
printf("#1(a) = %d\n", pco);
mpl_num_set(&b, &pco);
printf("#1(b) = %d\n", pco);
res = mpl_parity(&a);
if(res == MP_EVEN)
printf("a has even parity\n");
else
printf("a has odd parity\n");
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1 @@
31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989

View File

@ -0,0 +1 @@
314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759010

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,126 @@
#!/bin/sh
#
# Simple timing test for the MPI library. Basically, we use prime
# generation as a timing test, since it exercises most of the pathways
# of the library fairly heavily. The 'primegen' tool outputs a line
# summarizing timing results. We gather these and process them for
# statistical information, which is collected into a file.
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: timetest,v 1.1 2000-07-14 00:44:27 nelsonb%netscape.com Exp $
#
# Avoid using built-in shell echoes
ECHO=/bin/echo
# Use a fixed seed so timings will be more consistent
# This one is the 11th-18th decimal digits of 'e'
export SEED=45904523
#------------------------------------------------------------------------
$ECHO "\n** Running timing tests for MPI library\n"
$ECHO "Bringing 'metime' up to date ... "
if make metime ; then
:
else
$ECHO "\nMake failed to build metime.\n"
exit 1
fi
if [ ! -x ./metime ] ; then
$ECHO "\nCannot find 'metime' program, testing cannot continue.\n"
exit 1
fi
#------------------------------------------------------------------------
$ECHO "Bringing 'primegen' up to date ... "
if make primegen ; then
:
else
$ECHO "\nMake failed to build primegen.\n"
exit 1
fi
if [ ! -x ./primegen ] ; then
$ECHO "\nCannot find 'primegen' program, testing cannot continue.\n"
exit 1
fi
#------------------------------------------------------------------------
rm -f timing-results.txt
touch timing-results.txt
sizes="128 192 256 320 384 448 512 640 768 896 1024"
ntests=200
trap 'echo "oop!";rm -f tt*.tmp timing-results.txt;exit 0' INT HUP
$ECHO "\n-- Modular exponentiation\n"
$ECHO "Modular exponentiation:" >> timing-results.txt
$ECHO "Running $ntests modular exponentiations per test:"
for size in $sizes ; do
$ECHO "- Gathering statistics for $size bits ... "
secs=`./metime $ntests $size | tail -1 | awk '{print $2}'`
$ECHO "$size: " $secs >> timing-results.txt
tail -1 timing-results.txt
done
$ECHO "<done>";
sizes="128 192 256 320 384 448 512"
ntests=200
$ECHO "\n-- Prime generation\n"
$ECHO "Prime generation:" >> timing-results.txt
$ECHO "Generating $ntests prime values per test:"
for size in $sizes ; do
$ECHO "- Gathering statistics for $size bits ... "
./primegen $size $ntests | grep ticks | awk '{print $7}' | tr -d '(' > tt$$.tmp
$ECHO "$size:" >> timing-results.txt
perl stats tt$$.tmp >> timing-results.txt
tail -1 timing-results.txt
rm -f tt$$.tmp
done
$ECHO "<done>"
exit 0

View File

@ -0,0 +1,158 @@
#!/usr/bin/perl
#
# types.pl - find recommended type definitions for digits and words
#
# This script scans the Makefile for the C compiler and compilation
# flags currently in use, and using this combination, attempts to
# compile a simple test program that outputs the sizes of the various
# unsigned integer types, in bytes. Armed with these, it finds all
# the "viable" type combinations for mp_digit and mp_word, where
# viability is defined by the requirement that mp_word be at least two
# times the precision of mp_digit.
#
# Of these, the one with the largest digit size is chosen, and
# appropriate typedef statements are written to standard output.
#
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 2000 Michael J. Fromberger. All Rights Reserved
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: types.pl,v 1.1 2000-07-14 00:44:27 nelsonb%netscape.com Exp $
#
@_=split(/\//,$0);chomp($prog=pop(@_));
# The array of integer types to be considered...
@TYPES = (
"unsigned char",
"unsigned short",
"unsigned int",
"unsigned long"
);
# Macro names for the maximum unsigned value of each type
%TMAX = (
"unsigned char" => "UCHAR_MAX",
"unsigned short" => "USHRT_MAX",
"unsigned int" => "UINT_MAX",
"unsigned long" => "ULONG_MAX"
);
# Read the Makefile to find out which C compiler to use
open(MFP, "<Makefile") or die "$prog: Makefile: $!\n";
while(<MFP>) {
chomp;
if(/^CC=(.*)$/) {
$cc = $1;
last if $cflags;
} elsif(/^CFLAGS=(.*)$/) {
$cflags = $1;
last if $cc;
}
}
close(MFP);
# If we couldn't find that, use 'cc' by default
$cc = "cc" unless $cc;
printf STDERR "Using '%s' as the C compiler.\n", $cc;
print STDERR "Determining type sizes ... \n";
open(OFP, ">tc$$.c") or die "$prog: tc$$.c: $!\n";
print OFP "#include <stdio.h>\n\nint main(void)\n{\n";
foreach $type (@TYPES) {
printf OFP "\tprintf(\"%%d\\n\", (int)sizeof(%s));\n", $type;
}
print OFP "\n\treturn 0;\n}\n";
close(OFP);
system("$cc $cflags -o tc$$ tc$$.c");
die "$prog: unable to build test program\n" unless(-x "tc$$");
open(IFP, "./tc$$|") or die "$prog: can't execute test program\n";
$ix = 0;
while(<IFP>) {
chomp;
$size{$TYPES[$ix++]} = $_;
}
close(IFP);
unlink("tc$$");
unlink("tc$$.c");
print STDERR "Selecting viable combinations ... \n";
while(($type, $size) = each(%size)) {
push(@ts, [ $size, $type ]);
}
# Sort them ascending by size
@ts = sort { $a->[0] <=> $b->[0] } @ts;
# Try all possible combinations, finding pairs in which the word size
# is twice the digit size. The number of possible pairs is too small
# to bother doing this more efficiently than by brute force
for($ix = 0; $ix <= $#ts; $ix++) {
$w = $ts[$ix];
for($jx = 0; $jx <= $#ts; $jx++) {
$d = $ts[$jx];
if($w->[0] == 2 * $d->[0]) {
push(@valid, [ $d, $w ]);
}
}
}
# Sort descending by digit size
@valid = sort { $b->[0]->[0] <=> $a->[0]->[0] } @valid;
# Select the maximum as the recommended combination
$rec = shift(@valid);
printf("typedef %-18s mp_sign;\n", "char");
printf("typedef %-18s mp_digit; /* %d byte type */\n",
$rec->[0]->[1], $rec->[0]->[0]);
printf("typedef %-18s mp_word; /* %d byte type */\n",
$rec->[1]->[1], $rec->[1]->[0]);
printf("typedef %-18s mp_size;\n", "unsigned int");
printf("typedef %-18s mp_err;\n\n", "int");
printf("#define %-18s (CHAR_BIT*sizeof(mp_digit))\n", "DIGIT_BIT");
printf("#define %-18s %s\n", "DIGIT_MAX", $TMAX{$rec->[0]->[1]});
printf("#define %-18s (CHAR_BIT*sizeof(mp_word))\n", "MP_WORD_BIT");
printf("#define %-18s %s\n\n", "MP_WORD_MAX", $TMAX{$rec->[1]->[1]});
printf("#define %-18s (DIGIT_MAX+1)\n\n", "RADIX");
printf("#define %-18s \"%%0%dX\"\n", "DIGIT_FMT", (2 * $rec->[0]->[0]));
exit 0;

View File

@ -0,0 +1,4 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
PRIMES

View File

@ -0,0 +1,32 @@
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the Netscape security libraries.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1994-2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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.

View File

@ -0,0 +1,41 @@
Probable primes (sorted by number of significant bits)
128: 81386202757205669562183851789305348631
128: 180241813863264101444573802809858694397
128: 245274683055224433281596312431122059021
128: 187522309397665259809392608791686659539
256: 83252422946206411852330647237287722547866360773229941071371588246436\
513990159
256: 79132571131322331023736933767063051273085304521895229780914612117520\
058517909
256: 72081815425552909748220041100909735706208853818662000557743644603407\
965465527
256: 87504602391905701494845474079163412737334477797316409702279059573654\
274811271
512: 12233064210800062190450937494718705259777386009095453001870729392786\
63450255179083524798507997690270500580265258111668148238355016411719\
9168737693316468563
512: 12003639081420725322369909586347545220275253633035565716386136197501\
88208318984400479275215620499883521216480724155582768193682335576385\
2069481074929084063
1024: 16467877625718912296741904171202513097057724053648819680815842057593\
20371835940722471475475803725455063836431454757000451907612224427007\
63984592414360595161051906727075047683803534852982766542661204179549\
77327573530800542562611753617736693359790119074768292178493884576587\
0230450429880021317876149636714743053
1024: 16602953991090311275234291158294516471009930684624948451178742895360\
86073703307475884280944414508444679430090561246728195735962931545473\
40743240318558456247740186704660778277799687988031119436541068736925\
20563780233711166724859277827382391527748470939542560819625727876091\
5372193745283891895989104479029844957

View File

@ -0,0 +1,239 @@
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by Michael J. Fromberger are
Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
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.
Additional MPI utilities
------------------------
The files 'mpprime.h' and 'mpprime.c' define some useful extensions to
the MPI library for dealing with prime numbers (in particular, testing
for divisbility, and the Rabin-Miller probabilistic primality test).
The files 'mplogic.h' and 'mplogic.c' define extensions to the MPI
library for doing bitwise logical operations and shifting.
This document assumes you have read the help file for the MPI library
and understand its conventions.
Divisibility (mpprime.h)
------------
To test a number for divisibility by another number:
mpp_divis(a, b) - test if b|a
mpp_divis_d(a, d) - test if d|a
Each of these functions returns MP_YES if its initial argument is
divisible by its second, or MP_NO if it is not. Other errors may be
returned as appropriate (such as MP_RANGE if you try to test for
divisibility by zero).
Randomness (mpprime.h)
----------
To generate random data:
mpp_random(a) - fill a with random data
mpp_random_size(a, p) - fill a with p digits of random data
The mpp_random_size() function increases the precision of a to at
least p, then fills all those digits randomly. The mp_random()
function fills a to its current precision (as determined by the number
of significant digits, USED(a))
Note that these functions simply use the C library's rand() function
to fill a with random digits up to its precision. This should be
adequate for primality testing, but should not be used for
cryptographic applications where truly random values are required for
security.
You should call srand() in your driver program in order to seed the
random generator; this function doesn't call it.
Primality Testing (mpprime.h)
-----------------
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s values
in v, and if so, w = which.
mpp_divis_primes(a, np) - is a divisible by any of the first np primes?
mpp_fermat(a, w) - is a pseudoprime with respect to witness w?
mpp_pprime(a, nt) - run nt iterations of Rabin-Miller on a.
The mpp_divis_vector() function tests a for divisibility by each
member of an array of digits. The array is v, the size of that array
is s. Returns MP_YES if a is divisible, and stores the index of the
offending digit in w. Returns MP_NO if a is not divisible by any of
the digits in the array.
A small table of primes is compiled into the library (typically the
first 128 primes, although you can change this by editing the file
'primes.c' before you build). The global variable prime_tab_size
contains the number of primes in the table, and the values themselves
are in the array prime_tab[], which is an array of mp_digit.
The mpp_divis_primes() function is basically just a wrapper around
mpp_divis_vector() that uses prime_tab[] as the test vector. The np
parameter is a pointer to an mp_digit -- on input, it should specify
the number of primes to be tested against. If a is divisible by any
of the primes, MP_YES is returned and np is given the prime value that
divided a (you can use this if you're factoring, for example).
Otherwise, MP_NO is returned and np is untouched.
The function mpp_fermat() performs Fermat's test, using w as a
witness. This test basically relies on the fact that if a is prime,
and w is relatively prime to a, then:
w^a = w (mod a)
That is,
w^(a - 1) = 1 (mod a)
The function returns MP_YES if the test passes, MP_NO if it fails. If
w is relatively prime to a, and the test fails, a is definitely
composite. If w is relatively prime to a and the test passes, then a
is either prime, or w is a false witness (the probability of this
happening depends on the choice of w and of a ... consult a number
theory textbook for more information about this).
Note: If (w, a) != 1, the output of this test is meaningless.
----
The function mpp_pprime() performs the Rabin-Miller probabilistic
primality test for nt rounds. If all the tests pass, MP_YES is
returned, and a is probably prime. The probability that an answer of
MP_YES is incorrect is no greater than 1 in 4^nt, and in fact is
usually much less than that (this is a pessimistic estimate). If any
test fails, MP_NO is returned, and a is definitely composite.
Bruce Schneier recommends at least 5 iterations of this test for most
cryptographic applications; Knuth suggests that 25 are reasonable.
Run it as many times as you feel are necessary.
See the programs 'makeprime.c' and 'isprime.c' for reasonable examples
of how to use these functions for primality testing.
Bitwise Logic (mplogic.c)
-------------
The four commonest logical operations are implemented as:
mpl_not(a, b) - Compute bitwise (one's) complement, b = ~a
mpl_and(a, b, c) - Compute bitwise AND, c = a & b
mpl_or(a, b, c) - Compute bitwise OR, c = a | b
mpl_xor(a, b, c) - Compute bitwise XOR, c = a ^ b
Left and right shifts are available as well. These take a number to
shift, a destination, and a shift amount. The shift amount must be a
digit value between 0 and DIGIT_BIT inclusive; if it is not, MP_RANGE
will be returned and the shift will not happen.
mpl_rsh(a, b, d) - Compute logical right shift, b = a >> d
mpl_lsh(a, b, d) - Compute logical left shift, b = a << d
Since these are logical shifts, they fill with zeroes (the library
uses a signed magnitude representation, so there are no sign bits to
extend anyway).
Command-line Utilities
----------------------
A handful of interesting command-line utilities are provided. These
are:
lap.c - Find the order of a mod m. Usage is 'lap <a> <m>'.
This uses a dumb algorithm, so don't use it for
a really big modulus.
invmod.c - Find the inverse of a mod m, if it exists. Usage
is 'invmod <a> <m>'
sieve.c - A simple bitmap-based implementation of the Sieve
of Eratosthenes. Used to generate the table of
primes in primes.c. Usage is 'sieve <nbits>'
prng.c - Uses the routines in bbs_rand.{h,c} to generate
one or more 32-bit pseudo-random integers. This
is mainly an example, not intended for use in a
cryptographic application (the system time is
the only source of entropy used)
dec2hex.c - Convert decimal to hexadecimal
hex2dec.c - Convert hexadecimal to decimal
basecvt.c - General radix conversion tool (supports 2-64)
isprime.c - Probabilistically test an integer for primality
using the Rabin-Miller pseudoprime test combined
with division by small primes.
primegen.c - Generate primes at random.
exptmod.c - Perform modular exponentiation
ptab.pl - A Perl script to munge the output of the sieve
program into a compilable C structure.
Other Files
-----------
PRIMES - Some randomly generated numbers which are prime with
extremely high probability.
README - You're reading me already.
About the Author
----------------
This software was written by Michael J. Fromberger. You can contact
the author as follows:
E-mail: <sting@linguist.dartmouth.edu>
Postal: 8000 Cummings Hall, Thayer School of Engineering
Dartmouth College, Hanover, New Hampshire, USA
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
Last updated: $Id: README,v 1.1 2000-07-14 00:44:52 nelsonb%netscape.com Exp $

View File

@ -0,0 +1,97 @@
/*
* basecvt.c
*
* Convert integer values specified on the command line from one input
* base to another. Accepts input and output bases between 2 and 36
* inclusive.
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: basecvt.c,v 1.1 2000-07-14 00:44:53 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#define IBASE 10
#define OBASE 16
#define USAGE "Usage: %s ibase obase [value]\n"
#define MAXBASE 64
#define MINBASE 2
int main(int argc, char *argv[])
{
int ix, ibase = IBASE, obase = OBASE;
mp_int val;
ix = 1;
if(ix < argc) {
ibase = atoi(argv[ix++]);
if(ibase < MINBASE || ibase > MAXBASE) {
fprintf(stderr, "%s: input radix must be between %d and %d inclusive\n",
argv[0], MINBASE, MAXBASE);
return 1;
}
}
if(ix < argc) {
obase = atoi(argv[ix++]);
if(obase < MINBASE || obase > MAXBASE) {
fprintf(stderr, "%s: output radix must be between %d and %d inclusive\n",
argv[0], MINBASE, MAXBASE);
return 1;
}
}
mp_init(&val);
while(ix < argc) {
char *out;
int outlen;
mp_read_radix(&val, argv[ix++], ibase);
outlen = mp_radix_size(&val, obase);
out = calloc(outlen, sizeof(char));
mp_toradix(&val, out, obase);
printf("%s\n", out);
free(out);
}
mp_clear(&val);
return 0;
}

View File

@ -0,0 +1,93 @@
/*
* Blum, Blum & Shub PRNG using the MPI library
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: bbs_rand.c,v 1.1 2000-07-14 00:44:53 nelsonb%netscape.com Exp $
*/
#include "bbs_rand.h"
#define SEED 1
#define MODULUS 2
/* This modulus is the product of two randomly generated 512-bit
prime integers, each of which is congruent to 3 (mod 4). */
static char *bbs_modulus =
"75A2A6E1D27393B86562B9CE7279A8403CB4258A637DAB5233465373E37837383EDC"
"332282B8575927BC4172CE8C147B4894050EE9D2BDEED355C121037270CA2570D127"
"7D2390CD1002263326635CC6B259148DE3A1A03201980A925E395E646A5E9164B0EC"
"28559EBA58C87447245ADD0651EDA507056A1129E3A3E16E903D64B437";
static int bbs_init = 0; /* flag set when library is initialized */
static mp_int bbs_state; /* the current state of the generator */
/* Suggested size of random seed data */
int bbs_seed_size = (sizeof(bbs_modulus) / 2);
void bbs_srand(unsigned char *data, int len)
{
if((bbs_init & SEED) == 0) {
mp_init(&bbs_state);
bbs_init |= SEED;
}
mp_read_raw(&bbs_state, (char *)data, len);
} /* end bbs_srand() */
unsigned int bbs_rand(void)
{
static mp_int modulus;
unsigned int result = 0, ix;
if((bbs_init & MODULUS) == 0) {
mp_init(&modulus);
mp_read_radix(&modulus, bbs_modulus, 16);
bbs_init |= MODULUS;
}
for(ix = 0; ix < sizeof(unsigned int); ix++) {
mp_digit d;
mp_sqrmod(&bbs_state, &modulus, &bbs_state);
d = DIGIT(&bbs_state, 0);
result = (result << CHAR_BIT) | (d & UCHAR_MAX);
}
return result;
} /* end bbs_rand() */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,55 @@
/*
* bbs_rand.h
*
* Blum, Blum & Shub PRNG using the MPI library
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: bbs_rand.h,v 1.1 2000-07-14 00:44:54 nelsonb%netscape.com Exp $
*/
#ifndef _H_BBSRAND_
#define _H_BBSRAND_
#include <limits.h>
#include "mpi.h"
#define BBS_RAND_MAX UINT_MAX
/* Suggested length of seed data */
extern int bbs_seed_size;
void bbs_srand(unsigned char *data, int len);
unsigned int bbs_rand(void);
#endif /* end _H_BBSRAND_ */

View File

@ -0,0 +1,64 @@
/*
* bbsrand.c
*
* Test driver for routines in bbs_rand.h
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: bbsrand.c,v 1.1 2000-07-14 00:44:54 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include "bbs_rand.h"
#define NUM_TESTS 100
int main(void)
{
unsigned int seed, result, ix;
seed = time(NULL);
bbs_srand((unsigned char *)&seed, sizeof(seed));
for(ix = 0; ix < NUM_TESTS; ix++) {
result = bbs_rand();
printf("Test %3u: %08X\n", ix + 1, result);
}
return 0;
}

View File

@ -0,0 +1,68 @@
/*
* dec2hex.c
*
* Convert decimal integers into hexadecimal
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: dec2hex.c,v 1.1 2000-07-14 00:44:54 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a;
char *buf;
int len;
if(argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
mp_init(&a); mp_read_radix(&a, argv[1], 10);
len = mp_radix_size(&a, 16);
buf = malloc(len);
mp_toradix(&a, buf, 16);
printf("%s\n", buf);
free(buf);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* exptmod.c
*
* Command line tool to perform modular exponentiation on arbitrary
* precision integers.
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: exptmod.c,v 1.1 2000-07-14 00:44:55 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a, b, m;
mp_err res;
char *str;
int len, rval = 0;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]);
return 1;
}
mp_init(&a); mp_init(&b); mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
mp_read_radix(&m, argv[3], 10);
if((res = mp_exptmod(&a, &b, &m, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res));
rval = 1;
} else {
len = mp_radix_size(&a, 10);
str = calloc(len, sizeof(char));
mp_toradix(&a, str, 10);
printf("%s\n", str);
free(str);
}
mp_clear(&a); mp_clear(&b); mp_clear(&m);
return rval;
}

View File

@ -0,0 +1,112 @@
/*
* fact.c
*
* Compute factorial of input integer
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: fact.c,v 1.1 2000-07-14 00:44:56 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
mp_err mp_fact(mp_int *a, mp_int *b);
int main(int argc, char *argv[])
{
mp_int a;
mp_err res;
if(argc < 2) {
fprintf(stderr, "Usage: %s <number>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
if((res = mp_fact(&a, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0],
mp_strerror(res));
mp_clear(&a);
return 1;
}
{
char *buf;
int len;
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_todecimal(&a, buf);
puts(buf);
free(buf);
}
mp_clear(&a);
return 0;
}
mp_err mp_fact(mp_int *a, mp_int *b)
{
mp_int ix, s;
mp_err res = MP_OKAY;
if(mp_cmp_z(a) < 0)
return MP_UNDEF;
mp_init(&s);
mp_add_d(&s, 1, &s); /* s = 1 */
mp_init(&ix);
mp_add_d(&ix, 1, &ix); /* ix = 1 */
for(/* */; mp_cmp(&ix, a) <= 0; mp_add_d(&ix, 1, &ix)) {
if((res = mp_mul(&s, &ix, &s)) != MP_OKAY)
break;
}
mp_clear(&ix);
/* Copy out results if we got them */
if(res == MP_OKAY)
mp_copy(&s, b);
mp_clear(&s);
return res;
}

View File

@ -0,0 +1,116 @@
/*
* gcd.c
*
* Greatest common divisor
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: gcd.c,v 1.1 2000-07-14 00:44:56 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
char *g_prog = NULL;
void print_mp_int(mp_int *mp, FILE *ofp);
int main(int argc, char *argv[])
{
mp_int a, b, x, y;
mp_err res;
int ext = 0;
g_prog = argv[0];
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", g_prog);
return 1;
}
mp_init(&a); mp_read_radix(&a, argv[1], 10);
mp_init(&b); mp_read_radix(&b, argv[2], 10);
/* If we were called 'xgcd', compute x, y so that g = ax + by */
if(strcmp(g_prog, "xgcd") == 0) {
ext = 1;
mp_init(&x); mp_init(&y);
}
if(ext) {
if((res = mp_xgcd(&a, &b, &a, &x, &y)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", g_prog, mp_strerror(res));
mp_clear(&a); mp_clear(&b);
mp_clear(&x); mp_clear(&y);
return 1;
}
} else {
if((res = mp_gcd(&a, &b, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", g_prog,
mp_strerror(res));
mp_clear(&a); mp_clear(&b);
return 1;
}
}
print_mp_int(&a, stdout);
if(ext) {
fputs("x = ", stdout); print_mp_int(&x, stdout);
fputs("y = ", stdout); print_mp_int(&y, stdout);
}
mp_clear(&a); mp_clear(&b);
if(ext) {
mp_clear(&x);
mp_clear(&y);
}
return 0;
}
void print_mp_int(mp_int *mp, FILE *ofp)
{
char *buf;
int len;
len = mp_radix_size(mp, 10);
buf = calloc(len, sizeof(char));
mp_todecimal(mp, buf);
fprintf(ofp, "%s\n", buf);
free(buf);
}

View File

@ -0,0 +1,68 @@
/*
* hex2dec.c
*
* Convert decimal integers into hexadecimal
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: hex2dec.c,v 1.1 2000-07-14 00:44:57 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a;
char *buf;
int len;
if(argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
mp_init(&a); mp_read_radix(&a, argv[1], 16);
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_toradix(&a, buf, 10);
printf("%s\n", buf);
free(buf);
mp_clear(&a);
return 0;
}

View File

@ -0,0 +1,89 @@
/*
* invmod.c
*
* Compute modular inverses
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1997, 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: invmod.c,v 1.1 2000-07-14 00:44:57 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
mp_int a, m;
mp_err res;
char *buf;
int len, out = 0;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <m>\n", argv[0]);
return 1;
}
mp_init(&a); mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&m, argv[2], 10);
if(mp_cmp(&a, &m) > 0)
mp_mod(&a, &m, &a);
switch((res = mp_invmod(&a, &m, &a))) {
case MP_OKAY:
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_toradix(&a, buf, 10);
printf("%s\n", buf);
free(buf);
break;
case MP_UNDEF:
printf("No inverse\n");
out = 1;
break;
default:
printf("error: %s (%d)\n", mp_strerror(res), res);
out = 2;
break;
}
mp_clear(&a);
mp_clear(&m);
return out;
}

View File

@ -0,0 +1,118 @@
/*
* isprime.c
*
* Probabilistic primality tester command-line tool
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: isprime.c,v 1.1 2000-07-14 00:44:58 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#include "mpprime.h"
#define RM_TESTS 15 /* how many iterations of Rabin-Miller? */
#define MINIMUM 1024 /* don't bother us with a < this */
int g_tests = RM_TESTS;
char *g_prog = NULL;
int main(int argc, char *argv[])
{
mp_int a;
mp_digit np = prime_tab_size; /* from mpprime.h */
int res = 0;
g_prog = argv[0];
if(argc < 2) {
fprintf(stderr, "Usage: %s <a>, where <a> is a decimal integer\n"
"Use '0x' prefix for a hexadecimal value\n", g_prog);
return 1;
}
/* Read number of tests from environment, if present */
{
char *tmp;
if((tmp = getenv("RM_TESTS")) != NULL) {
if((g_tests = atoi(tmp)) <= 0)
g_tests = RM_TESTS;
}
}
mp_init(&a);
if(argv[1][0] == '0' && argv[1][1] == 'x')
mp_read_radix(&a, argv[1] + 2, 16);
else
mp_read_radix(&a, argv[1], 10);
if(mp_cmp_d(&a, MINIMUM) <= 0) {
fprintf(stderr, "%s: please use a value greater than %d\n",
g_prog, MINIMUM);
mp_clear(&a);
return 1;
}
/* Test for divisibility by small primes */
if(mpp_divis_primes(&a, &np) != MP_NO) {
printf("Not prime (divisible by small prime %d)\n", np);
res = 2;
goto CLEANUP;
}
/* Test with Fermat's test, using 2 as a witness */
if(mpp_fermat(&a, 2) != MP_YES) {
printf("Not prime (failed Fermat test)\n");
res = 2;
goto CLEANUP;
}
/* Test with Rabin-Miller probabilistic test */
if(mpp_pprime(&a, g_tests) == MP_NO) {
printf("Not prime (failed pseudoprime test)\n");
res = 2;
goto CLEANUP;
}
printf("Probably prime, 1 in 4^%d chance of false positive\n", g_tests);
CLEANUP:
mp_clear(&a);
return res;
}

View File

@ -0,0 +1,116 @@
/*
* lap.c
*
* Find least annihilating power of a mod m
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: lap.c,v 1.1 2000-07-14 00:44:58 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "mpi.h"
void sig_catch(int ign);
int g_quit = 0;
int main(int argc, char *argv[])
{
mp_int a, m, p, k;
if(argc < 3) {
fprintf(stderr, "Usage: %s <a> <m>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_init(&m);
mp_init(&p);
mp_add_d(&p, 1, &p);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&m, argv[2], 10);
mp_init_copy(&k, &a);
signal(SIGINT, sig_catch);
signal(SIGHUP, sig_catch);
signal(SIGTERM, sig_catch);
while(mp_cmp(&p, &m) < 0) {
if(g_quit) {
int len;
char *buf;
len = mp_radix_size(&p, 10);
buf = malloc(len);
mp_toradix(&p, buf, 10);
fprintf(stderr, "Terminated at: %s\n", buf);
free(buf);
return 1;
}
if(mp_cmp_d(&k, 1) == 0) {
int len;
char *buf;
len = mp_radix_size(&p, 10);
buf = malloc(len);
mp_toradix(&p, buf, 10);
printf("%s\n", buf);
free(buf);
break;
}
mp_mulmod(&k, &a, &m, &k);
mp_add_d(&p, 1, &p);
}
if(mp_cmp(&p, &m) >= 0)
printf("No annihilating power.\n");
mp_clear(&p);
mp_clear(&m);
mp_clear(&a);
return 0;
}
void sig_catch(int ign)
{
g_quit = 1;
}

View File

@ -0,0 +1,144 @@
/*
* makeprime.c
*
* A simple prime generator function (and test driver). Prints out the
* first prime it finds greater than or equal to the starting value.
*
* Usage: makeprime <start>
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: makeprime.c,v 1.1 2000-07-14 00:44:59 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* These two must be included for make_prime() to work */
#include "mpi.h"
#include "mpprime.h"
/*
make_prime(p, nr)
Find the smallest prime integer greater than or equal to p, where
primality is verified by 'nr' iterations of the Rabin-Miller
probabilistic primality test. The caller is responsible for
generating the initial value of p.
Returns MP_OKAY if a prime has been generated, otherwise the error
code indicates some other problem. The value of p is clobbered; the
caller should keep a copy if the value is needed.
*/
mp_err make_prime(mp_int *p, int nr);
/* The main() is not required -- it's just a test driver */
int main(int argc, char *argv[])
{
mp_int start;
mp_err res;
if(argc < 2) {
fprintf(stderr, "Usage: %s <start-value>\n", argv[0]);
return 1;
}
mp_init(&start);
if(argv[1][0] == '0' && tolower(argv[1][1]) == 'x') {
mp_read_radix(&start, argv[1] + 2, 16);
} else {
mp_read_radix(&start, argv[1], 10);
}
mp_abs(&start, &start);
if((res = make_prime(&start, 5)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res));
mp_clear(&start);
return 1;
} else {
char *buf = malloc(mp_radix_size(&start, 10));
mp_todecimal(&start, buf);
printf("%s\n", buf);
free(buf);
mp_clear(&start);
return 0;
}
} /* end main() */
/*------------------------------------------------------------------------*/
mp_err make_prime(mp_int *p, int nr)
{
mp_err res;
if(mp_iseven(p)) {
mp_add_d(p, 1, p);
}
do {
mp_digit which = prime_tab_size;
/* First test for divisibility by a few small primes */
if((res = mpp_divis_primes(p, &which)) == MP_YES)
continue;
else if(res != MP_NO)
goto CLEANUP;
/* If that passes, try one iteration of Fermat's test */
if((res = mpp_fermat(p, 2)) == MP_NO)
continue;
else if(res != MP_YES)
goto CLEANUP;
/* If that passes, run Rabin-Miller as often as requested */
if((res = mpp_pprime(p, nr)) == MP_YES)
break;
else if(res != MP_NO)
goto CLEANUP;
} while((res = mp_add_d(p, 2, p)) == MP_OKAY);
CLEANUP:
return res;
} /* end make_prime() */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,124 @@
/*
* metime.c
*
* Modular exponentiation timing test
*
* $Id: metime.c,v 1.1 2000-07-14 00:44:59 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
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 2000 Michael J. Fromberger. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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.1 2000-07-14 00:44:59 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mpprime.h"
double clk_to_sec(clock_t start, clock_t stop);
int main(int argc, char *argv[])
{
int ix, num, prec = 8;
unsigned int seed;
clock_t start, stop;
double sec;
mp_int a, m, c;
if(getenv("SEED") != NULL)
seed = abs(atoi(getenv("SEED")));
else
seed = (unsigned int)time(NULL);
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-tests> [<nbits>]\n", argv[0]);
return 1;
}
if((num = atoi(argv[1])) < 0)
num = -num;
if(!num) {
fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
return 1;
}
if(argc > 2) {
if((prec = atoi(argv[2])) <= 0)
prec = 8;
else
prec = (prec + (DIGIT_BIT - 1)) / DIGIT_BIT;
}
printf("Modular exponentiation timing test\n"
"Precision: %d digits (%d bits)\n"
"# of tests: %d\n\n", prec, prec * DIGIT_BIT, num);
mp_init_size(&a, prec);
mp_init_size(&m, prec);
mp_init_size(&c, prec);
srand(seed);
start = clock();
for(ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&c, prec);
mpp_random_size(&m, prec);
mp_exptmod(&a, &c, &m, &c);
}
stop = clock();
sec = clk_to_sec(start, stop);
printf("Total: %.3f seconds\n", sec);
printf("Individual: %.3f seconds\n", sec / num);
mp_clear(&c);
mp_clear(&a);
mp_clear(&m);
return 0;
}
double clk_to_sec(clock_t start, clock_t stop)
{
return (double)(stop - start) / CLOCKS_PER_SEC;
}
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,194 @@
/*
* pi.c
*
* Compute pi to an arbitrary number of digits. Uses Machin's formula,
* like everyone else on the planet:
*
* pi = 16 * arctan(1/5) - 4 * arctan(1/239)
*
* This is pretty effective for up to a few thousand digits, but it
* gets pretty slow after that.
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: pi.c,v 1.1 2000-07-14 00:45:00 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
mp_err arctan(mp_digit mul, mp_digit x, mp_digit prec, mp_int *sum);
int main(int argc, char *argv[])
{
mp_err res;
mp_digit ndigits;
mp_int sum1, sum2;
clock_t start, stop;
int out = 0;
/* Make the user specify precision on the command line */
if(argc < 2) {
fprintf(stderr, "Usage: %s <num-digits>\n", argv[0]);
return 1;
}
if((ndigits = abs(atoi(argv[1]))) == 0) {
fprintf(stderr, "%s: you must request at least 1 digit\n", argv[0]);
return 1;
}
start = clock();
mp_init(&sum1); mp_init(&sum2);
/* sum1 = 16 * arctan(1/5) */
if((res = arctan(16, 5, ndigits, &sum1)) != MP_OKAY) {
fprintf(stderr, "%s: arctan: %s\n", argv[0], mp_strerror(res));
out = 1; goto CLEANUP;
}
/* sum2 = 4 * arctan(1/239) */
if((res = arctan(4, 239, ndigits, &sum2)) != MP_OKAY) {
fprintf(stderr, "%s: arctan: %s\n", argv[0], mp_strerror(res));
out = 1; goto CLEANUP;
}
/* pi = sum1 - sum2 */
if((res = mp_sub(&sum1, &sum2, &sum1)) != MP_OKAY) {
fprintf(stderr, "%s: mp_sub: %s\n", argv[0], mp_strerror(res));
out = 1; goto CLEANUP;
}
stop = clock();
/* Write the output in decimal */
{
char *buf = malloc(mp_radix_size(&sum1, 10));
if(buf == NULL) {
fprintf(stderr, "%s: out of memory\n", argv[0]);
out = 1; goto CLEANUP;
}
mp_todecimal(&sum1, buf);
printf("%s\n", buf);
free(buf);
}
fprintf(stderr, "Computation took %.2f sec.\n",
(double)(stop - start) / CLOCKS_PER_SEC);
CLEANUP:
mp_clear(&sum1);
mp_clear(&sum2);
return out;
}
/* Compute sum := mul * arctan(1/x), to 'prec' digits of precision */
mp_err arctan(mp_digit mul, mp_digit x, mp_digit prec, mp_int *sum)
{
mp_int t, v;
mp_digit q = 1, rd;
mp_err res;
int sign = 1;
prec += 3; /* push inaccuracies off the end */
mp_init(&t); mp_set(&t, 10);
mp_init(&v);
if((res = mp_expt_d(&t, prec, &t)) != MP_OKAY || /* get 10^prec */
(res = mp_mul_d(&t, mul, &t)) != MP_OKAY || /* ... times mul */
(res = mp_mul_d(&t, x, &t)) != MP_OKAY) /* ... times x */
goto CLEANUP;
/*
The extra multiplication by x in the above takes care of what
would otherwise have to be a special case for 1 / x^1 during the
first loop iteration. A little sneaky, but effective.
We compute arctan(1/x) by the formula:
1 1 1 1
- - ----- + ----- - ----- + ...
x 3 x^3 5 x^5 7 x^7
We multiply through by 'mul' beforehand, which gives us a couple
more iterations and more precision
*/
x *= x; /* works as long as x < sqrt(RADIX), which it is here */
mp_zero(sum);
do {
if((res = mp_div_d(&t, x, &t, &rd)) != MP_OKAY)
goto CLEANUP;
if(sign < 0 && rd != 0)
mp_add_d(&t, 1, &t);
if((res = mp_div_d(&t, q, &v, &rd)) != MP_OKAY)
goto CLEANUP;
if(sign < 0 && rd != 0)
mp_add_d(&v, 1, &v);
if(sign > 0)
res = mp_add(sum, &v, sum);
else
res = mp_sub(sum, &v, sum);
if(res != MP_OKAY)
goto CLEANUP;
sign *= -1;
q += 2;
} while(mp_cmp_z(&t) != 0);
/* Chop off inaccurate low-order digits */
mp_div_d(sum, 1000, sum, NULL);
CLEANUP:
mp_clear(&v);
mp_clear(&t);
return res;
}
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View File

@ -0,0 +1,305 @@
/*
* primegen.c
*
* Generates random integers which are prime with a high degree of
* probability using the Miller-Rabin probabilistic primality testing
* algorithm.
*
* Usage:
* primegen <bits> [<num>]
*
* <bits> - number of significant bits each prime should have
* <num> - number of primes to generate
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: primegen.c,v 1.1 2000-07-14 00:45:00 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mpprime.h"
#undef MACOS /* define if running on a Macintosh */
#ifdef MACOS
#include <console.h>
#endif
#define NUM_TESTS 5 /* Number of Rabin-Miller iterations to test with */
int g_strong = 0;
int main(int argc, char *argv[])
{
unsigned char *raw;
char *out;
int rawlen, bits, outlen, ngen, ix, jx;
mp_int testval, ntries;
mp_err res;
mp_digit np;
clock_t start, end;
#ifdef MACOS
argc = ccommand(&argv);
#endif
/* We'll just use the C library's rand() for now, although this
won't be good enough for cryptographic purposes */
if((out = getenv("SEED")) == NULL) {
srand((unsigned int)time(NULL));
} else {
srand((unsigned int)atoi(out));
}
if(argc < 2) {
fprintf(stderr, "Usage: %s <bits> [<count> [strong]]\n", argv[0]);
return 1;
}
if((bits = abs(atoi(argv[1]))) < CHAR_BIT) {
fprintf(stderr, "%s: please request at least %d bits.\n",
argv[0], CHAR_BIT);
return 1;
}
/* If optional third argument is given, use that as the number of
primes to generate; otherwise generate one prime only.
*/
if(argc < 3) {
ngen = 1;
} else {
ngen = abs(atoi(argv[2]));
}
/* If fourth argument is given, and is the word "strong", we'll
generate strong (Sophie Germain) primes.
*/
if(argc > 3 && strcmp(argv[3], "strong") == 0)
g_strong = 1;
/* testval - candidate being tested; ntries - number tried so far */
if((res = mp_init(&testval)) != MP_OKAY ||
(res = mp_init(&ntries)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res));
return 1;
}
if(g_strong) {
printf("Requested %d strong prime values of at least %d bits.\n",
ngen, bits);
} else {
printf("Requested %d prime values of at least %d bits.\n", ngen, bits);
}
rawlen = (bits / CHAR_BIT) + ((bits % CHAR_BIT) ? 1 : 0) + 1;
if((raw = calloc(rawlen, sizeof(unsigned char))) == NULL) {
fprintf(stderr, "%s: out of memory, sorry.\n", argv[0]);
return 1;
}
/* This loop is one for each prime we need to generate */
for(jx = 0; jx < ngen; jx++) {
raw[0] = 0; /* sign is positive */
/* Pack the initializer with random bytes */
for(ix = 1; ix < rawlen; ix++)
raw[ix] = (rand() * rand()) & UCHAR_MAX;
raw[1] |= 0x80; /* set high-order bit of test value */
if(g_strong)
raw[rawlen - 1] |= 3; /* set low-order two bits of test value */
else
raw[rawlen - 1] |= 1; /* set low-order bit of test value */
/* Make an mp_int out of the initializer */
mp_read_raw(&testval, (char *)raw, rawlen);
/* If we asked for a strong prime, shift down one bit so that when
we double, we're still within the right range of bits ... this
is why we OR'd with 3 instead of 1 above
*/
if(g_strong)
mp_div_2(&testval, &testval);
/* Initialize candidate counter */
mp_zero(&ntries);
mp_add_d(&ntries, 1, &ntries);
start = clock(); /* time generation for this prime */
for(;;) {
/*
Test for divisibility by small primes (of which there is a table
conveniently stored in mpprime.c)
*/
np = prime_tab_size;
if(mpp_divis_primes(&testval, &np) == MP_NO) {
/* If that passed, run a Fermat test */
res = mpp_fermat(&testval, 2);
switch(res) {
case MP_NO: /* composite */
goto NEXT_CANDIDATE;
case MP_YES: /* may be prime */
break;
default:
goto CLEANUP; /* some other error */
}
/* If that passed, run some Miller-Rabin tests */
res = mpp_pprime(&testval, NUM_TESTS);
switch(res) {
case MP_NO: /* composite */
goto NEXT_CANDIDATE;
case MP_YES: /* may be prime */
break;
default:
goto CLEANUP; /* some other error */
}
/* At this point, we have strong evidence that our candidate
is itself prime. If we want a strong prime, we need now
to test q = 2p + 1 for primality...
*/
if(g_strong) {
if(res == MP_YES) {
mp_int q;
fputc('.', stderr);
mp_init_copy(&q, &testval);
mp_mul_2(&q, &q);
mp_add_d(&q, 1, &q);
/* Test q for small prime divisors ... */
np = prime_tab_size;
if(mpp_divis_primes(&q, &np) == MP_YES) {
mp_clear(&q);
goto NEXT_CANDIDATE;
}
/* And, with Fermat, as with its parent ... */
res = mpp_fermat(&q, 2);
switch(res) {
case MP_NO: /* composite */
mp_clear(&q);
goto NEXT_CANDIDATE;
case MP_YES: /* may be prime */
break;
default:
mp_clear(&q);
goto CLEANUP; /* some other error */
}
/* And, with Miller-Rabin, as with its parent ... */
res = mpp_pprime(&q, NUM_TESTS);
switch(res) {
case MP_NO: /* composite */
mp_clear(&q);
goto NEXT_CANDIDATE;
case MP_YES: /* may be prime */
break;
default:
mp_clear(&q);
goto CLEANUP; /* some other error */
}
/* If it passed, we've got a winner */
if(res == MP_YES) {
fputc('\n', stderr);
mp_copy(&q, &testval);
mp_clear(&q);
break;
}
mp_clear(&q);
} /* end if(res == MP_YES) */
} else {
/* We get here if g_strong is false */
if(res == MP_YES)
break;
}
} /* end if(not divisible by small primes) */
/*
If we're testing strong primes, skip to the next odd value
congruent to 3 (mod 4). Otherwise, just skip to the next odd
value
*/
NEXT_CANDIDATE:
if(g_strong)
mp_add_d(&testval, 4, &testval);
else
mp_add_d(&testval, 2, &testval);
mp_add_d(&ntries, 1, &ntries);
} /* end of loop to generate a single prime */
end = clock();
printf("After %d tests, the following value is still probably prime:\n",
NUM_TESTS);
outlen = mp_radix_size(&testval, 10);
out = calloc(outlen, sizeof(unsigned char));
mp_toradix(&testval, (char *)out, 10);
printf("10: %s\n", out);
mp_toradix(&testval, (char *)out, 16);
printf("16: %s\n\n", out);
free(out);
printf("Number of candidates tried: ");
outlen = mp_radix_size(&ntries, 10);
out = calloc(outlen, sizeof(unsigned char));
mp_toradix(&ntries, (char *)out, 10);
printf("%s\n", out);
free(out);
printf("This computation took %ld clock ticks (%.2f seconds)\n",
(end - start), ((double)(end - start) / CLOCKS_PER_SEC));
fputc('\n', stdout);
} /* end of loop to generate all requested primes */
CLEANUP:
if(res != MP_OKAY)
fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res));
free(raw);
mp_clear(&testval);
return 0;
}

View File

@ -0,0 +1,82 @@
/*
* prng.c
*
* Command-line pseudo-random number generator
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: prng.c,v 1.1 2000-07-14 00:45:01 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include "bbs_rand.h"
int main(int argc, char *argv[])
{
unsigned char *seed;
unsigned int ix, num = 1;
pid_t pid;
if(argc > 1) {
num = atoi(argv[1]);
if(num <= 0)
num = 1;
}
pid = getpid();
srand(time(NULL) * (unsigned int)pid);
/* Not a perfect seed, but not bad */
seed = malloc(bbs_seed_size);
for(ix = 0; ix < bbs_seed_size; ix++) {
seed[ix] = rand() % UCHAR_MAX;
}
bbs_srand(seed, bbs_seed_size);
memset(seed, 0, bbs_seed_size);
free(seed);
while(num-- > 0) {
ix = bbs_rand();
printf("%u\n", ix);
}
return 0;
}

View File

@ -0,0 +1,58 @@
#!/usr/linguist/bin/perl
##
## The contents of this file are subject to the Mozilla Public
## License Version 1.1 (the "License"); you may not use this file
## except in compliance with the License. You may obtain a copy of
## the License at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS
## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
## implied. See the License for the specific language governing
## rights and limitations under the License.
##
## The Original Code is the MPI Arbitrary Precision Integer Arithmetic
## library.
##
## The Initial Developer of the Original Code is
## Michael J. Fromberger <sting@linguist.dartmouth.edu>
##
## Portions created by Michael J. Fromberger are
## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved.
##
## Contributor(s):
##
## Alternatively, the contents of this file may be used under the
## terms of the GNU General Public License Version 2 or later (the
## "GPL"), in which case the provisions of the GPL are applicable
## instead of those above. If you wish to allow use of your
## version of this file only under the terms of the GPL and not to
## allow others to use your version of this file under the MPL,
## indicate your decision by deleting the provisions above and
## replace them with the notice and other provisions required by
## 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: ptab.pl,v 1.1 2000-07-14 00:45:01 nelsonb%netscape.com Exp $
##
while(<>) {
chomp;
push(@primes, $_);
}
printf("mp_size prime_tab_size = %d;\n", ($#primes + 1));
print "mp_digit prime_tab[] = {\n";
print "\t";
$last = pop(@primes);
foreach $prime (sort {$a<=>$b} @primes) {
printf("0x%04X, ", $prime);
$brk = ($brk + 1) % 8;
print "\n\t" if(!$brk);
}
printf("0x%04X", $last);
print "\n" if($brk);
print "};\n\n";
exit 0;

View File

@ -0,0 +1,265 @@
/*
* sieve.c
*
* Finds prime numbers using the Sieve of Eratosthenes
*
* This implementation uses a bitmap to represent all odd integers in a
* given range. We iterate over this bitmap, crossing off the
* multiples of each prime we find. At the end, all the remaining set
* bits correspond to prime integers.
*
* Here, we make two passes -- once we have generated a sieve-ful of
* primes, we copy them out, reset the sieve using the highest
* generated prime from the first pass as a base. Then we cross out
* all the multiples of all the primes we found the first time through,
* and re-sieve. In this way, we get double use of the memory we
* allocated for the sieve the first time though. Since we also
* implicitly ignore multiples of 2, this amounts to 4 times the
* values.
*
* This could (and probably will) be generalized to re-use the sieve a
* few more times.
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the MPI Arbitrary Precision Integer Arithmetic
* library.
*
* The Initial Developer of the Original Code is Michael J. Fromberger.
* Portions created by Michael J. Fromberger are
* Copyright (C) 1998, 1999, 2000 Michael J. Fromberger.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* 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: sieve.c,v 1.1 2000-07-14 00:45:02 nelsonb%netscape.com Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef unsigned char byte;
typedef struct {
int size;
byte *bits;
long base;
int next;
int nbits;
} sieve;
void sieve_init(sieve *sp, long base, int nbits);
void sieve_grow(sieve *sp, int nbits);
long sieve_next(sieve *sp);
void sieve_reset(sieve *sp, long base);
void sieve_cross(sieve *sp, long val);
void sieve_clear(sieve *sp);
#define S_ISSET(S, B) (((S)->bits[(B)/CHAR_BIT]>>((B)%CHAR_BIT))&1)
#define S_SET(S, B) ((S)->bits[(B)/CHAR_BIT]|=(1<<((B)%CHAR_BIT)))
#define S_CLR(S, B) ((S)->bits[(B)/CHAR_BIT]&=~(1<<((B)%CHAR_BIT)))
#define S_VAL(S, B) ((S)->base+(2*(B)))
#define S_BIT(S, V) (((V)-((S)->base))/2)
int main(int argc, char *argv[])
{
sieve s;
long pr, *p;
int c, ix, cur = 0;
if(argc < 2) {
fprintf(stderr, "Usage: %s <width>\n", argv[0]);
return 1;
}
c = atoi(argv[1]);
if(c < 0) c = -c;
fprintf(stderr, "%s: sieving to %d positions\n", argv[0], c);
sieve_init(&s, 3, c);
c = 0;
while((pr = sieve_next(&s)) > 0) {
++c;
}
p = calloc(c, sizeof(long));
if(!p) {
fprintf(stderr, "%s: out of memory after first half\n", argv[0]);
sieve_clear(&s);
exit(1);
}
fprintf(stderr, "%s: half done ... \n", argv[0]);
for(ix = 0; ix < s.nbits; ix++) {
if(S_ISSET(&s, ix)) {
p[cur] = S_VAL(&s, ix);
printf("%ld\n", p[cur]);
++cur;
}
}
sieve_reset(&s, p[cur - 1]);
fprintf(stderr, "%s: crossing off %d found primes ... \n", argv[0], cur);
for(ix = 0; ix < cur; ix++) {
sieve_cross(&s, p[ix]);
if(!(ix % 1000))
fputc('.', stderr);
}
fputc('\n', stderr);
free(p);
fprintf(stderr, "%s: sieving again from %ld ... \n", argv[0], p[cur - 1]);
c = 0;
while((pr = sieve_next(&s)) > 0) {
++c;
}
fprintf(stderr, "%s: done!\n", argv[0]);
for(ix = 0; ix < s.nbits; ix++) {
if(S_ISSET(&s, ix)) {
printf("%ld\n", S_VAL(&s, ix));
}
}
sieve_clear(&s);
return 0;
}
void sieve_init(sieve *sp, long base, int nbits)
{
sp->size = (nbits / CHAR_BIT);
if(nbits % CHAR_BIT)
++sp->size;
sp->bits = calloc(sp->size, sizeof(byte));
memset(sp->bits, UCHAR_MAX, sp->size);
if(!(base & 1))
++base;
sp->base = base;
sp->next = 0;
sp->nbits = sp->size * CHAR_BIT;
}
void sieve_grow(sieve *sp, int nbits)
{
int ns = (nbits / CHAR_BIT);
if(nbits % CHAR_BIT)
++ns;
if(ns > sp->size) {
byte *tmp;
int ix;
tmp = calloc(ns, sizeof(byte));
if(tmp == NULL) {
fprintf(stderr, "Error: out of memory in sieve_grow\n");
return;
}
memcpy(tmp, sp->bits, sp->size);
for(ix = sp->size; ix < ns; ix++) {
tmp[ix] = UCHAR_MAX;
}
free(sp->bits);
sp->bits = tmp;
sp->size = ns;
sp->nbits = sp->size * CHAR_BIT;
}
}
long sieve_next(sieve *sp)
{
long out;
int ix = 0;
long val;
if(sp->next > sp->nbits)
return -1;
out = S_VAL(sp, sp->next);
#ifdef DEBUG
fprintf(stderr, "Sieving %ld\n", out);
#endif
/* Sieve out all multiples of the current prime */
val = out;
while(ix < sp->nbits) {
val += out;
ix = S_BIT(sp, val);
if((val & 1) && ix < sp->nbits) { /* && S_ISSET(sp, ix)) { */
S_CLR(sp, ix);
#ifdef DEBUG
fprintf(stderr, "Crossing out %ld (bit %d)\n", val, ix);
#endif
}
}
/* Scan ahead to the next prime */
++sp->next;
while(sp->next < sp->nbits && !S_ISSET(sp, sp->next))
++sp->next;
return out;
}
void sieve_cross(sieve *sp, long val)
{
int ix = 0;
long cur = val;
while(cur < sp->base)
cur += val;
ix = S_BIT(sp, cur);
while(ix < sp->nbits) {
if(cur & 1)
S_CLR(sp, ix);
cur += val;
ix = S_BIT(sp, cur);
}
}
void sieve_reset(sieve *sp, long base)
{
memset(sp->bits, UCHAR_MAX, sp->size);
sp->base = base;
sp->next = 0;
}
void sieve_clear(sieve *sp)
{
if(sp->bits)
free(sp->bits);
sp->bits = NULL;
}