bigint multiprecision integer arithmetic
bigint is a class that provides a multiprecision integer arithmetic. A variable of type bigint can hold an integer with arbitrarily many digits. Since all operators which are available for machine integer (e.g. int) are also defined for the type bigint you can regard a variable of type bigint as an int-variable without length restriction.
bigint
is an interface that calls functions provided
by the kernel. Thus the representation of variables depends
on data types used in that level.
There is a fixed base B>0, which we call
bigint base
and which determines the
representation of each integer n by the array
, with
,
for
and
The coefficients are called base digits
, l is
called the length
of the representation and the mantissa
is the
array .
We assume that the kernel supports such a vector-based
representation for long integers, i.e., it defines such a base
B, the functions sign
for the calculation of the sign of a long integer, length for the length of a long integer, and pointers to the mantissas of represented integers.
Constructors/Destructor
bigint()
bigint(int)
bigint(long)
bigint(unsigned long)
bigint(double)
bigint(const bigint &)
bigint()
Type Checking
Before assigning a bigint variable to a machine type variable (e.g. int) it is often useful to perform a test which checks whether the assignment can be done without overflow. The following functions return 1 if an assignment is possible, 0 otherwise.
int is_char(const bigint &)
int is_uchar(const bigint &)
int is_short(const bigint &)
int is_ushort(const bigint &)
int is_int(const bigint &)
int is_uint(const bigint &)
int is_long(const bigint &)
int is_ulong(const bigint &)
Assignments
Let a be of type bigint .
The operator = is overloaded. For efficiency reasons, the following functions are also implemented:
void a.assign_zero()
a = 0.
void a.assign_one()
a = 1.
void a.assign(int i)
a = i.
void a.assign(long ui)
a = ui.
void a.assign(unsigned long ui)
a = ui.
void a.assign(const bigint & I)
a = I.
int a.intify(int & i)
checks whether a can be converted into an int
.
If this can successfully be done, the function will
assign i = a and return 0
;
otherwise, the return value will be 1
and i
will be left unchanged.
int a.longify(long & i)
checks whether a can be converted into a long
.
If this can successfully be done, the function will
assign i = a and return 0
;
otherwise, the return value will be 1
and i
will be left unchanged.
double dbl(const bigint & a)
returns . If a is too large to be stored
in a double variable, x will be the special value
infinity which is used in C++ to denote a value
too large to be stored in a double variable.
Arithmetical Operations
The following operators are overloaded and can be used in exactly the same way as for machine types in C (e.g. int) :
(unary) -, ++, --
(binary) +, -, *, /, %, <<, >>, , &, |, ^
(binary with assignment) +=, -=, *=, /=, %=, <<=, >>=,
&=, |=
Let a be of type bigint .
To avoid copying, these operations can also be performed by the following functions:
void add(bigint & c, const bigint & a, const bigint & b)
c = a + b.
void add(bigint & c, const bigint & a, long i)
c = a + i.
void add(bigint &c, long i, const bigint & a)
c = i + a.
void subtract(bigint & c, const bigint & a, const bigint & b)
c = a - b.
void subtract(bigint & c, const bigint & a, long i)
c = a - i.
void subtract(bigint & c, long i, const bigint & a)
c = i - a.
void multiply(bigint & c, const bigint & a, const bigint & b)
.
void multiply(bigint & c, const bigint & a, long i)
.
void multiply(bigint & c, long i, const bigint & a)
.
void divide(bigint & c, const bigint & a, const bigint & b)
, if
. Otherwise the
error_handler will be invoked.
void divide(bigint & c, const bigint & a, long i)
, if
.
Otherwise the error_handler will be invoked.
void divide(bigint & c, long i, const bigint & a)
, if
. Otherwise the
error_handler will be invoked.
void remainder(bigint & c, const bigint & a, const bigint & b)
computes c, with ,
|c| < |b| and
.
void remainder(long & c, const bigint & a, long i)
computes c, with ,
|c| < |i| and
.
long remainder(const bigint & a, long i)
returns a value c, with ,
|c| < |i| and
.
long remainder(long & i, const bigint & a)
returns a value c, with ,
|c| < |a| and
.
void div_rem(bigint & q, bigint & r, const bigint & a, const bigint & b)
computes q and r such that
, |r| < |b| and
.
void div_rem(bigint & q, long & r, const bigint & a, long i)
computes q and r such that
, |r| < |i| and
.
a.multiply_by_2()
.
a.divide_by_2()
.
void a.negate()
a = -a.
void negate(bigint & b, const bigint & a)
b = -a.
void inc(bigint & c)
c = c + 1.
void dec(bigint & c)
c = c - 1.
void square(bigint & a, const bigint & b)
.
void sqrt(bigint & a, const bigint & b)
a is set to the positive value of
, if
. Otherwise
the error_handler will be invoked.
void power(bigint & c, const bigint & a, const bigint & b)
. For negative exponents b, the
result of this computation will be 0, if a > 1,
respectively, if
and 0, if a=0.
void power(bigint & c, const bigint & a, long i)
. For negative exponents i, the
result of this computation will be 0, if a > 1,
respectively, if
and 0, if a=0.
Shift Operations
void shift_left(bigint & c, const bigint & a, long i)
c = a << i, if . Otherwise the error_handler
will be invoked.
void shift_right(bigint & c, const bigint & a, long i)
c = a >> i, if . Otherwise the error_handler
will be invoked.
Bit Operations
void and(bigint & c, const bigint & a, const bigint & b)
.
void or(bigint & c, const bigint & a, const bigint & b)
.
void xor(bigint & c, const bigint & a, const bigint & b)
.
void not(bigint & c, const bigint & a)
.
Comparisons
The binary operators == , != , >= , <= , > , < and the unary operator ! (comparison with zero) are overloaded and can be used in exactly the same way as for machine types in C (e.g. int). Let a be an instance of type bigint .
int a.is_zero() const
returns 1
if a = 0, 0
otherwise.
int a.is_one() const
returns 1
if a = 1, 0
otherwise.
int a.is_gt_zero() const
returns 1
if a > 0, 0
otherwise.
int a.is_ge_zero() const
returns 1
if , 0
otherwise.
int a.is_lt_zero() const
returns 1
if a < 0, 0
otherwise.
int a.is_le_zero() const
returns 1
if , 0
otherwise.
int a.is_positive() const
returns 1
if a > 0, 0
otherwise.
int a.is_negative() const
returns 1
if a < 0, 0
otherwise.
int a.is_even() const
returns 1
if , 0
otherwise.
int a.is_odd() const
returns 1
if , 0
otherwise.
int a.abs_compare(const bigint & b) const
returns .
int a.compare(const bigint & b) const
returns .
Basic Functions
Let a be of type bigint .
int a.length() const
returns the number of base digits of the mantissa of a.
int a.bit_length() const
returns the number of bits of the mantissa of a.
int a.bit(unsigned int i) const
returns the i-th bit of a. Bits are numbered from
0 to a.bit_length()-1, where the least
significant bit of a has index 0. If
a.bit_length(), the function always returns 0.
int a.sign() const
returns -1, 0, 1 if a <, =, > 0, respectively.
unsigned long a.least_significant_digit() const
returns the least significant digit of a, i.e. if
the mantissa of a is , the
function returns
(see basic description).
unsigned long a.most_significant_digit() const
returns the most significant digit of a, i.e. if
the mantissa of a is , the
function returns
(see basic description).
void a.absolute_value()
a = |a|.
bigint abs(const bigint & a)
returns |a|.
void seed(const bigint & a)
initializes the random number generator
defined in the kernel with a.
bigint randomize(const bigint & a)
returns a random value r by means of the random
number generator defined in the kernel
if a>0
and
if a<0.
void swap(bigint & a, bigint & b)
exchanges the values of a and b.
High-Level Functions
int fermat(const bigint & a)
performs a probabilistic primality test on a
using Fermat's theorem (see [11]).
The return value will be 0, if the function
recognizes a as composite; otherwise,
it will be 1.
For any input this function will return 0.
int integer_log(unsigned long x)
returns the position of the most significant bit in an
unsigned long. For non-zero x, the return value of this function will
be 1 at least; it corresponds to the value
.
int is_prime(const bigint & a, int n)
performs a probabilistic primality test on a
using the Miller-Rabin method (see [11, page 415,]).
If a >1 then the return value 0 implies that a is composite.
If a>1 and is_prime
returns 1 then a is a prime number
with probability .
For any input the return value
of is_prime
is 0.
int jacobi(const bigint & a, const bigint & b)
returns the value of the Jacobi
symbol , hence the Legendre symbol
when b is an odd prime (see [11, page 28,]).
The Legendre symbol is defined to be 1 if a is a quadratic residue mod b,
-1 if a is a quadratic non-residue mod b and 0 if
a is a multiple of b.
void nearest(bigint & z, const bigint & u, const bigint & v)
computes an integer z with minimal
distance , if
. If there are
two possible values, the one with the absolutely greater
value will be chosen.
If v=0 the error_handler will be invoked.
bigint next_prime(const bigint & a)
returns the least integer number > a that satisfies the
primality test in function is_prime
.
For any input this function will
return 2.
bigint previous_prime(const bigint & a)
returns the greatest integer number < a that satisfies the
primality test in function is_prime
.
For any input this function will
return 0.
void power_mod(bigint & res, const bigint & a, const bigint & n, const bigint & m, int err =0)
calculates in res the least non-negative residue of
(
,
) using the right-to-left binary exponentiation
method (see [11, page 8,]).
For negative exponents n, this function tries to compute
the multiplicative inverse of .
If it does not exist and err=0,
then the error_handler
will be invoked.
If the multiplicative inverse does not exist and
, the gcd of
and m will be assigned to res and the function
terminates.
long power_test(bigint & b, const bigint & a)
tests, whether a is a perfect power. If a is a
k-th power then b is set to k-th root
(i.e. ) and k is returned; otherwise the
function returns -1.
Greatest Common Divisor
bigint gcd(const bigint & a, const bigint & b)
returns the greatest common divisor (gcd) of a
and b as a positive bigint.
bigint bgcd(const bigint & a, const bigint & b)
calculates the gcd of a and b as a positive
bigint using a binary method.
bigint dgcd(const bigint & a, const bigint & b)
calculates the gcd of a and b as a positive
bigint
using Euclidian division and returns its value.
bigint xgcd(bigint & u, bigint & v, const bigint & a, const bigint & b)
returns the gcd of a and b as a positive bigint
and computes coefficients u and v with
and
such that
, i.e., uses an extended gcd algorithm.
bigint xgcd_left(bigint & u, const bigint & a, const bigint & b)
returns the gcd of a and b as a positive bigint
and computes a coefficient u such that for some
integer t .
bigint xgcd_right(bigint & v, const bigint & a, const bigint & b)
returns the gcd of a and b as a positive bigint
and computes a coefficient v such that for some
integer t .
bigint lcm(const bigint & a, const bigint & b)
returns the least common multiple (lcm) of a
and b as a positive bigint.
Input/Output
Let a be of type bigint .
The istream operator >> and the ostream operator << are overloaded. Furthermore, you can use the following member functions for writing to and reading from a file in binary or ASCII format, respectively. The input and output format of a bigint
consist only of the number itself without blanks. Note that you have to manage by yourself that successive bigint s have to be separated by blanks.
void a.read_from_file(FILE * fp)
reads a from the binary file using fread.
void a.write_to_file(FILE * fp)
writes a to binary file using fwrite.
void a.scan_from_file(FILE * fp)
scans a from the ASCII file using fscanf.
We assume that the file contains the number in decimal
representation.
void a.print_to_file(FILE * fp)
prints a in decimal representation to the ASCII file using fprintf.
The following functions allow conversion between bigint
values and strings:
int string_to_bigint( const char *s, bigint & a)
converts the string s into the bigint a and returns
the number of used characters.
int bigint_to_string( const bigint & a, char *s)
converts the bigint a into the string s and returns the number of
used characters. The number of characters allocated
for string s must be at least
.
UNIX manual page mp(3x)
The member functions scan_from_file() , print_to_file() , read_from_file() and write_to_file()
are included because there are still C++ compilers which do not handle fstream s correctly. In a future release, those functions will disappear.
#include <LiDIA/bigint.h> main() { bigint a, b, c; cout << "Please enter a : "; cin >> a ; cout << "Please enter b : "; cin >> b ; cout << "\n"; c = a + b; cout << "a + b = " << c << "\n"; }example:
Please enter a : 123456789123456789
Please enter b : 234567892345678911
a + b = 358024681469135700
For further examples please refer to
LiDIA/src/interfaces/INTERFACE/bigint_appl.c
.
Thomas Papanikolaou
Copyright 1995 by the
LiDIA -Group, Universität des Saarlandes