BigUnsignedInABase(std::string): Reject digits too big for the base.
[bigint/bigint.git] / testsuite.cc
index a831fbc..7cb9768 100644 (file)
@@ -55,11 +55,39 @@ TEST(10); //10
 
 // TODO: Comprehensively test the general and special cases of each function.
 
-// Default constructors
+// === Default constructors ===
+
 TEST(check(BigUnsigned())); //0
 TEST(check(BigInteger())); //0
 
-// BigUnsigned conversion limits
+// === 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
 TEST(BigUnsigned(4294967295U).toUnsignedLong()); //4294967295
 TEST(stringToBigUnsigned("4294967296").toUnsignedLong()); //error
@@ -85,7 +113,8 @@ TEST(BigUnsigned(0).toShort()); //0
 TEST(BigUnsigned(32767).toShort()); //32767
 TEST(BigUnsigned(32768).toShort()); //error
 
-// BigInteger conversion limits
+// === BigInteger conversion limits ===
+
 TEST(BigInteger(-1).toUnsignedLong()); //error
 TEST(BigInteger(0).toUnsignedLong()); //0
 TEST(BigInteger(4294967295U).toUnsignedLong()); //4294967295
@@ -123,7 +152,8 @@ TEST(BigInteger(0).toShort()); //0
 TEST(BigInteger(32767).toShort()); //32767
 TEST(BigInteger(32768).toShort()); //error
 
-// Negative BigUnsigneds
+// === Negative BigUnsigneds ===
+
 // ...during construction
 TEST(BigUnsigned(short(-1))); //error
 TEST(BigUnsigned(pathologicalShort)); //error
@@ -131,6 +161,7 @@ TEST(BigUnsigned(-1)); //error
 TEST(BigUnsigned(pathologicalInt)); //error
 TEST(BigUnsigned(long(-1))); //error
 TEST(BigUnsigned(pathologicalLong)); //error
+
 // ...during subtraction
 TEST(BigUnsigned(5) - BigUnsigned(6)); //error
 TEST(stringToBigUnsigned("314159265358979323") - stringToBigUnsigned("314159265358979324")); //error
@@ -138,7 +169,8 @@ TEST(check(BigUnsigned(5) - BigUnsigned(5))); //0
 TEST(check(stringToBigUnsigned("314159265358979323") - stringToBigUnsigned("314159265358979323"))); //0
 TEST(check(stringToBigUnsigned("4294967296") - BigUnsigned(1))); //4294967295
 
-// Addition
+// === BigUnsigned addition ===
+
 TEST(check(BigUnsigned(0) + 0)); //0
 TEST(check(BigUnsigned(0) + 1)); //1
 // Ordinary carry
@@ -147,7 +179,8 @@ TEST(check(stringToBigUnsigned("8589934591" /* 2^33 - 1*/)
 // Creation of a new block
 TEST(check(BigUnsigned(0xFFFFFFFFU) + 1)); //4294967296
 
-// Subtraction
+// === BigUnsigned subtraction ===
+
 TEST(check(BigUnsigned(1) - 0)); //1
 TEST(check(BigUnsigned(1) - 1)); //0
 TEST(check(BigUnsigned(2) - 1)); //1
@@ -157,7 +190,8 @@ TEST(check(stringToBigUnsigned("12884901889")
 // Borrow that removes a block
 TEST(check(stringToBigUnsigned("4294967296") - 1)); //4294967295
 
-// Multiplication and division
+// === BigUnsigned multiplication and division ===
+
 BigUnsigned a = check(BigUnsigned(314159265) * 358979323);
 TEST(a); //112776680263877595
 TEST(a / 123); //916883579381118
@@ -165,6 +199,60 @@ TEST(a % 123); //81
 
 TEST(BigUnsigned(5) / 0); //error
 
+// === Block accessors ===
+
+BigUnsigned b;
+TEST(b); //0
+TEST(b.getBlock(0)); //0
+b.setBlock(1, 314);
+// Did b grow properly?  And did we zero intermediate blocks?
+TEST(check(b)); //1348619730944
+TEST(b.getLength()); //2
+TEST(b.getBlock(0)); //0
+TEST(b.getBlock(1)); //314
+// Did b shrink properly?
+b.setBlock(1, 0);
+TEST(check(b)); //0
+
+BigUnsigned bb(314);
+bb.setBlock(1, 159);
+// Make sure we used allocateAndCopy, not allocate
+TEST(bb.getBlock(0)); //314
+TEST(bb.getBlock(1)); //159
+// Blocks beyond the number should be zero regardless of whether they are
+// within the capacity.
+bb.add(1, 2);
+TEST(bb.getBlock(0)); //3
+TEST(bb.getBlock(1)); //0
+TEST(bb.getBlock(2)); //0
+TEST(bb.getBlock(314159)); //0
+
+// === Bit accessors ===
+
+TEST(BigUnsigned(0).bitLength()); //0
+TEST(BigUnsigned(1).bitLength()); //1
+TEST(BigUnsigned(4095).bitLength()); //12
+TEST(BigUnsigned(4096).bitLength()); //13
+// 5 billion is between 2^32 (about 4 billion) and 2^33 (about 8 billion).
+TEST(stringToBigUnsigned("5000000000").bitLength()); //33
+
+// 25 is binary 11001.
+BigUnsigned bbb(25);
+TEST(bbb.getBit(4)); //1
+TEST(bbb.getBit(3)); //1
+TEST(bbb.getBit(2)); //0
+TEST(bbb.getBit(1)); //0
+TEST(bbb.getBit(0)); //1
+TEST(bbb.bitLength()); //5
+// Effectively add 2^32.
+bbb.setBit(32, true);
+TEST(bbb); //4294967321
+bbb.setBit(31, true);
+bbb.setBit(32, false);
+TEST(check(bbb)); //2147483673
+
+// === Combining BigUnsigned, BigInteger, and primitive integers ===
+
 BigUnsigned p1 = BigUnsigned(3) * 5;
 TEST(p1); //15
 /* In this case, we would like g++ to implicitly promote the BigUnsigned to a
@@ -177,6 +265,8 @@ TEST(p1); //15
 BigInteger p2 = BigInteger(BigUnsigned(3)) * -5;
 TEST(p2); //-15
 
+// === Test some previous bugs ===
+
 {
        /* Test that BigInteger division sets the sign to zero.
         * Bug reported by David Allen. */
@@ -221,6 +311,13 @@ TEST(p2); //-15
        TEST(check(num)); //25
 }
 
+{
+       /* Test that BigUnsignedInABase(std::string) constructor rejects digits
+        * too big for the specified base.
+        * Bug reported by Niakam Kazemi. */
+       TEST(BigUnsignedInABase("f", 10)); //error
+}
+
 } catch (const char *err) {
        cout << "UNCAUGHT ERROR: " << err << endl;
 }