X-Git-Url: https://mattmccutchen.net/bigint/bigint.git/blobdiff_plain/3e1327901d299a537a8d932c49dd330f87ac3bda..refs/heads/no-explicit-template-args:/BigInteger.cc diff --git a/BigInteger.cc b/BigInteger.cc index 2651ab7..dac50d9 100644 --- a/BigInteger.cc +++ b/BigInteger.cc @@ -13,11 +13,18 @@ void BigInteger::operator =(const BigInteger &x) { BigInteger::BigInteger(const Blk *b, Index blen, Sign s) : mag(b, blen) { switch (s) { case zero: + if (!mag.isZero()) + throw "BigInteger::BigInteger(const Blk *, Index, Sign): Cannot use a sign of zero with a nonzero magnitude"; + sign = zero; + break; case positive: case negative: + // If the magnitude is zero, force the sign to zero. sign = mag.isZero() ? zero : s; break; default: + /* g++ seems to be optimizing out this case on the assumption + * that the sign is a valid member of the enumeration. Oh well. */ throw "BigInteger::BigInteger(const Blk *, Index, Sign): Invalid sign"; } } @@ -25,12 +32,19 @@ BigInteger::BigInteger(const Blk *b, Index blen, Sign s) : mag(b, blen) { BigInteger::BigInteger(const BigUnsigned &x, Sign s) : mag(x) { switch (s) { case zero: + if (!mag.isZero()) + throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Cannot use a sign of zero with a nonzero magnitude"; + sign = zero; + break; case positive: case negative: + // If the magnitude is zero, force the sign to zero. sign = mag.isZero() ? zero : s; break; default: - throw "BigInteger::BigInteger(Blk *, Index, Sign): Invalid sign"; + /* g++ seems to be optimizing out this case on the assumption + * that the sign is a valid member of the enumeration. Oh well. */ + throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Invalid sign"; } } @@ -39,15 +53,9 @@ BigInteger::BigInteger(const BigUnsigned &x, Sign s) : mag(x) { * negative BigInteger instead of an exception. */ // Done longhand to let us use initialization. -BigInteger::BigInteger(unsigned long x) : mag(x) { - sign = mag.isZero() ? zero : positive; -} -BigInteger::BigInteger(unsigned int x) : mag(x) { - sign = mag.isZero() ? zero : positive; -} -BigInteger::BigInteger(unsigned short x) : mag(x) { - sign = mag.isZero() ? zero : positive; -} +BigInteger::BigInteger(unsigned long x) : mag(x) { sign = mag.isZero() ? zero : positive; } +BigInteger::BigInteger(unsigned int x) : mag(x) { sign = mag.isZero() ? zero : positive; } +BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; } // For signed input, determine the desired magnitude and sign separately. @@ -66,12 +74,9 @@ namespace { } } -BigInteger::BigInteger(long x) : sign(signOf(x)), - mag(magOf(x)) {} -BigInteger::BigInteger(int x) : sign(signOf(x)), - mag(magOf(x)) {} -BigInteger::BigInteger(short x) : sign(signOf(x)), - mag(magOf(x)) {} +BigInteger::BigInteger(long x) : sign(signOf(x)), mag(magOf(x)) {} +BigInteger::BigInteger(int x) : sign(signOf(x)), mag(magOf(x)) {} +BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf(x)) {} // CONVERSION TO PRIMITIVE INTEGERS @@ -80,23 +85,23 @@ BigInteger::BigInteger(short x) : sign(signOf(x)), * BigInteger::convertToUnsignedPrimitive to avoid requiring BigUnsigned to * declare BigInteger. */ template -inline X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a) { - return a.convertToPrimitive(); +inline X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a, X dummyX) { + return a.convertToPrimitive(dummyX); } template -X BigInteger::convertToUnsignedPrimitive() const { +X BigInteger::convertToUnsignedPrimitive(X dummyX) const { if (sign == negative) throw "BigInteger::to: " "Cannot convert a negative integer to an unsigned type"; else - return convertBigUnsignedToPrimitiveAccess(mag); + return convertBigUnsignedToPrimitiveAccess(mag, dummyX); } /* Similar to BigUnsigned::convertToPrimitive, but split into two cases for * nonnegative and negative numbers. */ template -X BigInteger::convertToSignedPrimitive() const { +X BigInteger::convertToSignedPrimitive(X /*dummyX*/, UX /*dummyUX*/) const { if (sign == zero) return 0; else if (mag.getLength() == 1) { @@ -119,24 +124,12 @@ X BigInteger::convertToSignedPrimitive() const { "Value is too big to fit in the requested type"; } -unsigned long BigInteger::toUnsignedLong() const { - return convertToUnsignedPrimitive(); -} -unsigned int BigInteger::toUnsignedInt() const { - return convertToUnsignedPrimitive(); -} -unsigned short BigInteger::toUnsignedShort() const { - return convertToUnsignedPrimitive(); -} -long BigInteger::toLong() const { - return convertToSignedPrimitive(); -} -int BigInteger::toInt() const { - return convertToSignedPrimitive(); -} -short BigInteger::toShort() const { - return convertToSignedPrimitive(); -} +unsigned long BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive((unsigned long )0) ; } +unsigned int BigInteger::toUnsignedInt () const { return convertToUnsignedPrimitive((unsigned int )0) ; } +unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive((unsigned short)0) ; } +long BigInteger::toLong () const { return convertToSignedPrimitive ((long )0, (unsigned long )0); } +int BigInteger::toInt () const { return convertToSignedPrimitive ((int )0, (unsigned int )0); } +short BigInteger::toShort () const { return convertToSignedPrimitive ((short)0, (unsigned short)0); } // COMPARISON BigInteger::CmpRes BigInteger::compareTo(const BigInteger &x) const {