/*
* Matt McCutchen's Big Integer Library
-* http://mysite.verizon.net/mccutchen/bigint/
*/
#include "BigInteger.hh"
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
}
}
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
} else if (x < 0) {
cap = 1;
blk = new Blk[1];
sign = negative;
len = 1;
- *blk = Blk(-x);
+ blk[0] = Blk(-x);
} else
sign = zero;
}
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
}
}
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
} else if (x < 0) {
cap = 1;
blk = new Blk[1];
sign = negative;
len = 1;
- *blk = Blk(-x);
+ blk[0] = Blk(-x);
} else
sign = zero;
}
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
}
}
blk = new Blk[1];
sign = positive;
len = 1;
- *blk = Blk(x);
+ blk[0] = Blk(x);
} else if (x < 0) {
cap = 1;
blk = new Blk[1];
sign = negative;
len = 1;
- *blk = Blk(-x);
+ blk[0] = Blk(-x);
} else
sign = zero;
}
return 0;
case positive:
if (len == 1)
- return *blk;
+ return blk[0];
else
throw "BigInteger operator unsigned long() const: Value is too big for an unsigned long";
case negative:
case zero:
return 0;
case positive:
- if (len == 1 && (*blk & ~lMask) == 0)
- return long(*blk);
+ if (len == 1 && (blk[0] & ~lMask) == 0)
+ return long(blk[0]);
else
throw "BigInteger operator long() const: Value is too big for a long";
case negative:
- if (len == 1 && (*blk & ~lMask) == 0)
- return -long(*blk);
+ if (len == 1 && (blk[0] & ~lMask) == 0)
+ return -long(blk[0]);
else
throw "BigInteger operator long() const: Value is too big for a long";
default:
case zero:
return 0;
case positive:
- if (len == 1 && (*blk & ~uiMask) == 0)
- return (unsigned int)(*blk);
+ if (len == 1 && (blk[0] & ~uiMask) == 0)
+ return (unsigned int)(blk[0]);
else
throw "BigInteger operator unsigned int() const: Value is too big for an unsigned int";
case negative:
case zero:
return 0;
case positive:
- if (len == 1 && (*blk & ~iMask) == 0)
- return int(*blk);
+ if (len == 1 && (blk[0] & ~iMask) == 0)
+ return int(blk[0]);
else
throw "BigInteger operator int() const: Value is too big for an int";
case negative:
- if (len == 1 && (*blk & ~iMask) == 0)
- return -int(*blk);
+ if (len == 1 && (blk[0] & ~iMask) == 0)
+ return -int(blk[0]);
else
throw "BigInteger operator int() const: Value is too big for an int";
default:
case zero:
return 0;
case positive:
- if (len == 1 && (*blk & ~usMask) == 0)
- return (unsigned short)(*blk);
+ if (len == 1 && (blk[0] & ~usMask) == 0)
+ return (unsigned short)(blk[0]);
else
throw "BigInteger operator unsigned short() const: Value is too big for an unsigned short";
case negative:
case zero:
return 0;
case positive:
- if (len == 1 && (*blk & ~sMask) == 0)
- return short(*blk);
+ if (len == 1 && (blk[0] & ~sMask) == 0)
+ return short(blk[0]);
else
throw "BigInteger operator short() const: Value is too big for a short";
case negative:
- if (len == 1 && (*blk & ~sMask) == 0)
- return -short(*blk);
+ if (len == 1 && (blk[0] & ~sMask) == 0)
+ return -short(blk[0]);
else
throw "BigInteger operator short() const: Value is too big for a short";
default:
// 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 DOTR_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";
+ DOTR_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";
+ DOTR_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";
+ DOTR_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;
* -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.
* 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";
+ DOTR_ALIASED(this == &a, negate(a));
// Copy a's magnitude
BigUnsigned::operator =(a);
// Copy the opposite of a.sign
allocate(1);
sign = positive;
len = 1;
- *blk = 1;
+ blk[0] = 1;
break;
case positive:
BigUnsigned::operator ++();
allocate(1);
sign = negative;
len = 1;
- *blk = 1;
+ blk[0] = 1;
break;
case negative:
BigUnsigned::operator ++();