#include <linteger/linteger.hxx>
LInteger
objects will be as easy
the corresponding operations on regular int
s.
LInteger
sLInteger
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 |
Note that the 4 being added to the start address in the table above is a
byte displacement.
Warning:
It is important that _magnitude
unsigned int* _magnitude;
Magnitudes are represented by
arrays of
unsigned int
s. 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
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:
inline int LInteger::IsCompressable() const
will return zero if the integer has no lead zeros, and non-zero
otherwise.
void LInteger::compress()
will strip the
leading zeros, if any, off the magnitude and adjust the
_digits member accordingly.
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.)
static const LInteger LInteger::One;This is an instance representing the integer 1.
static const LInteger LInteger::Zero;This is an instance representing the integer 0.
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.
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
LInteger
s 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.
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.
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.
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
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.
LInteger::LInteger(const LInteger& x);This constructor creates an instance which represents the same integer that x does.
unsigned int
sLInteger::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.
int
s
LInteger::LInteger(const int x);
This constructor creates an instance representing the same integer that x represents.
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.
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.
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.
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.
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.
LInteger::~LInteger();The destructor frees the memory dynamically allocated to store the magnitude.
static LInteger LInteger::TwoToThe(const int x);This method returns an instance representing 2**x.
inline unsigned char LInteger::sign() const;This method returns 0 if the calling instance represents a non-negative integer, and 1 otherwise.
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.
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!
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.
inline void LInteger::SetDigits(const int newDigits);This method sets the _digits member of the calling instance equal to the value specified by newDigits.
inline void LInteger::SetMagnitude(unsigned int* newMagnitude);This method sets the _magnitude member of the calling instance equal to the value specified by newMagnitude.
-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.
+x
friend inline LInteger operator+(const LInteger& x);This operator returns a new instance representing the same integer that x represents.
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.
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.
x++
inline LInteger LInteger::operator++(int); // postfixThis 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.
++x
inline LInteger& LInteger::operator++(); // prefixThis 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.
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.
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.
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.
--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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
~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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
void LInteger::compress();This method strips the lead zeros, if any, off the calling instance's magnitude and modifies the internal digit count accordingly.
inline LInteger::NumberOfBits() const;This method returns the number of base 2 digits in calling instance's magnitude.
inline LInteger::NumberOfBytes() const;This method returns the number of base 256 digits in calling instance's magnitude.
static const LInteger& LInteger::MultiplicativeIdentity();This method returns a reference to an instance representing the multiplicative identity of the integer ring.
static const LInteger& LInteger::AdditiveIdentity();This method returns a reference to an instance representing the additive identity of the integer ring.
LInteger& LInteger::Square();This method makes the calling instance represent the square of the integer it represented before the call.
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.
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.
static inline LInteger LInteger::AbsoluteValue(const LInteger& x);This method returns an instance which represents the absolute value of the integer that x represents.
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.
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.)
inline int LInteger::IsOdd() const;This method returns a non-zero value if the calling instance represents an odd integer and returns 0 otherwise.
inline int LInteger::IsEven() const;This method returns a non-zero value if the calling instance represents an even integer and returns 0 otherwise.
inline int LInteger::IsZero() const;This method returns a non-zero value if the calling instance represents 0 and returns 0 otherwise.
inline int LInteger::IsOne() const;This method returns a non-zero value if the calling instance represents 1 and returns 0 otherwise.
inline int LInteger::IsPositive() const;This method returns a non-zero value if the calling instance represents a positive integer and returns 0 otherwise.
inline int LInteger::IsNegative() const;This method returns a non-zero value if the calling instance represents a negative integer and returns 0 otherwise.
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.
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.
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.
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.
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.
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.
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.
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.