BigUnsignedInABase::BigUnsignedInABase(const std::string &s, Base base) { // Check the base. if (base > 36) throw "BigUnsignedInABase(std::string, Base): The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine."; // Save the base. // This pattern is seldom seen in C++, but the analogous ``this.'' is common in Java. this->base = base; // `s.length()' is a `size_t', while `len' is a `NumberlikeArray::Index', // also known as an `unsigned int'. Some compilers warn without this cast. len = Index(s.length()); allocate(len); Index digitNum, symbolNumInString; for (digitNum = 0; digitNum < len; digitNum++) { symbolNumInString = len - 1 - digitNum; char theSymbol = s[symbolNumInString]; if (theSymbol >= '0' && theSymbol <= '9') blk[digitNum] = theSymbol - '0'; else if (theSymbol >= 'A' && theSymbol <= 'Z') blk[digitNum] = theSymbol - 'A' + 10; else if (theSymbol >= 'a' && theSymbol <= 'z') blk[digitNum] = theSymbol - 'a' + 10; else throw "BigUnsignedInABase(std::string, Base): Bad symbol in input. Only 0-9, A-Z, a-z are accepted."; if (blk[digitNum] >= base) throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base"; } zapLeadingZeros(); }
BigUnsignedInABase::BigUnsignedInABase(const Digit *d, Index l, Base base) : NumberlikeArray<Digit>(d, l), base(base) { // Check the base if (base < 2) throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): The base must be at least 2"; // Validate the digits. for (Index i = 0; i < l; i++) if (blk[i] >= base) throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base"; // Eliminate any leading zeros we may have been passed. zapLeadingZeros(); }
void BigUnsigned::subtract(const BigUnsigned &a, const BigUnsigned &b) { DTRT_ALIASED(this == &a || this == &b, subtract(a, b)); if (b.len == 0) { // If b is zero, copy a. operator =(a); return; } else if (a.len < b.len) // If a is shorter than b, the result is negative. throw "BigUnsigned::subtract: " "Negative result in unsigned calculation"; // Some variables... bool borrowIn, borrowOut; Blk temp; Index i; // Set preliminary length and make room len = a.len; allocate(len); // For each block index that is present in both inputs... for (i = 0, borrowIn = false; i < b.len; i++) { temp = a.blk[i] - b.blk[i]; // If a reverse rollover occurred, // the result is greater than the block from a. borrowOut = (temp > a.blk[i]); // Handle an incoming borrow if (borrowIn) { borrowOut |= (temp == 0); temp--; } blk[i] = 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++) { borrowIn = (a.blk[i] == 0); blk[i] = a.blk[i] - 1; } /* If there's still a borrow, the result is negative. * Throw an exception, but zero out this object so as to leave it in a * predictable state. */ 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++) blk[i] = a.blk[i]; // Zap leading zeros zapLeadingZeros(); }
void BigUnsigned::setBlock(Index i, Blk newBlock) { if (newBlock == 0) { if (i < len) { blk[i] = 0; zapLeadingZeros(); } // If i >= len, no effect. } else { if (i >= len) { // The nonzero block extends the number. allocateAndCopy(i+1); // Zero any added blocks that we aren't setting. for (Index j = len; j < i; j++) blk[j] = 0; len = i+1; } blk[i] = newBlock; } }