Remove unused bigint from runtime
This commit is contained in:
parent
2791877009
commit
b43e639bf6
|
@ -578,7 +578,7 @@ for t in $CFG_TARGET_TRIPLES
|
||||||
do
|
do
|
||||||
make_dir rt/$t
|
make_dir rt/$t
|
||||||
for i in \
|
for i in \
|
||||||
isaac linenoise bigint sync test arch/i386 arch/x86_64 \
|
isaac linenoise sync test arch/i386 arch/x86_64 \
|
||||||
libuv libuv/src/ares libuv/src/eio libuv/src/ev
|
libuv libuv/src/ares libuv/src/eio libuv/src/ev
|
||||||
do
|
do
|
||||||
make_dir rt/$t/$i
|
make_dir rt/$t/$i
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
/* bigint.h - include file for bigint package
|
|
||||||
**
|
|
||||||
** This library lets you do math on arbitrarily large integers. It's
|
|
||||||
** pretty fast - compared with the multi-precision routines in the "bc"
|
|
||||||
** calculator program, these routines are between two and twelve times faster,
|
|
||||||
** except for division which is maybe half as fast.
|
|
||||||
**
|
|
||||||
** The calling convention is a little unusual. There's a basic problem
|
|
||||||
** with writing a math library in a language that doesn't do automatic
|
|
||||||
** garbage collection - what do you do about intermediate results?
|
|
||||||
** You'd like to be able to write code like this:
|
|
||||||
**
|
|
||||||
** d = bi_sqrt( bi_add( bi_multiply( x, x ), bi_multiply( y, y ) ) );
|
|
||||||
**
|
|
||||||
** That works fine when the numbers being passed back and forth are
|
|
||||||
** actual values - ints, floats, or even fixed-size structs. However,
|
|
||||||
** when the numbers can be any size, as in this package, then you have
|
|
||||||
** to pass them around as pointers to dynamically-allocated objects.
|
|
||||||
** Those objects have to get de-allocated after you are done with them.
|
|
||||||
** But how do you de-allocate the intermediate results in a complicated
|
|
||||||
** multiple-call expression like the above?
|
|
||||||
**
|
|
||||||
** There are two common solutions to this problem. One, switch all your
|
|
||||||
** code to a language that provides automatic garbage collection, for
|
|
||||||
** example Java. This is a fine idea and I recommend you do it wherever
|
|
||||||
** it's feasible. Two, change your routines to use a calling convention
|
|
||||||
** that prevents people from writing multiple-call expressions like that.
|
|
||||||
** The resulting code will be somewhat clumsy-looking, but it will work
|
|
||||||
** just fine.
|
|
||||||
**
|
|
||||||
** This package uses a third method, which I haven't seen used anywhere
|
|
||||||
** before. It's simple: each number can be used precisely once, after
|
|
||||||
** which it is automatically de-allocated. This handles the anonymous
|
|
||||||
** intermediate values perfectly. Named values still need to be copied
|
|
||||||
** and freed explicitly. Here's the above example using this convention:
|
|
||||||
**
|
|
||||||
** d = bi_sqrt( bi_add(
|
|
||||||
** bi_multiply( bi_copy( x ), bi_copy( x ) ),
|
|
||||||
** bi_multiply( bi_copy( y ), bi_copy( y ) ) ) );
|
|
||||||
** bi_free( x );
|
|
||||||
** bi_free( y );
|
|
||||||
**
|
|
||||||
** Or, since the package contains a square routine, you could just write:
|
|
||||||
**
|
|
||||||
** d = bi_sqrt( bi_add( bi_square( x ), bi_square( y ) ) );
|
|
||||||
**
|
|
||||||
** This time the named values are only being used once, so you don't
|
|
||||||
** have to copy and free them.
|
|
||||||
**
|
|
||||||
** This really works, however you do have to be very careful when writing
|
|
||||||
** your code. If you leave out a bi_copy() and use a value more than once,
|
|
||||||
** you'll get a runtime error about "zero refs" and a SIGFPE. Run your
|
|
||||||
** code in a debugger, get a backtrace to see where the call was, and then
|
|
||||||
** eyeball the code there to see where you need to add the bi_copy().
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions
|
|
||||||
** are met:
|
|
||||||
** 1. Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
** SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Type definition for bigints - it's an opaque type, the real definition
|
|
||||||
** is in bigint.c.
|
|
||||||
*/
|
|
||||||
typedef void* bigint;
|
|
||||||
|
|
||||||
|
|
||||||
/* Some convenient pre-initialized numbers. These are all permanent,
|
|
||||||
** so you can use them as many times as you want without calling bi_copy().
|
|
||||||
*/
|
|
||||||
extern bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint;
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the bigint package. You must call this when your program
|
|
||||||
** starts up.
|
|
||||||
*/
|
|
||||||
void bi_initialize( void );
|
|
||||||
|
|
||||||
/* Shut down the bigint package. You should call this when your program
|
|
||||||
** exits. It's not actually required, but it does do some consistency
|
|
||||||
** checks which help keep your program bug-free, so you really ought
|
|
||||||
** to call it.
|
|
||||||
*/
|
|
||||||
void bi_terminate( void );
|
|
||||||
|
|
||||||
/* Run in unsafe mode, skipping most runtime checks. Slightly faster.
|
|
||||||
** Once your code is debugged you can add this call after bi_initialize().
|
|
||||||
*/
|
|
||||||
void bi_no_check( void );
|
|
||||||
|
|
||||||
/* Make a copy of a bigint. You must call this if you want to use a
|
|
||||||
** bigint more than once. (Or you can make the bigint permanent.)
|
|
||||||
** Note that this routine is very cheap - all it actually does is
|
|
||||||
** increment a reference counter.
|
|
||||||
*/
|
|
||||||
bigint bi_copy( bigint bi );
|
|
||||||
|
|
||||||
/* Make a bigint permanent, so it doesn't get automatically freed when
|
|
||||||
** used as an operand.
|
|
||||||
*/
|
|
||||||
void bi_permanent( bigint bi );
|
|
||||||
|
|
||||||
/* Undo bi_permanent(). The next use will free the bigint. */
|
|
||||||
void bi_depermanent( bigint bi );
|
|
||||||
|
|
||||||
/* Explicitly free a bigint. Normally bigints get freed automatically
|
|
||||||
** when they are used as an operand. This routine lets you free one
|
|
||||||
** without using it. If the bigint is permanent, this doesn't do
|
|
||||||
** anything, you have to depermanent it first.
|
|
||||||
*/
|
|
||||||
void bi_free( bigint bi );
|
|
||||||
|
|
||||||
/* Compare two bigints. Returns -1, 0, or 1. */
|
|
||||||
int bi_compare( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* Convert an int to a bigint. */
|
|
||||||
bigint int_to_bi( int i );
|
|
||||||
|
|
||||||
/* Convert a string to a bigint. */
|
|
||||||
bigint str_to_bi( char* str );
|
|
||||||
|
|
||||||
/* Convert a bigint to an int. SIGFPE on overflow. */
|
|
||||||
int bi_to_int( bigint bi );
|
|
||||||
|
|
||||||
/* Write a bigint to a file. */
|
|
||||||
void bi_print( FILE* f, bigint bi );
|
|
||||||
|
|
||||||
/* Read a bigint from a file. */
|
|
||||||
bigint bi_scan( FILE* f );
|
|
||||||
|
|
||||||
|
|
||||||
/* Operations on a bigint and a regular int. */
|
|
||||||
|
|
||||||
/* Add an int to a bigint. */
|
|
||||||
bigint bi_int_add( bigint bi, int i );
|
|
||||||
|
|
||||||
/* Subtract an int from a bigint. */
|
|
||||||
bigint bi_int_subtract( bigint bi, int i );
|
|
||||||
|
|
||||||
/* Multiply a bigint by an int. */
|
|
||||||
bigint bi_int_multiply( bigint bi, int i );
|
|
||||||
|
|
||||||
/* Divide a bigint by an int. SIGFPE on divide-by-zero. */
|
|
||||||
bigint bi_int_divide( bigint binumer, int denom );
|
|
||||||
|
|
||||||
/* Take the remainder of a bigint by an int, with an int result.
|
|
||||||
** SIGFPE if m is zero.
|
|
||||||
*/
|
|
||||||
int bi_int_rem( bigint bi, int m );
|
|
||||||
|
|
||||||
/* Take the modulus of a bigint by an int, with an int result.
|
|
||||||
** Note that mod is not rem: mod is always within [0..m), while
|
|
||||||
** rem can be negative. SIGFPE if m is zero or negative.
|
|
||||||
*/
|
|
||||||
int bi_int_mod( bigint bi, int m );
|
|
||||||
|
|
||||||
|
|
||||||
/* Basic operations on two bigints. */
|
|
||||||
|
|
||||||
/* Add two bigints. */
|
|
||||||
bigint bi_add( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* Subtract bib from bia. */
|
|
||||||
bigint bi_subtract( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* Multiply two bigints. */
|
|
||||||
bigint bi_multiply( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* Divide one bigint by another. SIGFPE on divide-by-zero. */
|
|
||||||
bigint bi_divide( bigint binumer, bigint bidenom );
|
|
||||||
|
|
||||||
/* Binary division of one bigint by another. SIGFPE on divide-by-zero.
|
|
||||||
** This is here just for testing. It's about five times slower than
|
|
||||||
** regular division.
|
|
||||||
*/
|
|
||||||
bigint bi_binary_divide( bigint binumer, bigint bidenom );
|
|
||||||
|
|
||||||
/* Take the remainder of one bigint by another. SIGFPE if bim is zero. */
|
|
||||||
bigint bi_rem( bigint bia, bigint bim );
|
|
||||||
|
|
||||||
/* Take the modulus of one bigint by another. Note that mod is not rem:
|
|
||||||
** mod is always within [0..bim), while rem can be negative. SIGFPE if
|
|
||||||
** bim is zero or negative.
|
|
||||||
*/
|
|
||||||
bigint bi_mod( bigint bia, bigint bim );
|
|
||||||
|
|
||||||
|
|
||||||
/* Some less common operations. */
|
|
||||||
|
|
||||||
/* Negate a bigint. */
|
|
||||||
bigint bi_negate( bigint bi );
|
|
||||||
|
|
||||||
/* Absolute value of a bigint. */
|
|
||||||
bigint bi_abs( bigint bi );
|
|
||||||
|
|
||||||
/* Divide a bigint in half. */
|
|
||||||
bigint bi_half( bigint bi );
|
|
||||||
|
|
||||||
/* Multiply a bigint by two. */
|
|
||||||
bigint bi_double( bigint bi );
|
|
||||||
|
|
||||||
/* Square a bigint. */
|
|
||||||
bigint bi_square( bigint bi );
|
|
||||||
|
|
||||||
/* Raise bi to the power of biexp. SIGFPE if biexp is negative. */
|
|
||||||
bigint bi_power( bigint bi, bigint biexp );
|
|
||||||
|
|
||||||
/* Integer square root. */
|
|
||||||
bigint bi_sqrt( bigint bi );
|
|
||||||
|
|
||||||
/* Factorial. */
|
|
||||||
bigint bi_factorial( bigint bi );
|
|
||||||
|
|
||||||
|
|
||||||
/* Some predicates. */
|
|
||||||
|
|
||||||
/* 1 if the bigint is odd, 0 if it's even. */
|
|
||||||
int bi_is_odd( bigint bi );
|
|
||||||
|
|
||||||
/* 1 if the bigint is even, 0 if it's odd. */
|
|
||||||
int bi_is_even( bigint bi );
|
|
||||||
|
|
||||||
/* 1 if the bigint equals zero, 0 if it's nonzero. */
|
|
||||||
int bi_is_zero( bigint bi );
|
|
||||||
|
|
||||||
/* 1 if the bigint equals one, 0 otherwise. */
|
|
||||||
int bi_is_one( bigint bi );
|
|
||||||
|
|
||||||
/* 1 if the bigint is less than zero, 0 if it's zero or greater. */
|
|
||||||
int bi_is_negative( bigint bi );
|
|
||||||
|
|
||||||
|
|
||||||
/* Now we get into the esoteric number-theory stuff used for cryptography. */
|
|
||||||
|
|
||||||
/* Modular exponentiation. Much faster than bi_mod(bi_power(bi,biexp),bim).
|
|
||||||
** Also, biexp can be negative.
|
|
||||||
*/
|
|
||||||
bigint bi_mod_power( bigint bi, bigint biexp, bigint bim );
|
|
||||||
|
|
||||||
/* Modular inverse. mod( bi * modinv(bi), bim ) == 1. SIGFPE if bi is not
|
|
||||||
** relatively prime to bim.
|
|
||||||
*/
|
|
||||||
bigint bi_mod_inverse( bigint bi, bigint bim );
|
|
||||||
|
|
||||||
/* Produce a random number in the half-open interval [0..bi). You need
|
|
||||||
** to have called srandom() before using this.
|
|
||||||
*/
|
|
||||||
bigint bi_random( bigint bi );
|
|
||||||
|
|
||||||
/* Greatest common divisor of two bigints. Euclid's algorithm. */
|
|
||||||
bigint bi_gcd( bigint bim, bigint bin );
|
|
||||||
|
|
||||||
/* Greatest common divisor of two bigints, plus the corresponding multipliers.
|
|
||||||
** Extended Euclid's algorithm.
|
|
||||||
*/
|
|
||||||
bigint bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul );
|
|
||||||
|
|
||||||
/* Least common multiple of two bigints. */
|
|
||||||
bigint bi_lcm( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* The Jacobi symbol. SIGFPE if bib is even. */
|
|
||||||
bigint bi_jacobi( bigint bia, bigint bib );
|
|
||||||
|
|
||||||
/* Probabalistic prime checking. A non-zero return means the probability
|
|
||||||
** that bi is prime is at least 1 - 1/2 ^ certainty.
|
|
||||||
*/
|
|
||||||
int bi_is_probable_prime( bigint bi, int certainty );
|
|
||||||
|
|
||||||
/* Random probabilistic prime with the specified number of bits. */
|
|
||||||
bigint bi_generate_prime( int bits, int certainty );
|
|
||||||
|
|
||||||
/* Number of bits in the number. The log base 2, approximately. */
|
|
||||||
int bi_bits( bigint bi );
|
|
|
@ -1,553 +0,0 @@
|
||||||
/* bigint_ext - external portion of large integer package
|
|
||||||
**
|
|
||||||
** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions
|
|
||||||
** are met:
|
|
||||||
** 1. Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in the
|
|
||||||
** documentation and/or other materials provided with the distribution.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
** SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "bigint.h"
|
|
||||||
#include "low_primes.h"
|
|
||||||
|
|
||||||
|
|
||||||
bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint;
|
|
||||||
|
|
||||||
|
|
||||||
/* Forwards. */
|
|
||||||
static void print_pos( FILE* f, bigint bi );
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
str_to_bi( char* str )
|
|
||||||
{
|
|
||||||
int sign;
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
sign = 1;
|
|
||||||
if ( *str == '-' )
|
|
||||||
{
|
|
||||||
sign = -1;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
for ( biR = bi_0; *str >= '0' && *str <= '9'; ++str )
|
|
||||||
biR = bi_int_add( bi_int_multiply( biR, 10 ), *str - '0' );
|
|
||||||
if ( sign == -1 )
|
|
||||||
biR = bi_negate( biR );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
bi_print( FILE* f, bigint bi )
|
|
||||||
{
|
|
||||||
if ( bi_is_negative( bi_copy( bi ) ) )
|
|
||||||
{
|
|
||||||
putc( '-', f );
|
|
||||||
bi = bi_negate( bi );
|
|
||||||
}
|
|
||||||
print_pos( f, bi );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_scan( FILE* f )
|
|
||||||
{
|
|
||||||
int sign;
|
|
||||||
int c;
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
sign = 1;
|
|
||||||
c = getc( f );
|
|
||||||
if ( c == '-' )
|
|
||||||
sign = -1;
|
|
||||||
else
|
|
||||||
ungetc( c, f );
|
|
||||||
|
|
||||||
biR = bi_0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
c = getc( f );
|
|
||||||
if ( c < '0' || c > '9' )
|
|
||||||
break;
|
|
||||||
biR = bi_int_add( bi_int_multiply( biR, 10 ), c - '0' );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sign == -1 )
|
|
||||||
biR = bi_negate( biR );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_pos( FILE* f, bigint bi )
|
|
||||||
{
|
|
||||||
if ( bi_compare( bi_copy( bi ), bi_10 ) >= 0 )
|
|
||||||
print_pos( f, bi_int_divide( bi_copy( bi ), 10 ) );
|
|
||||||
putc( bi_int_mod( bi, 10 ) + '0', f );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
bi_int_mod( bigint bi, int m )
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if ( m <= 0 )
|
|
||||||
{
|
|
||||||
(void) fprintf( stderr, "bi_int_mod: zero or negative modulus\n" );
|
|
||||||
(void) kill( getpid(), SIGFPE );
|
|
||||||
}
|
|
||||||
r = bi_int_rem( bi, m );
|
|
||||||
if ( r < 0 )
|
|
||||||
r += m;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_rem( bigint bia, bigint bim )
|
|
||||||
{
|
|
||||||
return bi_subtract(
|
|
||||||
bia, bi_multiply( bi_divide( bi_copy( bia ), bi_copy( bim ) ), bim ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_mod( bigint bia, bigint bim )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
if ( bi_compare( bi_copy( bim ), bi_0 ) <= 0 )
|
|
||||||
{
|
|
||||||
(void) fprintf( stderr, "bi_mod: zero or negative modulus\n" );
|
|
||||||
(void) kill( getpid(), SIGFPE );
|
|
||||||
}
|
|
||||||
biR = bi_rem( bia, bi_copy( bim ) );
|
|
||||||
if ( bi_is_negative( bi_copy( biR ) ) )
|
|
||||||
biR = bi_add( biR, bim );
|
|
||||||
else
|
|
||||||
bi_free( bim );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_square( bigint bi )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
biR = bi_multiply( bi_copy( bi ), bi_copy( bi ) );
|
|
||||||
bi_free( bi );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_power( bigint bi, bigint biexp )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
if ( bi_is_negative( bi_copy( biexp ) ) )
|
|
||||||
{
|
|
||||||
(void) fprintf( stderr, "bi_power: negative exponent\n" );
|
|
||||||
(void) kill( getpid(), SIGFPE );
|
|
||||||
}
|
|
||||||
biR = bi_1;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ( bi_is_odd( bi_copy( biexp ) ) )
|
|
||||||
biR = bi_multiply( biR, bi_copy( bi ) );
|
|
||||||
biexp = bi_half( biexp );
|
|
||||||
if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 )
|
|
||||||
break;
|
|
||||||
bi = bi_multiply( bi_copy( bi ), bi );
|
|
||||||
}
|
|
||||||
bi_free( bi );
|
|
||||||
bi_free( biexp );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_factorial( bigint bi )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
biR = bi_1;
|
|
||||||
while ( bi_compare( bi_copy( bi ), bi_1 ) > 0 )
|
|
||||||
{
|
|
||||||
biR = bi_multiply( biR, bi_copy( bi ) );
|
|
||||||
bi = bi_int_subtract( bi, 1 );
|
|
||||||
}
|
|
||||||
bi_free( bi );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
bi_is_even( bigint bi )
|
|
||||||
{
|
|
||||||
return ! bi_is_odd( bi );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_mod_power( bigint bi, bigint biexp, bigint bim )
|
|
||||||
{
|
|
||||||
int invert;
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
invert = 0;
|
|
||||||
if ( bi_is_negative( bi_copy( biexp ) ) )
|
|
||||||
{
|
|
||||||
biexp = bi_negate( biexp );
|
|
||||||
invert = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
biR = bi_1;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ( bi_is_odd( bi_copy( biexp ) ) )
|
|
||||||
biR = bi_mod( bi_multiply( biR, bi_copy( bi ) ), bi_copy( bim ) );
|
|
||||||
biexp = bi_half( biexp );
|
|
||||||
if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 )
|
|
||||||
break;
|
|
||||||
bi = bi_mod( bi_multiply( bi_copy( bi ), bi ), bi_copy( bim ) );
|
|
||||||
}
|
|
||||||
bi_free( bi );
|
|
||||||
bi_free( biexp );
|
|
||||||
|
|
||||||
if ( invert )
|
|
||||||
biR = bi_mod_inverse( biR, bim );
|
|
||||||
else
|
|
||||||
bi_free( bim );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_mod_inverse( bigint bi, bigint bim )
|
|
||||||
{
|
|
||||||
bigint gcd, mul0, mul1;
|
|
||||||
|
|
||||||
gcd = bi_egcd( bi_copy( bim ), bi, &mul0, &mul1 );
|
|
||||||
|
|
||||||
/* Did we get gcd == 1? */
|
|
||||||
if ( ! bi_is_one( gcd ) )
|
|
||||||
{
|
|
||||||
(void) fprintf( stderr, "bi_mod_inverse: not relatively prime\n" );
|
|
||||||
(void) kill( getpid(), SIGFPE );
|
|
||||||
}
|
|
||||||
|
|
||||||
bi_free( mul0 );
|
|
||||||
return bi_mod( mul1, bim );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Euclid's algorithm. */
|
|
||||||
bigint
|
|
||||||
bi_gcd( bigint bim, bigint bin )
|
|
||||||
{
|
|
||||||
bigint bit;
|
|
||||||
|
|
||||||
bim = bi_abs( bim );
|
|
||||||
bin = bi_abs( bin );
|
|
||||||
while ( ! bi_is_zero( bi_copy( bin ) ) )
|
|
||||||
{
|
|
||||||
bit = bi_mod( bim, bi_copy( bin ) );
|
|
||||||
bim = bin;
|
|
||||||
bin = bit;
|
|
||||||
}
|
|
||||||
bi_free( bin );
|
|
||||||
return bim;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Extended Euclidean algorithm. */
|
|
||||||
bigint
|
|
||||||
bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul )
|
|
||||||
{
|
|
||||||
bigint a0, b0, c0, a1, b1, c1, q, t;
|
|
||||||
|
|
||||||
if ( bi_is_negative( bi_copy( bim ) ) )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
biR = bi_egcd( bi_negate( bim ), bin, &t, bin_mul );
|
|
||||||
*bim_mul = bi_negate( t );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
if ( bi_is_negative( bi_copy( bin ) ) )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
biR = bi_egcd( bim, bi_negate( bin ), bim_mul, &t );
|
|
||||||
*bin_mul = bi_negate( t );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
a0 = bi_1; b0 = bi_0; c0 = bim;
|
|
||||||
a1 = bi_0; b1 = bi_1; c1 = bin;
|
|
||||||
|
|
||||||
while ( ! bi_is_zero( bi_copy( c1 ) ) )
|
|
||||||
{
|
|
||||||
q = bi_divide( bi_copy( c0 ), bi_copy( c1 ) );
|
|
||||||
t = a0;
|
|
||||||
a0 = bi_copy( a1 );
|
|
||||||
a1 = bi_subtract( t, bi_multiply( bi_copy( q ), a1 ) );
|
|
||||||
t = b0;
|
|
||||||
b0 = bi_copy( b1 );
|
|
||||||
b1 = bi_subtract( t, bi_multiply( bi_copy( q ), b1 ) );
|
|
||||||
t = c0;
|
|
||||||
c0 = bi_copy( c1 );
|
|
||||||
c1 = bi_subtract( t, bi_multiply( bi_copy( q ), c1 ) );
|
|
||||||
bi_free( q );
|
|
||||||
}
|
|
||||||
|
|
||||||
bi_free( a1 );
|
|
||||||
bi_free( b1 );
|
|
||||||
bi_free( c1 );
|
|
||||||
*bim_mul = a0;
|
|
||||||
*bin_mul = b0;
|
|
||||||
return c0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_lcm( bigint bia, bigint bib )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
biR = bi_divide(
|
|
||||||
bi_multiply( bi_copy( bia ), bi_copy( bib ) ),
|
|
||||||
bi_gcd( bi_copy( bia ), bi_copy( bib ) ) );
|
|
||||||
bi_free( bia );
|
|
||||||
bi_free( bib );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The Jacobi symbol. */
|
|
||||||
bigint
|
|
||||||
bi_jacobi( bigint bia, bigint bib )
|
|
||||||
{
|
|
||||||
bigint biR;
|
|
||||||
|
|
||||||
if ( bi_is_even( bi_copy( bib ) ) )
|
|
||||||
{
|
|
||||||
(void) fprintf( stderr, "bi_jacobi: don't know how to compute Jacobi(n, even)\n" );
|
|
||||||
(void) kill( getpid(), SIGFPE );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bi_compare( bi_copy( bia ), bi_copy( bib ) ) >= 0 )
|
|
||||||
return bi_jacobi( bi_mod( bia, bi_copy( bib ) ), bib );
|
|
||||||
|
|
||||||
if ( bi_is_zero( bi_copy( bia ) ) || bi_is_one( bi_copy( bia ) ) )
|
|
||||||
{
|
|
||||||
bi_free( bib );
|
|
||||||
return bia;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bi_compare( bi_copy( bia ), bi_2 ) == 0 )
|
|
||||||
{
|
|
||||||
bi_free( bia );
|
|
||||||
switch ( bi_int_mod( bib, 8 ) )
|
|
||||||
{
|
|
||||||
case 1: case 7:
|
|
||||||
return bi_1;
|
|
||||||
case 3: case 5:
|
|
||||||
return bi_m1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bi_is_even( bi_copy( bia ) ) )
|
|
||||||
{
|
|
||||||
biR = bi_multiply(
|
|
||||||
bi_jacobi( bi_2, bi_copy( bib ) ),
|
|
||||||
bi_jacobi( bi_half( bia ), bi_copy( bib ) ) );
|
|
||||||
bi_free( bib );
|
|
||||||
return biR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bi_int_mod( bi_copy( bia ), 4 ) == 3 &&
|
|
||||||
bi_int_mod( bi_copy( bib ), 4 ) == 3 )
|
|
||||||
return bi_negate( bi_jacobi( bib, bia ) );
|
|
||||||
else
|
|
||||||
return bi_jacobi( bib, bia );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Probabalistic prime checking. */
|
|
||||||
int
|
|
||||||
bi_is_probable_prime( bigint bi, int certainty )
|
|
||||||
{
|
|
||||||
int i, p;
|
|
||||||
bigint bim1;
|
|
||||||
|
|
||||||
/* First do trial division by a list of small primes. This eliminates
|
|
||||||
** many candidates.
|
|
||||||
*/
|
|
||||||
for ( i = 0; i < sizeof(low_primes)/sizeof(*low_primes); ++i )
|
|
||||||
{
|
|
||||||
p = low_primes[i];
|
|
||||||
switch ( bi_compare( int_to_bi( p ), bi_copy( bi ) ) )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
bi_free( bi );
|
|
||||||
return 1;
|
|
||||||
case 1:
|
|
||||||
bi_free( bi );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ( bi_int_mod( bi_copy( bi ), p ) == 0 )
|
|
||||||
{
|
|
||||||
bi_free( bi );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now do the probabilistic tests. */
|
|
||||||
bim1 = bi_int_subtract( bi_copy( bi ), 1 );
|
|
||||||
for ( i = 0; i < certainty; ++i )
|
|
||||||
{
|
|
||||||
bigint a, j, jac;
|
|
||||||
|
|
||||||
/* Pick random test number. */
|
|
||||||
a = bi_random( bi_copy( bi ) );
|
|
||||||
|
|
||||||
/* Decide whether to run the Fermat test or the Solovay-Strassen
|
|
||||||
** test. The Fermat test is fast but lets some composite numbers
|
|
||||||
** through. Solovay-Strassen runs slower but is more certain.
|
|
||||||
** So the compromise here is we run the Fermat test a couple of
|
|
||||||
** times to quickly reject most composite numbers, and then do
|
|
||||||
** the rest of the iterations with Solovay-Strassen so nothing
|
|
||||||
** slips through.
|
|
||||||
*/
|
|
||||||
if ( i < 2 && certainty >= 5 )
|
|
||||||
{
|
|
||||||
/* Fermat test. Note that this is not state of the art. There's a
|
|
||||||
** class of numbers called Carmichael numbers which are composite
|
|
||||||
** but look prime to this test - it lets them slip through no
|
|
||||||
** matter how many reps you run. However, it's nice and fast so
|
|
||||||
** we run it anyway to help quickly reject most of the composites.
|
|
||||||
*/
|
|
||||||
if ( ! bi_is_one( bi_mod_power( bi_copy( a ), bi_copy( bim1 ), bi_copy( bi ) ) ) )
|
|
||||||
{
|
|
||||||
bi_free( bi );
|
|
||||||
bi_free( bim1 );
|
|
||||||
bi_free( a );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* GCD test. This rarely hits, but we need it for Solovay-Strassen. */
|
|
||||||
if ( ! bi_is_one( bi_gcd( bi_copy( bi ), bi_copy( a ) ) ) )
|
|
||||||
{
|
|
||||||
bi_free( bi );
|
|
||||||
bi_free( bim1 );
|
|
||||||
bi_free( a );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solovay-Strassen test. First compute pseudo Jacobi. */
|
|
||||||
j = bi_mod_power(
|
|
||||||
bi_copy( a ), bi_half( bi_copy( bim1 ) ), bi_copy( bi ) );
|
|
||||||
if ( bi_compare( bi_copy( j ), bi_copy( bim1 ) ) == 0 )
|
|
||||||
{
|
|
||||||
bi_free( j );
|
|
||||||
j = bi_m1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now compute real Jacobi. */
|
|
||||||
jac = bi_jacobi( bi_copy( a ), bi_copy( bi ) );
|
|
||||||
|
|
||||||
/* If they're not equal, the number is definitely composite. */
|
|
||||||
if ( bi_compare( j, jac ) != 0 )
|
|
||||||
{
|
|
||||||
bi_free( bi );
|
|
||||||
bi_free( bim1 );
|
|
||||||
bi_free( a );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bi_free( a );
|
|
||||||
}
|
|
||||||
|
|
||||||
bi_free( bim1 );
|
|
||||||
|
|
||||||
bi_free( bi );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bigint
|
|
||||||
bi_generate_prime( int bits, int certainty )
|
|
||||||
{
|
|
||||||
bigint bimo2, bip;
|
|
||||||
int i, inc = 0;
|
|
||||||
|
|
||||||
bimo2 = bi_power( bi_2, int_to_bi( bits - 1 ) );
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
bip = bi_add( bi_random( bi_copy( bimo2 ) ), bi_copy( bimo2 ) );
|
|
||||||
/* By shoving the candidate numbers up to the next highest multiple
|
|
||||||
** of six plus or minus one, we pre-eliminate all multiples of
|
|
||||||
** two and/or three.
|
|
||||||
*/
|
|
||||||
switch ( bi_int_mod( bi_copy( bip ), 6 ) )
|
|
||||||
{
|
|
||||||
case 0: inc = 4; bip = bi_int_add( bip, 1 ); break;
|
|
||||||
case 1: inc = 4; break;
|
|
||||||
case 2: inc = 2; bip = bi_int_add( bip, 3 ); break;
|
|
||||||
case 3: inc = 2; bip = bi_int_add( bip, 2 ); break;
|
|
||||||
case 4: inc = 2; bip = bi_int_add( bip, 1 ); break;
|
|
||||||
case 5: inc = 2; break;
|
|
||||||
}
|
|
||||||
/* Starting from the generated random number, check a bunch of
|
|
||||||
** numbers in sequence. This is just to avoid calls to bi_random(),
|
|
||||||
** which is more expensive than a simple add.
|
|
||||||
*/
|
|
||||||
for ( i = 0; i < 1000; ++i ) /* arbitrary */
|
|
||||||
{
|
|
||||||
if ( bi_is_probable_prime( bi_copy( bip ), certainty ) )
|
|
||||||
{
|
|
||||||
bi_free( bimo2 );
|
|
||||||
return bip;
|
|
||||||
}
|
|
||||||
bip = bi_int_add( bip, inc );
|
|
||||||
inc = 6 - inc;
|
|
||||||
}
|
|
||||||
/* We ran through the whole sequence and didn't find a prime.
|
|
||||||
** Shrug, just try a different random starting point.
|
|
||||||
*/
|
|
||||||
bi_free( bip );
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue