/*
-* Matt McCutchen's Big Integer Library
-* http://mysite.verizon.net/mccutchen/bigint/
-*/
+ * Matt McCutchen's Big Integer Library
+ */
#include "BigInteger.hh"
}
/*
-* The steps for construction of a BigInteger
-* from an integral value x are as follows:
-* 1. If x is zero, create an empty BigInteger and stop.
-* 2. Allocate a one-block number array.
-* 3. If x is positive (or of an unsigned type), set the
-* sign of the BigInteger to positive.
-* 4. If x is of a signed type and is negative, set the
-* sign of the BigInteger to negative.
-* 5. If x is of a signed type, convert x (or -x if x < 0)
-* to the unsigned type of the same length.
-* 6. Expand x (or the result of step 5) to a Blk,
-* and store it in the number array.
-*
-* See remarks in `BigUnsigned.cc' and `NumberlikeArray.hh'
-* about new handling of zero-length arrays.
-*/
+ * The steps for construction of a BigInteger
+ * from an integral value x are as follows:
+ * 1. If x is zero, create an empty BigInteger and stop.
+ * 2. Allocate a one-block number array.
+ * 3. If x is positive (or of an unsigned type), set the
+ * sign of the BigInteger to positive.
+ * 4. If x is of a signed type and is negative, set the
+ * sign of the BigInteger to negative.
+ * 5. If x is of a signed type, convert x (or -x if x < 0)
+ * to the unsigned type of the same length.
+ * 6. Expand x (or the result of step 5) to a Blk,
+ * and store it in the number array.
+ *
+ * See remarks in `BigUnsigned.cc' and `NumberlikeArray.hh'
+ * about new handling of zero-length arrays.
+ */
BigInteger::BigInteger(unsigned long x) {
if (x == 0)
// CONVERTERS
/*
-* The steps for conversion of a BigInteger to an
-* integral type are as follows:
-* 1. If the BigInteger is zero, return zero.
-* 2. If the BigInteger is positive:
-* 3. If it is more than one block long or its lowest
-* block has bits set out of the range of the target
-* type, throw an exception.
-* 4. Otherwise, convert the lowest block to the
-* target type and return it.
-* 5. If the BigInteger is negative:
-* 6. If the target type is unsigned, throw an exception.
-* 7. If it is more than one block long or its lowest
-* block has bits set out of the range of the target
-* type, throw an exception.
-* 8. Otherwise, convert the lowest block to the
-* target type, negate it, and return it.
-*/
+ * The steps for conversion of a BigInteger to an
+ * integral type are as follows:
+ * 1. If the BigInteger is zero, return zero.
+ * 2. If the BigInteger is positive:
+ * 3. If it is more than one block long or its lowest
+ * block has bits set out of the range of the target
+ * type, throw an exception.
+ * 4. Otherwise, convert the lowest block to the
+ * target type and return it.
+ * 5. If the BigInteger is negative:
+ * 6. If the target type is unsigned, throw an exception.
+ * 7. If it is more than one block long or its lowest
+ * block has bits set out of the range of the target
+ * type, throw an exception.
+ * 8. Otherwise, convert the lowest block to the
+ * target type, negate it, and return it.
+ */
namespace {
// These masks are used to test whether a Blk has bits
// These do some messing around to determine the sign of the result,
// then call one of BigUnsigned's put-heres.
+// See remarks about aliased calls in BigUnsigned.cc .
+#define DTRT_ALIASED(cond, op) \
+ if (cond) { \
+ BigInteger tmpThis; \
+ tmpThis.op; \
+ *this = tmpThis; \
+ return; \
+ }
+
// Addition
void BigInteger::add(const BigInteger &a, const BigInteger &b) {
- // Block unsafe calls
- if (this == &a || this == &b)
- throw "BigInteger::add: One of the arguments is the invoked object";
+ DTRT_ALIASED(this == &a || this == &b, add(a, b));
// If one argument is zero, copy the other.
if (a.sign == zero)
operator =(b);
void BigInteger::subtract(const BigInteger &a, const BigInteger &b) {
// Notice that this routine is identical to BigInteger::add,
// if one replaces b.sign by its opposite.
- // Block unsafe calls
- if (this == &a || this == &b)
- throw "BigInteger::subtract: One of the arguments is the invoked object";
+ DTRT_ALIASED(this == &a || this == &b, subtract(a, b));
// If a is zero, copy b and flip its sign. If b is zero, copy a.
if (a.sign == zero) {
BigUnsigned::operator =(b);
- sign = Sign(-sign);
+ // Take the negative of _b_'s, sign, not ours.
+ // Bug pointed out by Sam Larkin on 2005.03.30.
+ sign = Sign(-b.sign);
} else if (b.sign == zero)
- operator =(a);
+ operator =(a);
// If their signs differ, take a.sign and add the magnitudes.
else if (a.sign != b.sign) {
sign = a.sign;
// Multiplication
void BigInteger::multiply(const BigInteger &a, const BigInteger &b) {
- // Block unsafe calls
- if (this == &a || this == &b)
- throw "BigInteger::multiply: One of the arguments is the invoked object";
+ DTRT_ALIASED(this == &a || this == &b, multiply(a, b));
// If one object is zero, copy zero and return.
if (a.sign == zero || b.sign == zero) {
sign = zero;
}
/*
-* DIVISION WITH REMAINDER
-* Please read the comments before the definition of
-* `BigUnsigned::divideWithRemainder' in `BigUnsigned.cc' for lots of
-* information you should know before reading this function.
-*
-* Following Knuth, I decree that x / y is to be
-* 0 if y==0 and floor(real-number x / y) if y!=0.
-* Then x % y shall be x - y*(integer x / y).
-*
-* Note that x = y * (x / y) + (x % y) always holds.
-* In addition, (x % y) is from 0 to y - 1 if y > 0,
-* and from -(|y| - 1) to 0 if y < 0. (x % y) = x if y = 0.
-*
-* Examples: (q = a / b, r = a % b)
-* a b q r
-* === === === ===
-* 4 3 1 1
-* -4 3 -2 2
-* 4 -3 -2 -2
-* -4 -3 1 -1
-*/
+ * DIVISION WITH REMAINDER
+ * Please read the comments before the definition of
+ * `BigUnsigned::divideWithRemainder' in `BigUnsigned.cc' for lots of
+ * information you should know before reading this function.
+ *
+ * Following Knuth, I decree that x / y is to be
+ * 0 if y==0 and floor(real-number x / y) if y!=0.
+ * Then x % y shall be x - y*(integer x / y).
+ *
+ * Note that x = y * (x / y) + (x % y) always holds.
+ * In addition, (x % y) is from 0 to y - 1 if y > 0,
+ * and from -(|y| - 1) to 0 if y < 0. (x % y) = x if y = 0.
+ *
+ * Examples: (q = a / b, r = a % b)
+ * a b q r
+ * === === === ===
+ * 4 3 1 1
+ * -4 3 -2 2
+ * 4 -3 -2 -2
+ * -4 -3 1 -1
+ */
void BigInteger::divideWithRemainder(const BigInteger &b, BigInteger &q) {
- // Block unsafe calls
- if (this == &b || this == &q || &b == &q)
- throw "BigInteger::divideWithRemainder: One of the arguments is the invoked object";
+ // Defend against aliased calls;
+ // same idea as in BigUnsigned::divideWithRemainder .
+ if (this == &q)
+ throw "BigInteger::divideWithRemainder: Cannot write quotient and remainder into the same variable";
+ if (this == &b || &q == &b) {
+ BigInteger tmpB(b);
+ divideWithRemainder(tmpB, q);
+ return;
+ }
+
// Division by zero gives quotient 0 and remainder *this
if (b.sign == zero) {
q.len = 0;
q.sign = zero;
return;
}
-
+
// Here *this != 0, b != 0.
-
+
// Do the operands have the same sign?
if (sign == b.sign) {
// Yes: easy case. Quotient is zero or positive.
// Decrease the magnitude of the dividend by one.
BigUnsigned::operator --();
/*
- * We tinker with the dividend before and with the
- * quotient and remainder after so that the result
- * comes out right. To see why it works, consider the following
- * list of examples, where A is the magnitude-decreased
- * a, Q and R are the results of BigUnsigned division
- * with remainder on A and |b|, and q and r are the
- * final results we want:
- *
- * a A b Q R q r
- * -3 -2 3 0 2 -1 0
- * -4 -3 3 1 0 -2 2
- * -5 -4 3 1 1 -2 1
- * -6 -5 3 1 2 -2 0
- *
- * It appears that we need a total of 3 corrections:
- * Decrease the magnitude of a to get A. Increase the
- * magnitude of Q to get q (and make it negative).
- * Find r = (b - 1) - R and give it the desired sign.
- */
+ * We tinker with the dividend before and with the
+ * quotient and remainder after so that the result
+ * comes out right. To see why it works, consider the following
+ * list of examples, where A is the magnitude-decreased
+ * a, Q and R are the results of BigUnsigned division
+ * with remainder on A and |b|, and q and r are the
+ * final results we want:
+ *
+ * a A b Q R q r
+ * -3 -2 3 0 2 -1 0
+ * -4 -3 3 1 0 -2 2
+ * -5 -4 3 1 1 -2 1
+ * -6 -5 3 1 2 -2 0
+ *
+ * It appears that we need a total of 3 corrections:
+ * Decrease the magnitude of a to get A. Increase the
+ * magnitude of Q to get q (and make it negative).
+ * Find r = (b - 1) - R and give it the desired sign.
+ */
}
-
+
// Divide the magnitudes.
BigUnsigned::divideWithRemainder(b, q);
-
+
if (sign != b.sign) {
// More for the harder case (as described):
// Increase the magnitude of the quotient by one.
BigUnsigned::subtract(b, temp);
BigUnsigned::operator --();
}
-
+
// Sign of the remainder is always the sign of the divisor b.
sign = b.sign;
-
+
// Set signs to zero as necessary. (Thanks David Allen!)
if (len == 0)
sign = zero;
if (q.len == 0)
q.sign = zero;
-
+
// WHEW!!!
}
// Negation
void BigInteger::negate(const BigInteger &a) {
- // Block unsafe calls
- if (this == &a)
- throw "BigInteger::negate: The argument is the invoked object";
+ DTRT_ALIASED(this == &a, negate(a));
// Copy a's magnitude
BigUnsigned::operator =(a);
// Copy the opposite of a.sign