Next Previous Table of Contents

The LInteger Class

#include <linteger/linteger.hxx>

Overview

The LInteger class provides support for the construction, destruction, and copying of objects representing signed multiple precision integers. Included amongst the constructors are constructors for pseudo-random multiple precision integers. Many operators have been overloaded with the hope that basic arithmetic and I/O involving LInteger objects will be as easy the corresponding operations on regular ints.

The Internal Representation of LIntegers

An LInteger is represented internally as a triple, as summarized in the table below.

member type description
_magnitude unsigned int* points to a string of digits representing the magnitude
_sign unsigned char represents the sign
_digits int the number of digits in the array representing the magnitude

_magnitude

unsigned int* _magnitude;
Magnitudes are represented by arrays of unsigned ints. Each unsigned int in the array represents a digit of the magnitude in a base equal to 2**(sizeof(unsigned int)*8). The digits within a given magnitude are 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 will be stored in memory as:

starting memory address: 0xfedcba98
starting memory address+4: 0x76543210

Note that the 4 being added to the start address in the table above is a byte displacement.

Warning: It is important that LInteger magnitudes be stored with no leading zeros. This requirement is necessary for the internal consistency of the library. The LInteger class provides two methods to aid with this requirement:

  1. inline int LInteger::IsCompressable() const will return zero if the integer has no lead zeros, and non-zero otherwise.
  2. void LInteger::compress() will strip the leading zeros, if any, off the magnitude and adjust the _digits member accordingly.

_sign

unsigned char _sign;

This member represents the sign of the LInteger. It is 0 iff the LInteger represents an integer greater than or equal to zero. If the LInteger represents a negative integer, _sign is 1.

Warning: It is imporant, for the internal consistency of the library, that an LInteger representing zero have sign 0 and not sign 1.

_digits

int _digits;
This member tells how many digits are in the magnitude. (See
_magnitude for more details.)

Public Constants

One

static const LInteger LInteger::One;
This is an instance representing the integer 1.

Zero

static const LInteger LInteger::Zero;
This is an instance representing the integer 0.

Public Methods

Default Constructor

LInteger::LInteger();
This constructor creates an instance with NULL magnitude. (NULL magnitude is not equivalent to zero magnitude.) Be sure to assign a value to the instance before using it.

Constructor from Magnitude and Sign

LInteger::LInteger(unsigned int* magnitude, const int digits, 
                   const unsigned char sign=0, const int copyMag=1);
This constructor creates an instance representing the integer specified by the first three arguments. (See the Internal Representation of LIntegers section for details on the required format.) If copyMag is non-zero, the new instance will make its own copy of the magnitude, so that the caller may retain ownership of the memory pointed to by magnitude. If copyMag is zero, the library will assume control of the memory pointed to by magnitude, and will delete it upon destruction of the newly created instance.

Warning: Be sure that the magnitude of any instance created with this constructor does not have lead zeros. This is necessary for the internal consistency of the library. If you do not feel like checking if the magnitude you use has lead zeros or not, call compress() immediately after creating the new instance. Also be sure that if the new instance has magnitude 0, its sign is equal to 0.

Pseudo-Random Constructor from Number of Bits

LInteger::LInteger(const int maxBits, PRNG& prng, const int fewerBits=0, 
                   const int requireOdd=0);
This constructor creates a non-negative pseudo-random integer with a number of bits equal to maxBits if fewerBits is 0 and a number of bits less than or equal to maxBits if fewerBits is non-zero. If requireOdd is non-zero the least significant bit of the newly created instance is guaranteed to be 1. prng specifies what pseudo-random number generator is to be used to generate the random bits of the magnitude.

Assuming that the pseudo-random number generator is unbiased, the distribution of returned values should be flat. That is to say, if fewerBits is 1 each integer in the interval [0,2**maxBits-1] should be equally likely, while if fewBits is 0, each integer in the interval [2**(maxBits-1),2**(maxBits)-1] should be equally likely.

Pseudo-Random Constructor from a Range

LInteger::LInteger(PRNG& prng, const LInteger& x, const LInteger& y);
This constructor creates a pseudo-random integer in the interval [x,y]. prng specifies what pseudo-random number generator is to be used to generate the random bits of the magnitude of the new instance. Assuming that the pseudo-random number generator is unbiased, the distribution of returned values should be flat. That is to say, each integer in the interval [x,y] should be equally likely.

Constructor from a Character String

