Old snapshot `BigIntegerLibrary-2004.12.24.2'; see the ChangeLog file.
[bigint/bigint.git] / BigUnsigned.cpp
diff --git a/BigUnsigned.cpp b/BigUnsigned.cpp
deleted file mode 100644 (file)
index 6864d1c..0000000
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
-* Matt McCutchen's Big Integer Library
-* http://mysite.verizon.net/mccutchen/bigint/
-*/
-
-#include "BigUnsigned.h"
-
-// MANAGEMENT
-
-// This routine is called to ensure the number array is at least a
-// certain size before the result of an operation is written over it. 
-void BigUnsigned::allocate(BlkNum c) {
-       // If the requested capacity is more than the current capacity...
-       if (c > cap) {
-               // Delete the old number array
-               delete [] blk;
-               // Allocate the new array
-               cap = c;
-               blk = new Blk[cap];
-       }
-}
-
-// This routine is called to ensure the number array is at least a
-// certain size without losing its contents.
-void BigUnsigned::allocateAndCopy(BlkNum c) {
-       // If the requested capacity is more than the current capacity...
-       if (c > cap) {
-               Blk *oldBlk = blk;
-               // Allocate the new number array
-               cap = c;
-               blk = new Blk[cap];
-               // Copy number blocks
-               BlkNum i;
-               Blk *blkI;
-               const Blk *oldBlkI;
-               for (i = 0, blkI = blk, oldBlkI = oldBlk; i < len; i++, blkI++, oldBlkI++)
-                       *blkI = *oldBlkI;
-               // Delete the old array
-               delete [] oldBlk;
-       }
-}
-
-// Copy constructor
-BigUnsigned::BigUnsigned(const BigUnsigned &x) : len(x.len) {
-       // Create number array
-       cap = len;
-       blk = new Blk[cap];
-       // Copy number blocks
-       BlkNum i;
-       Blk *blkI;
-       const Blk *xBlkI;
-       for (i = 0, blkI = blk, xBlkI = x.blk; i < len; i++, blkI++, xBlkI++)
-               *blkI = *xBlkI;
-}
-
-// Assignment operator
-void BigUnsigned::operator=(const BigUnsigned &x) {
-       // Calls like a = a have no effect
-       if (this == &x)
-               return;
-       // Copy length
-       len = x.len;
-       // Expand number array if necessary
-       allocate(len);
-       // Copy number blocks
-       BlkNum i;
-       Blk *blkI;
-       const Blk *xBlkI;
-       for (i = 0, blkI = blk, xBlkI = x.blk; i < len; i++, blkI++, xBlkI++)
-               *blkI = *xBlkI;
-}
-
-// Constructor from an array of blocks
-BigUnsigned::BigUnsigned(const Blk *b, BlkNum l) : cap(l), len(l) {
-       // Create number array
-       blk = new Blk[cap];
-       // Copy number blocks
-       BlkNum i;
-       Blk *blkI;
-       const Blk *bI;
-       for (i = 0, blkI = blk, bI = b; i < len; i++, blkI++, bI++)
-               *blkI = *bI;
-       zapLeadingZeros();
-}
-
-/*
-* The steps for construction of a BigUnsigned
-* from an integral value x are as follows:
-* 1. If x is zero, create an empty BigUnsigned and stop.
-* 2. If x is negative, throw an exception.
-* 3. Allocate a one-block number array.
-* 4. If x is of a signed type, convert x to the unsigned
-*    type of the same length.
-* 5. Expand x to a Blk, and store it in the number array.
-*/
-
-BigUnsigned::BigUnsigned(unsigned long x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       }
-}
-
-BigUnsigned::BigUnsigned(long x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else if (x > 0) {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       } else
-    throw "BigUnsigned::BigUnsigned(long): Cannot construct a BigUnsigned from a negative number";
-}
-
-BigUnsigned::BigUnsigned(unsigned int x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       }
-}
-
-BigUnsigned::BigUnsigned(int x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else if (x > 0) {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       } else
-    throw "BigUnsigned::BigUnsigned(int): Cannot construct a BigUnsigned from a negative number";
-}
-
-BigUnsigned::BigUnsigned(unsigned short x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       }
-}
-
-BigUnsigned::BigUnsigned(short x) {
-       if (x == 0) {
-               cap = 0;
-               blk = new Blk[0];
-               len = 0;
-       } else if (x > 0) {
-               cap = 1;
-               blk = new Blk[1];
-               len = 1;
-               *blk = Blk(x);
-       } else
-    throw "BigUnsigned::BigUnsigned(short): Cannot construct a BigUnsigned from a negative number";
-}
-
-// CONVERTERS
-/*
-* The steps for conversion of a BigUnsigned to an
-* integral type are as follows:
-* 1. If the BigUnsigned is zero, return zero.
-* 2. 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.
-* 3. Otherwise, convert the lowest block to the
-*    target type and return it.
-*/
-
-namespace {
-       // These masks are used to test whether a Blk has bits
-       // set out of the range of a smaller integral type.  Note
-       // that this range is not considered to include the sign bit.
-       const BigUnsigned::Blk  lMask = ~0 >> 1;
-       const BigUnsigned::Blk uiMask = (unsigned int)(~0);
-       const BigUnsigned::Blk  iMask = uiMask >> 1;
-       const BigUnsigned::Blk usMask = (unsigned short)(~0);
-       const BigUnsigned::Blk  sMask = usMask >> 1;
-}
-
-BigUnsigned::operator unsigned long() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1)
-               return (unsigned long) *blk;
-       else
-               throw "BigUnsigned::operator unsigned long: Value is too big for an unsigned long";
-}
-
-BigUnsigned::operator long() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1 && (*blk & lMask) == *blk)
-               return (long) *blk;
-       else
-               throw "BigUnsigned::operator long: Value is too big for a long";
-}
-
-BigUnsigned::operator unsigned int() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1 && (*blk & uiMask) == *blk)
-               return (unsigned int) *blk;
-       else
-               throw "BigUnsigned::operator unsigned int: Value is too big for an unsigned int";
-}
-
-BigUnsigned::operator int() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1 && (*blk & iMask) == *blk)
-               return (int) *blk;
-       else
-               throw "BigUnsigned::operator int: Value is too big for an int";
-}
-
-BigUnsigned::operator unsigned short() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1 && (*blk & usMask) == *blk)
-               return (unsigned short) *blk;
-       else
-               throw "BigUnsigned::operator unsigned short: Value is too big for an unsigned short";
-}
-
-BigUnsigned::operator short() const {
-       if (len == 0)
-               return 0;
-       else if (len == 1 && (*blk & sMask) == *blk)
-               return (short) *blk;
-       else
-               throw "BigUnsigned::operator short: Value is too big for a short";
-}
-
-// COMPARISON
-BigUnsigned::CmpRes BigUnsigned::compareTo(const BigUnsigned &x) const {
-       // A bigger length implies a bigger number.
-       if (len < x.len)
-               return less;
-       else if (len > x.len)
-               return greater;
-       else {
-               // Compare blocks one by one from left to right.
-               BlkNum i = len;
-               const Blk *blkI = blk + len;
-               const Blk *xBlkI = x.blk + len;
-               while (i > 0) {
-                       i--;
-                       blkI--;
-                       xBlkI--;
-                       if (*blkI == *xBlkI)
-                               continue;
-                       else if (*blkI > *xBlkI)
-                               return greater;
-                       else
-                               return less;
-               }
-               // If no blocks differed, the numbers are equal.
-               return equal;
-       }
-}
-
-// PUT-HERE OPERATIONS
-
-// Addition
-void BigUnsigned::add(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::add: One of the arguments is the invoked object";
-       // If one argument is zero, copy the other.
-       if (a.len == 0) {
-               operator =(b);
-               return;
-       } else if (b.len == 0) {
-               operator =(a);
-               return;
-       }
-       // Carries in and out of an addition stage
-       bool carryIn, carryOut;
-       Blk temp;
-       BlkNum i;
-       // a2 points to the longer input, b2 points to the shorter
-       const BigUnsigned *a2, *b2;
-       if (a.len >= b.len) {
-               a2 = &a;
-               b2 = &b;
-       } else {
-               a2 = &b;
-               b2 = &a;
-       }
-       // These point directly to the position of interest in the
-       // corresponding block arrays, for faster access.
-       Blk *blkI;
-       const Blk *a2BlkI, *b2BlkI;
-       // Set prelimiary length and make room in this BigUnsigned
-       len = a2->len + 1;
-       allocate(len);
-       // For each block index that is present in both inputs...
-       for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk,
-       carryIn = false; i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++) {
-               // Add input blocks
-               temp = *a2BlkI + *b2BlkI;
-               // If a rollover occurred, the result is less than either input.
-               // This test is used many times in the BigUnsigned code.
-               carryOut = (temp < *a2BlkI);
-               // If a carry was input, handle it
-               if (carryIn) {
-                       temp++;
-                       carryOut |= (temp == 0);
-               }
-               *blkI = temp; // Save the addition result
-               carryIn = carryOut; // Pass the carry along
-       }
-       // If there is a carry left over, increase blocks until
-       // one does not roll over.
-       for (; i < a2->len && carryIn; i++, blkI++, a2BlkI++) {
-               temp = *a2BlkI + 1;
-               carryIn = (temp == 0);
-               *blkI = temp;
-       }
-       // If the carry was resolved but the larger number
-       // still has blocks, copy them over.
-       for (; i < a2->len; i++, blkI++, a2BlkI++)
-               *blkI = *a2BlkI;
-       // Set the extra block if there's still a carry, decrease length otherwise
-       if (carryIn)
-               *blkI = 1;
-       else
-               len--;
-}
-
-// Subtraction
-void BigUnsigned::subtract(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::subtract: One of the arguments is the invoked object";
-       // If b is zero, copy a.  If a is shorter than b, the result is negative.
-       if (b.len == 0) {
-               operator =(a);
-               return;
-       } else if (a.len < b.len)
-    throw "BigUnsigned::subtract: Negative result in unsigned calculation";
-       bool borrowIn, borrowOut;
-       Blk temp;
-       BlkNum i;
-       // These point directly to the position of interest in the
-       // corresponding block arrays, for faster access.
-       Blk *blkI;
-       const Blk *aBlkI, *bBlkI;
-       // Set preliminary length and make room
-       len = a.len;
-       allocate(len);
-       // For each block index that is present in both inputs...
-       for (i = 0, blkI = blk, aBlkI = a.blk, bBlkI = b.blk,
-       borrowIn = false; i < b.len; i++, blkI++, aBlkI++, bBlkI++) {
-               temp = *aBlkI - *bBlkI;
-               // If a reverse rollover occurred, the result is greater than the block from a.
-               borrowOut = (temp > *aBlkI);
-               // Handle an incoming borrow
-               if (borrowIn) {
-                       borrowOut |= (temp == 0);
-                       temp--;
-               }
-               *blkI = temp; // Save the subtraction result
-               borrowIn = borrowOut; // Pass the borrow along
-       }
-       // If there is a borrow left over, decrease blocks until
-       // one does not reverse rollover.
-       for (; i < a.len && borrowIn; i++, blkI++, aBlkI++) {
-               borrowIn = (*aBlkI == 0);
-               *blkI = *aBlkI - 1;
-       }
-       // If there's still a borrow, the result is negative.
-       // Throw an exception, but zero out this object first.
-       if (borrowIn) {
-               len = 0;
-               throw "BigUnsigned::subtract: Negative result in unsigned calculation";
-       } else // Copy over the rest of the blocks
-    for (; i < a.len; i++, blkI++, aBlkI++)
-               *blkI = *aBlkI;
-       // Zap leading zeros
-       zapLeadingZeros();
-}
-
-// Multiplication
-void BigUnsigned::multiply(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::multiply: One of the arguments is the invoked object";
-       // If either a or b is zero, set to zero.
-       if (a.len == 0 || b.len == 0) {
-               len = 0;
-               return;
-       }
-       // Overall method: this = 0, then for each 1-bit of a, add b
-       // to this shifted the appropriate amount.
-       // Variables for the calculation
-       BlkNum i, j;
-       unsigned int i2;
-       Blk aBlk, bHigh, temp;
-       bool carryIn, carryOut;
-       // These point directly to the positions of interest in the
-       // corresponding block arrays, for faster access.
-       Blk *blkI, *blkK;
-       const Blk *aBlkI, *bBlkJ;
-       // Set preliminary length and make room
-       len = a.len + b.len;
-       allocate(len);
-       // Zero out this object
-       for (i = 0, blkI = blk; i < len; i++, blkI++)
-               *blkI = 0;
-       // For each block of the first number...
-       for (i = 0, blkI = blk, aBlkI = a.blk; i < a.len; i++, blkI++, aBlkI++)
-               // For each 1-bit of that block...
-    for (i2 = 0, aBlk = *aBlkI; aBlk != 0; i2++, aBlk >>= 1) {
-               if ((aBlk & 1) == 0)
-                       continue;
-               /* Add b to this, shifted left i blocks and i2 bits.
-               * j is the index in b, and k = i + j is the index in this.
-               * The low bits of b.blk[j] are shifted and added to blk[k].
-               * bHigh is used to carry the high bits to the next addition. */
-               carryIn = false;
-               bHigh = 0;
-               for (j = 0, bBlkJ = b.blk, blkK = blkI; j < b.len; j++, bBlkJ++, blkK++) {
-                       temp = *blkK + ((*bBlkJ << i2) | bHigh);
-                       carryOut = (temp < *blkK);
-                       if (carryIn) {
-                               temp++;
-                               carryOut |= (temp == 0);
-                       }
-                       *blkK = temp;
-                       carryIn = carryOut;
-                       bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
-               }
-               temp = *blkK + bHigh;
-               carryOut = (temp < *blkK);
-               if (carryIn) {
-                       temp++;
-                       carryOut |= (temp == 0);
-               }
-               *blkK = temp;
-               carryIn = carryOut;
-               for (; carryIn; blkK++) {
-                       (*blkK)++;
-                       carryIn = (*blkK == 0);
-               }
-    }
-       // Zap leading zero
-       if (blk[len - 1] == 0)
-               len--;
-}
-
-// Division
-void BigUnsigned::divide(const BigUnsigned &a, const BigUnsigned &b) {
-       // Note: This is integer division.  Any fractional part
-       // of the result is truncated.
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::divide: One of the arguments is the invoked object";
-       // If b is zero, throw an exception.  If a is zero, set to zero.
-       else if (b.len == 0)
-               throw "BigUnsigned::divide: Division by zero";
-       else if (a.len < b.len) {
-               len = 0;
-               return;
-       }
-       /* Overall method: Subtract b, shifted varying amounts to
-       * the left, from a, setting the bit in the quotient
-       * whenever the subtraction succeeds. */
-       // Variables for the calculation
-       BlkNum i, j, k;
-       unsigned int i2;
-       Blk bHigh, temp;
-       bool borrowIn, borrowOut;
-       // work1 is a copy of a that can be modified
-       // after each successful subtraction.
-       Blk *work1 = new Blk[a.len + 1];
-       Blk *work1I = work1;
-       const Blk *aBlkI = a.blk;
-       for (i = 0; i < a.len; i++, work1I++, aBlkI++)
-               *work1I = *aBlkI;
-       *work1I = 0;
-       // work2 holds part of the result of a subtraction
-       Blk *work2 = new Blk[a.len + 1];
-       // These point directly to the positions of interest in the
-       // corresponding block arrays, for faster access.
-       Blk *blkI, *work1K, *work2J;
-       const Blk *bBlkJ;
-       // Set preliminary length and make room
-       len = a.len - b.len + 1;
-       allocate(len);
-       // For each possible left-shift of b in blocks...
-       i = len;
-       blkI = blk + len;
-       work1I = work1 + len;
-       while (i > 0) {
-               i--;
-               blkI--;
-               work1I--;
-               // For each possible left-shift of b in bits...
-               *blkI = 0;
-               i2 = 8 * sizeof(Blk);
-               while (i2 > 0) {
-                       i2--;
-                       // Subtract b, shifted left i blocks and i2 bits, from work1
-                       // and store the answer in work2.  See note in BigUnsigned::multiply.
-                       bHigh = 0;
-                       for (j = 0, bBlkJ = b.blk, work2J = work2, k = i, work1K = work1I,
-                       borrowIn = false; j < b.len; j++, bBlkJ++, work2J++, k++, work1K++) {
-                               temp = *work1K - ((*bBlkJ << i2) | bHigh);
-                               borrowOut = (temp > *work1K);
-                               if (borrowIn) {
-                                       borrowOut |= (temp == 0);
-                                       temp--;
-                               }
-                               *work2J = temp;
-                               borrowIn = borrowOut;
-                               bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
-                       }
-                       temp = *work1K - bHigh;
-                       borrowOut = (temp > *work1K);
-                       if (borrowIn) {
-                               borrowOut |= (temp == 0);
-                               temp--;
-                       }
-                       *work2J = temp;
-                       borrowIn = borrowOut;
-                       j++;
-                       work2J++;
-                       k++;
-                       work1K++;
-                       for (; k < a.len + 1 && borrowIn; j++, work2J++, k++, work1K++) {
-                               borrowIn = (*work1K == 0);
-                               *work2J = *work1K - 1;
-                       }
-                       /* If the subtraction was performed successfully, set bit i2
-                       * in block i of the quotient, and copy the changed portion of
-                       * work2 back to work1. Otherwise, reset that bit and move on. */
-                       if (!borrowIn) {
-                               *blkI |= (1 << i2);
-                               while (j > 0) {
-                                       j--;
-                                       work2J--;
-                                       k--;
-                                       work1K--;
-                                       *work1K = *work2J;
-                               }
-                       }
-               }
-       }
-       // Zap leading zero
-       if (blk[len - 1] == 0)
-               len--;
-       // Deallocate temporary arrays.
-       // (Thanks to Brad Spencer for noticing my accidental omission of this!)
-       delete [] work1;
-       delete [] work2;
-}
-
-// Modulo
-void BigUnsigned::modulo(const BigUnsigned &a, const BigUnsigned &b) {
-       /* Note that the mathematical definition of mod is somewhat
-       * different from the way the normal C++ % operator behaves.
-       * This function does it the mathematical way. */
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::modulo: One of the arguments is the invoked object";
-       // If b is zero, copy a and return.  By the mathematical definition,
-       // x mod 0 = x, though the normal C++ % would throw an exception.
-       else if (b.len == 0) {
-               len = 0;
-               return;
-               // If a is zero, set to zero and return.
-       } else if (a.len < b.len) {
-               operator =(a);
-               return;
-       }
-       /* Overall method: Copy a into this.  Then subtract b,
-       * shifted varying amounts to the left, from this.
-       * When no more subtraction is possible, stop; this
-       * will contain the remainder.
-       * This is very similar to the division routine, except
-       * that whether or not a subtraction succeeds is ignored,
-       * and "this" serves the purpose of work1. */
-       // Variables for the calculation
-       BlkNum i, j, k;
-       unsigned int i2;
-       Blk bHigh, temp;
-       bool borrowIn, borrowOut;
-       allocate(a.len + 1);
-       operator =(a);
-       blk[len] = 0;
-       // work2 holds part of the result of a subtraction
-       Blk *work2 = new Blk[a.len + 1];
-       // These point directly to the positions of interest in the
-       // corresponding block arrays, for faster access.
-       Blk *blkI, *blkK, *work2J;
-       const Blk *bBlkJ;
-       // For each possible left-shift of b in blocks...
-       i = len;
-       blkI = blk + len;
-       while (i > 0) {
-               i--;
-               blkI--;
-               // For each possible left-shift of b in bits...
-               i2 = 8 * sizeof(Blk);
-               while (i2 > 0) {
-                       i2--;
-                       // Subtract b, shifted left i blocks and i2 bits, from work1
-                       // and store the answer in work2.  See note in BigUnsigned::multiply.
-                       bHigh = 0;
-                       for (j = 0, bBlkJ = b.blk, work2J = work2, k = i, blkK = blkI,
-                       borrowIn = false; j < b.len; j++, bBlkJ++, work2J++, k++, blkK++) {
-                               temp = *blkK - ((*bBlkJ << i2) | bHigh);
-                               borrowOut = (temp > *blkK);
-                               if (borrowIn) {
-                                       borrowOut |= (temp == 0);
-                                       temp--;
-                               }
-                               *work2J = temp;
-                               borrowIn = borrowOut;
-                               bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
-                       }
-                       temp = *blkK - bHigh;
-                       borrowOut = (temp > *blkK);
-                       if (borrowIn) {
-                               borrowOut |= (temp == 0);
-                               temp--;
-                       }
-                       *work2J = temp;
-                       borrowIn = borrowOut;
-                       j++;
-                       work2J++;
-                       k++;
-                       blkK++;
-                       for (; k < a.len + 1 && borrowIn; j++, work2J++, k++, blkK++) {
-                               borrowIn = (*blkK == 0);
-                               *work2J = *blkK - 1;
-                       }
-                       // If the subtraction was performed successfully, set bit i2
-                       // in block i of the quotient, and copy the changed portion of
-                       // work2 back to this.
-                       if (!borrowIn)
-                       while (j > 0) {
-                               j--;
-                               work2J--;
-                               k--;
-                               blkK--;
-                               *blkK = *work2J;
-                       }
-               }
-       }
-       // Blocks higher than the last block of the modulus are zero.
-       len = b.len;
-       // Zap leading zeros
-       zapLeadingZeros();
-}
-
-// Bitwise and
-void BigUnsigned::bitAnd(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::bitAnd: One of the arguments is the invoked object";
-       len = (a.len >= b.len) ? b.len : a.len;
-       allocate(len);
-       BlkNum i;
-       Blk *blkI;
-       const Blk *aBlkI, *bBlkI;
-       for (i = 0, blkI = blk, aBlkI = a.blk, bBlkI = b.blk;
-       i < len; i++, blkI++, aBlkI++, bBlkI++)
-    *blkI = *aBlkI & *bBlkI;
-       zapLeadingZeros();
-}
-
-// Bitwise or
-void BigUnsigned::bitOr(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::bitOr: One of the arguments is the invoked object";
-       BlkNum i;
-       Blk *blkI;
-       const BigUnsigned *a2, *b2;
-       if (a.len >= b.len) {
-               a2 = &a;
-               b2 = &b;
-       } else {
-               a2 = &b;
-               b2 = &a;
-       }
-       allocate(a2->len);
-       const Blk *a2BlkI, *b2BlkI;
-       for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk;
-       i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++)
-    *blkI = *a2BlkI | *b2BlkI;
-       for (; i < a2->len; i++, blkI++, a2BlkI++)
-               *blkI = *a2BlkI;
-       len = a2->len;
-}
-
-// Bitwise xor
-void BigUnsigned::bitXor(const BigUnsigned &a, const BigUnsigned &b) {
-       // Block unsafe calls
-       if (this == &a || this == &b)
-               throw "BigUnsigned::bitXor: One of the arguments is the invoked object";
-       BlkNum i;
-       Blk *blkI;
-       const BigUnsigned *a2, *b2;
-       if (a.len >= b.len) {
-               a2 = &a;
-               b2 = &b;
-       } else {
-               a2 = &b;
-               b2 = &a;
-       }
-       allocate(b2->len);
-       const Blk *a2BlkI, *b2BlkI;
-       for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk;
-       i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++)
-    *blkI = *a2BlkI ^ *b2BlkI;
-       for (; i < a2->len; i++, blkI++, a2BlkI++)
-               *blkI = *a2BlkI;
-       len = a2->len;
-       zapLeadingZeros();
-}
-
-// INCREMENT/DECREMENT OPERATORS
-
-// Prefix increment
-void BigUnsigned::operator ++() {
-       BlkNum i;
-       Blk *blkI;
-       bool carry = true;
-       for (i = 0, blkI = blk; i < len && carry; i++) {
-               (*blkI)++;
-               carry = (*blkI == 0);
-       }
-       if (carry) {
-               allocateAndCopy(len + 1);
-               *blkI = 1;
-       }
-}
-
-// Postfix increment: same as prefix
-void BigUnsigned::operator ++(int) {
-       operator ++();
-}
-
-// Prefix decrement
-void BigUnsigned::operator --() {
-       if (len == 0)
-               throw "BigUnsigned::operator --(): Cannot decrement an unsigned zero";
-       BlkNum i;
-       Blk *blkI;
-       bool borrow = true;
-       for (i = 0, blkI = blk; borrow; i++) {
-               borrow = (*blkI == 0);
-               (*blkI)--;
-       }
-       if (blk[len - 1] == 0)
-               len--;
-}
-
-// Postfix decrement: same as prefix
-void BigUnsigned::operator --(int) {
-       operator --();
-}
-