From cb2f0c288d4b7acfa37d7a9c8bc1024c3f332b5f Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Thu, 17 Jul 2008 07:44:27 -0400 Subject: [PATCH] - Fix a sign-checking bug in the BigInteger(..., Sign) constructors. - Add some tests of constructors, including one for the aforementioned bug. - Improve some comments. --- BigInteger.cc | 16 +++++++++++++++- testsuite.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/BigInteger.cc b/BigInteger.cc index 56f30ab..3b23aa1 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"; } } diff --git a/testsuite.cc b/testsuite.cc index 8d31eda..7817e9a 100644 --- a/testsuite.cc +++ b/testsuite.cc @@ -60,6 +60,32 @@ TEST(10); //10 TEST(check(BigUnsigned())); //0 TEST(check(BigInteger())); //0 +// === Block-array constructors === + +BigUnsigned::Blk myBlocks[3]; +myBlocks[0] = 3; +myBlocks[1] = 4; +myBlocks[2] = 0; +BigUnsigned bu(myBlocks, 3); +TEST(check(bu)); //17179869187 +TEST(check(BigInteger(myBlocks, 3))); //17179869187 +TEST(check(BigInteger(bu ))); //17179869187 + +// For nonzero magnitude, reject zero and invalid signs. +TEST(check(BigInteger(myBlocks, 3, BigInteger::positive))); //17179869187 +TEST(check(BigInteger(myBlocks, 3, BigInteger::negative))); //-17179869187 +TEST(check(BigInteger(myBlocks, 3, BigInteger::zero ))); //error +TEST(check(BigInteger(bu, BigInteger::positive))); //17179869187 +TEST(check(BigInteger(bu, BigInteger::negative))); //-17179869187 +TEST(check(BigInteger(bu, BigInteger::zero ))); //error + +// For zero magnitude, force the sign to zero without error. +BigUnsigned::Blk myZeroBlocks[1]; +myZeroBlocks[0] = 0; +TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::positive))); //0 +TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::negative))); //0 +TEST(check(BigInteger(myZeroBlocks, 1, BigInteger::zero ))); //0 + // === BigUnsigned conversion limits === TEST(BigUnsigned(0).toUnsignedLong()); //0 -- 2.34.1