LInteger::LInteger(const char* magString, int base=10); 
This constructor creates an instance representing the integer whose base base digits are specified in magString. Bases 2 to 36 are allowed. For bases higher than 10, 'a' through 'z' represent the digits 10 through 35, as do 'A' through 'Z'. The magnitude may be prefixed by a sign equal to '+' or '-'. If a sign is not explicitly specified the new instance is assumed to represent a non-negative integer. Additionally, the magnitude may be prefixed by "0x" to indicate hexadecimal digits or "0" to indicate octal digits. Specifying the base in magString in one of these two manners overrides the value specified by base. Therefore,
LInteger a("0x100000000");
creates an instance, a, representing the integer 2**32. Here are some further examples:
LInteger x("0xa0");   // x will represent the (base ten) integer 160
LInteger y("-070");   // y will represent the (base ten) integer -56
LInteger z("-345");   // z will represent the (base ten) integer -345 

Constructor from a Byte String

LInteger::LInteger(const u8* magnitude, const int magBytes, 
                   const unsigned char sign=0);
This constructor creates an instance with sign equal to sign (0 for non-negative, 1 for negative) and magnitude equal to the binary number specified by the concatenation of the bytes of the high endian byte string, of length magBytes bytes, pointed to by magnitude.

Warning: Be sure that the magnitude of any new instance created with this constructor does not have lead zeroes. A new instance will have lead zeros iff the first sizeof(unsigned int) bytes pointed to by magnitude are zero. This requirement is necessary for the internal consistency of the library. If you do not feel like checking if the magnitude you use has lead zeroes or not, call compress() immediately after the creation of the new instance. Also be sure that if the new instance has magnitude 0, its sign is equal to 0.

Copy Constructor

LInteger::LInteger(const LInteger& x);
This constructor creates an instance which represents the same integer that x does.

Consturctor from unsigned ints

LInteger::LInteger(const unsigned int x, const int sign=0);
This constructor creates an instance representing an integer whose magnitude is equal to the magnitude of the integer that x represents, and whose sign is equal to sign. sign must be 0 for non-negative integers, and 1 for negative integers.

Constructor from ints

LInteger::LInteger(const int x);

This constructor creates an instance representing the same integer that x represents.

StringToLInteger

static int LInteger::StringToLInteger(const char* magString, LInteger& x, 
                                      int base=10);
This method sets x equal to the integer represented by the string magString. If magString does not specify an integer according to the parsing rules, x is left unchanged, and -1 is returned. Otherwise 0 is returned. The parsing rules for magString are identical to those for the Constructor from a Character String.

Assignment from a char*

LInteger& LInteger::operator=(const char* magString);
This assignment will make the calling instance represent the same integer the string magString represents. The parsing rules for magString are identical to those for the Constructor from a Character String. If there is a parsing error, an assertion will cause the program to terminate.

Assignment from an LInteger

LInteger& LInteger::operator=(const LInteger& x);
This assignment makes the calling instance represent an integer equal to the integer represented by x and returns a reference to the modified calling instance.

Assignment from an unsigned int

LInteger& LInteger::operator=(const unsigned int x);
This assignment makes the calling instance represent an integer equal to the integer represented by x and returns a reference to the modified calling instance.

Assignment from an int

LInteger& LInteger::operator=(const int x);
This assignment makes the calling instance represent an integer equal to the integer represented by x and returns a reference to the modified calling instance.

Destructor

LInteger::~LInteger();
The destructor frees the memory dynamically allocated to store the magnitude.

TwoToThe

static LInteger LInteger::TwoToThe(const int x);
This method returns an instance representing 2**x.

sign

inline unsigned char LInteger::sign() const; 
This method returns 0 if the calling instance represents a non-negative integer, and 1 otherwise.

digits

inline int LInteger::digits() const;
This method returns the number of radix 2**(sizeof(unsigned int)*8) digits in the magnitude of the integer the calling instance represents.

magnitude

inline unsigned int* LInteger::magnitude() const; 
This method returns a pointer to an array of radix 2**(sizeof(unsigned int)*8) digits representing the calling instance's magnitude.

Warning: This is the calling instance's private data, not a copy, so be sure you know what you are doing before you modify it!

SetSign

inline void LInteger::SetSign(const unsigned char newSign); 
This method sets the _sign member of the calling instance equal to the value specified by newSign.

SetDigits

inline void LInteger::SetDigits(const int newDigits); 
This method sets the _digits member of the calling instance equal to the value specified by newDigits.

SetMagnitude

