#include <linteger/bmath.hxx>
LInteger
s as black boxes,
however, will have no need to know about the methods presented
here, and can safely skip this section.
(It is assumed that most people will want to treat
LInteger
s as black boxes when initially encountering
the LInteger library.)
unsigned int
s. Each unsigned int
s
in the array is to
represent a digit of the magnitude in a base
equal to
2**(sizeof(unsigned int)*8)
. The digits
within a given magnitude are to be stored in consecutive memory locations
such that a digit at a lower memory address has greater significance
than any digit at a higher memory address. For example, consider
the 64-bit magnitude 0xfedcba9876543210. On a 32-bit machine this
is to be stored in memory as:
starting memory address: | 0xfedcba98 |
---|---|
starting memory address+4: | 0x76543210 |
Note that the 4 above is a byte displacement. If A
is an unsigned int*
pointing to the magnitude on
this hypothetical 32-bit machine,
then A[0]=0xfedcba98, while A[1]=0x76543210.
unsigned int* mem=start; while (1) { (*mem)++; if (increment did not cause a carry) break; mem--; }
unsigned int* mem=start; while (1) { (*mem)--; if (decrement did not cause a borrow) break; mem--; }
static const unsigned int BMath::SmallPrime[];This is an array of the first few primes. Check the public constant BMath::SmallPrimesAvailable to see how many small primes this array contains.
static const int BMath::SmallPrimesAvailable;This constant tells how many small primes are available in the BMath::SmallPrime[] array.
static inline void BMath::SetBit(const int bitNum, unsigned int* x, const int digits);Sets the (bitNum+1)th least significant bit in the magnitude pointed to by x to 1. digits indicates how many digits are in the magnitude.
static inline void BMath::TestBit(const int bitNum, const unsigned int* x, const int digits);Returns a non-zero value if the (bitNum+1)th least significant bit in the magnitude pointed to by x is equal to 1 and returns 0 otherwise. digits indicates how many digits are in the magnitude.
static inline int BMath::BSR(const unsigned int x);Returns the bit position (0 to LMisc::bitsPerUInt-1 with 0 being least significant) of the most significant bit which is 1 in x.
static inline int BMath::BSF(const unsigned int x);Returns the bit position (0 to LMisc::bitsPerUInt-1 with 0 being least significant) of the least significant bit which is 1 in x.
static int BMath::BSR(const unsigned int* x, const int digits);Returns the bit position (with 0 being least significant) of the most significant bit which is 1 in the magnitude pointed to by x. digits indicates how many digits are in the magnitude.
static int BMath::BSF(const unsigned int* x, const int digits);Returns the bit position (with 0 being least significant) of the least significant bit which is 1 in the magnitude pointed to by x. digits indicates how many digits are in the magnitude.
static inline char BMath::GreaterThanOrEqualTo(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is greater than or equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::GreaterThan(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is greater than the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::LessThanOrEqualTo(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is less than or equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::LessThan(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is less than the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::EqualTo(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::NotEqualTo(const unsigned int* x, const unsigned int* y, int digits);Compares two magnitudes, returning 1 if the magnitude pointed to by x is not equal to the magnitude pointed to by y and 0 otherwise. Both magnitudes must have an equal number of digits and this number is to be passed as digits.
static inline char BMath::BasicAdd(const unsigned int* x, const unsigned int* y, unsigned int* z, int digits);Adds the magnitude pointed to by x to the mangitude pointed to by y, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the addition results in a carry, 1 is returned, otherwise 0 is returned.
x and y must have the same number of digits, and this number is to be passed as digits.
static inline void BMath::RippleAdd(const unsigned int* x, const unsigned int* y, unsigned int* z, int digits);Adds the magnitude pointed to by x to the mangitude pointed to by y, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the addition results in a carry, it is rippled out via the ripple carry algorithm with a starting point equal to z-1.
x and y must have the same number of digits, and this number is to be passed as digits.
static char BMath::Add(const unsigned int* x, const int digitsX, const unsigned int* y, const int digitsY, unsigned int* z);Adds the digitsY digit mangitude pointed to by y to the digitsX digit mangitude pointed to by x. The magnitude pointed to by x must have at least as many digits as the magnitude pointed by y for this to work. The digitsX least significant digits of the sum are stored into memory starting at the location pointed to by z. If the sum is a digitsX+1 digit number, 1 is returned, otherwise 0 is returned.
static inline char BMath::BasicSubtract(const unsigned int* x, const unsigned int* y, unsigned int* z, int digits);Subtracts the magnitude pointed to by y from the mangitude pointed to by x, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the subtraction requires a borrow, 1 is returned, otherwise 0 is returned.
x and y must have the same number of digits, and this number is to be passed as digits.
static inline void BMath::RippleSubtract(const unsigned int* x, const unsigned int* y, unsigned int* z, int digits);Subtracts the magnitude pointed to by y from the mangitude pointed to by x, storing the digits least significant digits of the result into memory starting at the location pointed to by z. If the subtraction requires a borrow, it is rippled out via the ripple borrow algorithm with a starting point equal to z-1.
x and y must have the same number of digits, and this number is to be passed as digits.
static void BMath::Subtract(const unsigned int* x, const int digitsX, const unsigned int* y, const int digitsY, unsigned int* z);Subtracts the digitsY digit magnitude pointed to by y from the digitsX digit mangitude pointed to by x, storing the digitsX least significant digits of the result into memory starting at the location pointed to by z. The magnitude poitned to by x must be greater than or equal to the magnitude pointed to by y and must have at least as many digits if this method is to work.
static inline void BMath::RippleIncrement(unsigned int* x, int digits);Increments the magnitude pointed to by x by 1. If this increment results in a carry, it is rippled out via the ripple carry algorithm with a starting point equal to x-1. digits indicates the number of digits (before incrementing) in the magnitude pointed to by x.
static char BMath::Increment(unsigned int* x, int digits);Increments the digits digit magnitude pointed to by x by 1. If this increment result in a carry, 1 is returned, otherwise 0 is returned.
static inline void BMath::RippleDecrement(unsigned int* x, int digits);Decrements the digits digit magnitude pointed to by x by 1. If this decrement results in a borrow, it is rippled out via the ripple borrow algorithm with a starting point equal to x-1. digits indicates the number of digits (before decrementing) in the magnitude pointed to by x.
static inline void BMath::BasicMultiply(const unsigned int* x, const unsigned int y, unsigned int* z, int digitsX);Multiplies the digitsX digit magnitude pointed to by x by y and adds the digitsX+1 digit result to the digitsX+1 digit magnitude pointed to by z. If this addition results in a carry it is rippled out via the ripple carry algorithm with a starting point equal to z-1.
static inline void BMath::MultDouble(const unsigned int* x, const unsigned int* y, unsigned int* z);Multplies the two digit magnitude pointed to by x by the two digit magnitude pointed to by y, storing the four digit result into memory starting at the location pointed to by z.
static void BMath::Multiply(const unsigned int* x, int digitsX, const unsigned int* y, int digitsY, unsigned int* z);Multiplies the digitsX digit magnitude pointed to by x by the digitsY digit magnitude pointed to by y, storing the digitsX+digitsY digit result into memory starting at the location pointed to by z. The memory locations from z to z+digitsX+digitsY-1 inclusive must be zero before this method is called if it is to work.
static inline void BMath::SquareDouble(const unsigned int* x, unsigned int* y);Squares the two digit magnitude pointed to by x, storing the four digit result into memory starting at the location pointed to by y. This is method is equivalent to
MultDouble(x,x,y)
except that it is faster.
static void BMath::Square(const unsigned int* x, const int digitsX, unsigned int* y);
Squares the digitsX digit magnitude pointed to by
x, storing the 2*digitsX result
into memory starting at the location pointed to by y.
The memory locations from
y to y+2*digitsX-1 inclusive must be
zero
before this method is called if it is to work. This method is equivalent to
Multiply(x,digitsX,x,digitsX,y)
except that it is
faster.
static inline void BMath::BasicDivide(unsigned int dividendHigh, unsigned int dividendLow, unsigned int divisor, unsigned int& quotient, unsigned int& remainder);Divides the two digit dividend given by dividendHigh*base+dividendLow by divisor, storing the quotient in quotient and the remainder in remainder.
Warning:
Be sure that the quotient can fit into an
unsigned int
before calling this method, or you will get a
floating exception!
static void BMath::Divide(const unsigned int* dividend, const int dividendSize, const unsigned int* divisor, const int divisorSize, unsigned int*& quotient, unsigned int*& remainder);Divides the dividendSize digit dividend pointed to by dividend by the divisorSize digit divisor pointed to by divisor. Upon return, quotient will point to a dynamically allocated memory block containing the dividendSize-divisorSize+1 digit magnitude of the quotient, while remainder will point to a dynamically allocated memory block of dividendSize+1 digits containing the remainder.
The caller is assumed to own the memory pointed to by quotient and remainder after this method is called, and is, therefore, responsible for deleting it.
Note: dividendSize must be greater than or equal to divisorSize, and the magnitude pointed to by divisor may not have lead zeros, if this method is to work.
static inline unsigned int BMath::ModSmall(const unsigned int* dividend, int digits, const unsigned int divisor);Returns the remainder when the digits digit magnitude pointed to by dividend is divided by divisor.
static inline void BMath::ShortShiftRight(unsigned int* x, int digits, const char distance);Shifts the bits of the digits digit magnitude pointed to by x to the right by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the left, while bits shifted out on the right are lost.
static inline void BMath::ShortShiftLeft(unsigned int* x, int digits, const char distance);Shifts the bits of the digits digit magnitude pointed to by x to the left by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the right, while bits shifted out on the left are lost.
static void BMath::ShiftRight(unsigned int*& x, int& digits, const int distance);Shifts the bits of the digits digit magnitude pointed to by x to the right by the number of positions given by distance. Zeros are shifted in on the left, while bits shifted out on the right are lost. If the shift results in a magnitude with lead zeros, the magnitude is copied without its lead zeros, deleted, and x is modified to point to the copy. Upon return, digits will contain the number of digits in the magnitude that x points to.
static void BMath::ShiftLeft(unsigned int*& x, int& digits, const int distance);Shifts the bits of the digits digit magnitude pointed to by x to the left by the number of positions given by distance. Zeros are shifted in on the right, and no bits are lost. If the shift results in a magnitude with more digits than the magnitude before shifting, the magnitude is copied, deleted, and x is modified to point to the copy. Upon return, digits will contain the number of digits in the magnitude that x points to.
static inline void BMath::Div2(unsigned int* x, int digits);Shifts the bits of the digits digit magnitude pointed to by x to the right once place. A zero is shifted into the most significant bit of the magnitude, while the least significant bit is lost. This method is equivalent to
BMath::ShiftRight(x,digits,1)
except that it is faster.