inline void LInteger::SetMagnitude(unsigned int* newMagnitude); 
This method sets the _magnitude member of the calling instance equal to the value specified by newMagnitude.

Unary Minus: -x

friend inline LInteger operator-(const LInteger& x);
This operator returns a new instance representing the proudct of -1 and the integer represented by x.

Unary Plus: +x

friend inline LInteger operator+(const LInteger& x);
This operator returns a new instance representing the same integer that x represents.

Plus: x+y

friend LInteger operator+(const LInteger& x, const LInteger& y); 
This operator returns a new instance representing the sum of the integers represented by x and y.

Plus Equals: y+=x

inline LInteger& LInteger::operator+=(const LInteger& x); 
This operator makes the calling instance represent the sum of the integer it represented before the call and the integer that x represents. A reference to the modified calling instance is returned.

Postfix Increment: x++

inline LInteger LInteger::operator++(int); // postfix 
This operator makes the calling instance represent the integer one greater than the integer it represented before the call. An instance representing the integer the calling instance represented before the increment is returned.

Prefix Increment: ++x

inline LInteger& LInteger::operator++(); // prefix 
This operator makes the calling instance represent the integer one greater than the integer it represented before the call. A reference to the modified calling instance is returned.

Minus: x-y

friend LInteger operator-(const LInteger& x, const LInteger& y);
This operator returns a new instance representing the integer represented by x minus the integer represneted by y.

Minus Equals: y-=x

inline LInteger& LInteger::operator-=(const LInteger& x);
This operator makes the calling instance represent the integer it represented before the call minus the integer that x represents. A reference to the modified calling instance is returned.

Postfix Decrement: x--

inline LInteger LInteger::operator--(int);
This operator makes the calling instance represent the integer one less than the integer it represented before the call. An instance representing the integer represented by the calling instance before the decrement is returned.

Prefix Decrement: --x

inline LInteger& LInteger::operator--(); 
This operator makes the calling instance represent the integer one less than the integer it represented before the call. A reference to the modified calling instance is returned.

Times: x*y

friend LInteger operator*(const LInteger& x, const LInteger& y); 
friend LInteger operator*(const unsigned int x, const LInteger& y);
friend inline LInteger operator*(const LInteger& x, const unsigned int y);
friend inline LInteger operator*(const int x, const LInteger& y);
friend inline LInteger operator*(const LInteger& x, const int y);
These operators each return a new instance representing the product of the integer represented by x and the integer represneted by y.

Times Equals: y*=x

inline LInteger& LInteger::operator*=(const LInteger& x);
inline LInteger& LInteger::operator*=(const int x);
inline LInteger& LInteger::operator*=(const unsigned int x);
These operator each make the calling instance represent the product of the integer it represented before the call and the integer that x represents. A reference to the modified calling instance is returned by each.

Div: x/y

friend LInteger operator/(const LInteger& x, const LInteger& y);
From number theory, it is know that given two integers x and y, such that y is not zero, there exists integers q and r such that x=q*y +r with 0<=r<|y|. x/y returns an instance representing the integer q given by this theorem.

Div Equals: y/=x

inline LInteger& LInteger::operator/=(const LInteger& x);
This operator makes the calling instance represent the integer the return value of (*this)/x would represent (see directly above), and returns a reference to the modified calling instance.

Mod: x%y

friend LInteger operator%(const LInteger& x , const LInteger& y);
From number theory, it is known that given two integers x and y, such that y is not zero, there exists integers q and r such that x=q*y+ r with 0<=r<|y|. x%y returns an instance representing the integer r given by this theorem.

Mod Equals: y%=x

inline LInteger& LInteger::operator%=(const LInteger& x); 
This operator makes the calling instance represent the integer the return value of (*this)%x would represent (see directly above), and returns a reference to the modified calling instance.

Exclusive OR: x^y

friend LInteger operator^(const LInteger& x, const LInteger& y); 
This operator returns a new instance representing the integer whose ith most significant bit is equal to the exclusive OR of the ith most significant bit of the integer represented by x and the ith most significant bit of the integer represented by y.

Under the current implementation, x and y must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

Exclusive OR Equals: y^=x

inline LInteger& LInteger::operator^=(const LInteger& x); 
This operator makes the calling instance represent the integer the return value of (*this)^x would represent (see directly above), and returns a reference to the modified calling instance.

Under the current implementation, the calling instance and x must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

Inclusive OR: x|y

friend LInteger operator|(const LInteger& x, const LInteger& y); 
This operator returns a new instance representing the integer whose ith most significant bit is equal to the inclusive OR of the ith most significant bit of the integer represented by x and the ith most significant bit of the integer represented by y.

Under the current implementation, x and y must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

Inclusive OR Equals: y|=x

inline LInteger& LInteger::operator^=(const LInteger& x); 
This operator makes the calling instance represent the integer the return value of (*this)|x would represent (see directly above), and returns a reference to the modified calling instance.

Under the current implementation, the calling instance and x must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

AND: x&y

friend LInteger operator&(const LInteger& x, const LInteger& y); 
This operator returns a new instance representing the integer whose ith most significant bit is equal to the logical conjunction of the ith most significant bit of the integer represented by x and the ith most significant bit of the integer represented by y.

Under the current implementation, x and y must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

AND Equals: y&=x

inline LInteger& LInteger::operator^=(const LInteger& x); 
This operator makes the calling instance represent the integer the return value of (*this)&x would represent (see directly above), and returns a reference to the modified calling instance.

Under the current implementation, the calling instance and x must both represent non-negative integers with the same number of radix 2**(sizeof(unsigned int)*8) digits in their magnitudes.

Bitwise Negation: ~x

friend LInteger operator~(const LInteger& x);
This operator returns a new instance representing the integer whose ith most significant bit is equal to the logical negation of the ith most singficant bit of the integer represent by x.

Shift Right: x>>distance

friend LInteger operator>>(const LInteger& x, const int distance);
This operator returns a new instance representing the integer whose ith least significant bit is equal to the (i+distance)th least significant bit of the integer represented by x.

distance is allowed to be greater than the number of bits in an unsigned int, but must be non-negative.

Shift Right Equals: x>>=distance

inline LInteger& LInteger::operator>>=(const int distance); 
This operator makes the calling instance represent the integer the return value of (*this)>>distance would represent (see directly above), and returns a reference to the modified calling instance.

Shift Left: x<<distance

friend LInteger operator<<(const LInteger& x, const int distance);
This operator returns a new instance representing the integer whose ith least significant bit is equal to the (i-distance)th least significant bit of the integer represented by x. If (i-distance) is not positive, the ith bit of the integer represented by the returned instance will be zero.

distance can be greater than the number of bits in an unsigned int, but must be non-negative.

Shift Left Equals: x<<=distance

inline LInteger& LInteger::operator<<=(const int distance);
This operator makes the calling instance represent the integer the return value of (*this)<<distance would represent (see directly above), and returns a reference to the modified calling instance.

Less Than: x<y

friend inline int operator<(const LInteger& x, const LInteger& y);
This operator returns a non-zero value if x represents an integer that is less than the integer that y represents. Otherwise, 0 is returned.

Greater Than: x>y

friend inline int operator>(const LInteger& x, const LInteger& y);
This operator returns a non-zero value if x represents an integer that is greater than the integer that y represents. Otherwise, 0 is returned.

Equal To: x==y

friend inline int operator==(const LInteger& x, const LInteger& y); 
This operator returns a non-zero value if x represents an integer that is equal to the integer that y represents. Otherwise, 0 is returned.

Not Equal To: x!=y

friend inline int operator!=(const LInteger& x, const LInteger& y);
This operator returns a non-zero value if x represents an integer that is not equal to the integer that y represents. Otherwise, 0 is returned.

Less Than Or Equal To: x<=y

friend inline int operator<=(const LInteger& x, const LInteger& y);
This operator returns a non-zero value if x represents an integer that is less than or equal to the integer that y represents. Otherwise, 0 is returned.

Greater Than Or Equal To: x>=y

friend inline int operator>=(const LInteger& x, const LInteger& y);
This operator returns a non-zero value if x represents an integer that is greater than or equal to the integer that y represents. Otherwise, 0 is returned.

compress

void LInteger::compress(); 
This method strips the lead zeros, if any, off the calling instance's magnitude and modifies the internal digit count accordingly.

NumberOfBits

inline LInteger::NumberOfBits() const; 
This method returns the number of base 2 digits in calling instance's magnitude.

NumberOfBytes

inline LInteger::NumberOfBytes() const; 
This method returns the number of base 256 digits in calling instance's magnitude.

MultiplicativeIdentity

static const LInteger& LInteger::MultiplicativeIdentity();
This method returns a reference to an instance representing the multiplicative identity of the integer ring.

AdditiveIdentity

static const LInteger& LInteger::AdditiveIdentity();
This method returns a reference to an instance representing the additive identity of the integer ring.

Square

LInteger& LInteger::Square();
This method makes the calling instance represent the square of the integer it represented before the call.

DivByTwo

inline LInteger& LInteger::DivByTwo();
Let x be the integer the calling instance represents before the call. If x is non-negative, then this method makes the calling instance represent the floor of the integer x/2. If x is negative, then this method makes the calling instance represent the ceiling of the integer x/2.

Negative

static inline LInteger LInteger::Negative(const LInteger& x);
This method returns an instance which represents the product of -1 and the integer that x represents.

AbsoluteValue

static inline LInteger LInteger::AbsoluteValue(const LInteger& x);
This method returns an instance which represents the absolute value of the integer that x represents.

CompareMagnitudes

static int LInteger::CompareMagnitudes(const LInteger& x, 
                                       const LInteger& y);
This method returns a positive, zero, or negative value if x represents an integer that is, respectively, greater than, equal to, or less than the integer that y represents.

HasSmallPrimeFactor

unsigned int LIntger::HasSmallPrimeFactor() const;
This mehtod returns the smallest prime number in the BMath::SmallPrime[] array that is a factor of the integer that the calling instance represents. If none of the primes in BMath::SmallPrime[] is a factor, then 0 is returned. (Under version 0.2 of this library, the prime numbers under 2000 are tested as factors.)

IsOdd

inline int LInteger::IsOdd() const;
This method returns a non-zero value if the calling instance represents an odd integer and returns 0 otherwise.

IsEven

inline int LInteger::IsEven() const;
This method returns a non-zero value if the calling instance represents an even integer and returns 0 otherwise.

IsZero

inline int LInteger::IsZero() const;
This method returns a non-zero value if the calling instance represents 0 and returns 0 otherwise.

IsOne

inline int LInteger::IsOne() const;
This method returns a non-zero value if the calling instance represents 1 and returns 0 otherwise.

IsPositive

inline int LInteger::IsPositive() const;
This method returns a non-zero value if the calling instance represents a positive integer and returns 0 otherwise.

IsNegative

inline int LInteger::IsNegative() const;
This method returns a non-zero value if the calling instance represents a negative integer and returns 0 otherwise.

IsNonNegative

inline int LInteger::IsNonNegative() const;
This method returns a non-zero value if the calling instance represents a non-negative integer and returns 0 otherwise.

IsNonZero

inline int LInteger::IsNonZero() const;
This method returns a non-zero value if the calling instance represents an non-zero integer and returns 0 otherwise.

IsCompressable

inline int LInteger::IsCompressable() const;
This method returns a non-zero value if the calling instance's magnitude has lead zeros and returns 0 otherwise.

Print

ostream& Print(ostream& os, const int base=10) const;
This method pushes a base base ASCII representation of the integer the calling instance represents onto the output stream specified by os. base must be between 2 and 36. The representation is preceeded by a '-' if the calling instance represents a negative number, then by a '0' if base=8, or "0x" if base=16. The digits then follow: Digit values 0 to 9 are printed out as '0' through '9', while digits values 10 to 35 are printed out as 'A' through 'Z'. A reference to the modified output stream is returned.

Stream Output: os<<x

friend ostream& operator<<(ostream& os, const LInteger& x);
This operator pushes a base 10 ASCII representation of the integer that x represents onto the output stream specified by os. os<<x is equivalent to x.Print(os), so see Print for more details. A reference to the modified output stream is returned.

Stream Input: is>>x

friend istream& operator>>(istream& is, const LInteger& x);
This operator reads a line of input from the input stream specified by is into a string and attempts to convert this line into an integer using the same parsing rules as for the Constructor from a Character String. If the parsing succeeds, x will represent the integer that the line read in represents. Otherwise, the "fail" bit of the input stream will be set, and x's value will remain unchanged. In either case, a reference to the modified input stream is returned.

File Stream Output: ofs<<x

friend ofstream& operator<<(ofstream& ofs, const LInteger& x);
This operator writes a binary representation of the integer that x represents onto the file stream specified by ofs. The binary representation is the one given by the Distinguished Encoding Rules (DER). A reference to the modified file stream is returned.

File Stream Input: ifs>>x

friend ifstream& operator>>(ifstream& ifs, LInteger& x);
This operator reads a DER encoded integer from the file stream specified by ifs into x. If a parse error occurs, the input stream's "fail" bit will be set and x left unchanged. In any case, a reference to the modified input stream is returned.
Next Previous Table of Contents