// Oldham, Jeffrey D. // 2000 Jan 16 // CS1321 // // Modified by: // Massingill, Berna L. // 2000 Feb 01 // // Test unary number class. // Tests primarily those functions students were required to write. // Compile with -DDEBUG for more verbose output. #include "unary.h" // ASSUMES the other file is called unary.h. #include #include // has EXIT_SUCCESS #include // Known-to-be-correct versions of iszero, add1, sub1 -- in case the // ones being tested are not correct. bool ISZERO(const natural & n) { return n.empty(); } natural ADD1(const natural & n) { return Seq(true, n); } natural SUB1(const natural &n) { assert (!ISZERO(n)); return n.tl(); } // // Functions to convert between integers and naturals. // // (What's this? Aren't we cheating? Wasn't this assignment supposed // to be done without integers?? Yes, it was. But now we are no // longer *implementing* this class (which is meant as a replacement // for integers on a computer that doesn't supply them), but *testing* // it -- and we could do the testing on a computer that *does* support // integers, and then port it to our hypothetical computer without // integers.) // natural make_natural(const int n) { assert (n >= 0); if (n == 0) return zero; else return ADD1(make_natural(n-1)); } int make_int(const natural & n) { return n.length(); } // Miscellaneous helper functions. int int_power(const int b, const int e) { assert (e >= 0); if (e == 0) return 1; else return b * int_power(b, e-1); } string bool2string(const bool b) { if (b) return "true"; else return "false"; } // Function to test iszero, add1, sub1. // Returns true if okay, false otherwise. bool testPrimitives(void) { #ifdef DEBUG cout << "In testPrimitives()\n"; #endif // DEBUG bool returnVal = true; if (!iszero(zero)) { cout << "Failed test: iszero(zero)\n"; returnVal = false; } if (iszero(ADD1(zero))) { cout << "Failed test: iszero(ADD1(zero))\n"; returnVal = false; } if (add1(zero).length() != 1) { cout << "Failed test: add1(zero))\n"; returnVal = false; } if (add1(add1(zero)).length() != 2) { cout << "Failed test: add1(add1(zero))\n"; returnVal = false; } if (!sub1(ADD1(zero)).empty()) { cout << "Failed test: sub1(ADD1(zero))\n"; returnVal = false; } if (sub1(ADD1(ADD1(zero))).length() != 1) { cout << "Failed test: sub1(ADD1(ADD1(zero)))\n"; returnVal = false; } return returnVal; } // Functions to test operators. // (Yes, these could probably be written more simply using function // parameters. We do it this way just to be sure the code to overload // operators in unary.h compiles as expected.) bool testAdd(const int i1, const int i2) { #ifdef DEBUG cout << "In testAdd() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); natural result = n1 + n2; int i_result = i1 + i2; if (make_int(result) == i_result) return true; cout << "Failed test: " << i1 << " + " << i2 << ": result = " << make_int(result) << " (should be " << i_result << ")" << endl; return false; } bool testSubtract(const int i1, const int i2) { #ifdef DEBUG cout << "In testSubtract() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); natural result = n1 - n2; int i_result = i1 - i2; if (make_int(result) == i_result) return true; cout << "Failed test: " << i1 << " - " << i2 << ": result = " << make_int(result) << " (should be " << i_result << ")" << endl; return false; } bool testMultiply(const int i1, const int i2) { #ifdef DEBUG cout << "In testMultiply() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); natural result = n1 * n2; int i_result = i1 * i2; if (make_int(result) == i_result) return true; cout << "Failed test: " << i1 << " * " << i2 << ": result = " << make_int(result) << " (should be " << i_result << ")" << endl; return false; } bool testDivide(const int i1, const int i2) { #ifdef DEBUG cout << "In testDivide() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); natural result = n1 / n2; int i_result = i1 / i2; if (make_int(result) == i_result) return true; cout << "Failed test: " << i1 << " / " << i2 << ": result = " << make_int(result) << " (should be " << i_result << ")" << endl; return false; } bool testExponentiate(const int i1, const int i2) { #ifdef DEBUG cout << "In testExponentiate() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); natural result = n1 ^ n2; int i_result = int_power(i1, i2); if (make_int(result) == i_result) return true; cout << "Failed test: " << i1 << " ^ " << i2 << ": result = " << make_int(result) << " (should be " << i_result << ")" << endl; return false; } bool testLT(const int i1, const int i2) { #ifdef DEBUG cout << "In testLT() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 < n2; if (result == (i1 < i2)) return true; cout << "Failed test: " << i1 << " < " << i2 << ": result = " << bool2string(result) << endl; return false; } bool testGT(const int i1, const int i2) { #ifdef DEBUG cout << "In testGT() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 > n2; if (result == (i1 > i2)) return true; cout << "Failed test: " << i1 << " > " << i2 << ": result = " << bool2string(result) << endl; return false; } bool testEQ(const int i1, const int i2) { #ifdef DEBUG cout << "In testEQ() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 == n2; if (result == (i1 == i2)) return true; cout << "Failed test: " << i1 << " == " << i2 << ": result = " << bool2string(result) << endl; return false; } bool testNE(const int i1, const int i2) { #ifdef DEBUG cout << "In testNE() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 != n2; if (result == (i1 != i2)) return true; cout << "Failed test: " << i1 << " != " << i2 << ": result = " << bool2string(result) << endl; return false; } bool testLE(const int i1, const int i2) { #ifdef DEBUG cout << "In testLE() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 <= n2; if (result == (i1 <= i2)) return true; cout << "Failed test: " << i1 << " <= " << i2 << ": result = " << bool2string(result) << endl; return false; } bool testGE(const int i1, const int i2) { #ifdef DEBUG cout << "In testGE() for " << i1 << ", " << i2 << "\n"; #endif // DEBUG natural n1 = make_natural(i1); natural n2 = make_natural(i2); bool result = n1 >= n2; if (result == (i1 >= i2)) return true; cout << "Failed test: " << i1 << " >= " << i2 << ": result = " << bool2string(result) << endl; return false; } // Function to test one complicated arithmetic expression. bool testExpression(void) { #ifdef DEBUG cout << "In testExpression()\n"; #endif // DEBUG int c4 = 4; int c5 = 5; int c2 = 2; int c1 = 1; int i_result = (c4 * c5 + c5 / c2 - int_power(c4, c1)) / c2; natural n4 = make_natural(4); natural n5 = make_natural(5); natural n2 = make_natural(2); natural n1 = make_natural(1); natural n_result = (n4 * n5 + n5 / n2 - (n4 ^ n1)) / n2; if (i_result == make_int(n_result)) return true; cout << "Failed complicated expression test: result = " << make_int(n_result) << " (should be " << i_result << ")" << endl; return false; } // Main program. // This program requires no input data. It tests the student-provided // functions in unary.h and reports on their correctness. int main(void) { bool returnVal = true; // test primitives first returnVal = testPrimitives() && returnVal; // test simple arithmetic, small numbers returnVal = testAdd(0, 2) && returnVal; returnVal = testAdd(2, 0) && returnVal; returnVal = testAdd(2, 1) && returnVal; returnVal = testAdd(3, 4) && returnVal; returnVal = testSubtract(1, 0) && returnVal; returnVal = testSubtract(2, 0) && returnVal; returnVal = testSubtract(2, 1) && returnVal; returnVal = testSubtract(5, 2) && returnVal; returnVal = testMultiply(2, 0) && returnVal; returnVal = testMultiply(0, 2) && returnVal; returnVal = testMultiply(2, 1) && returnVal; returnVal = testMultiply(1, 2) && returnVal; returnVal = testMultiply(2, 3) && returnVal; returnVal = testDivide(0, 1) && returnVal; returnVal = testDivide(1, 1) && returnVal; returnVal = testDivide(1, 2) && returnVal; returnVal = testDivide(4, 2) && returnVal; returnVal = testDivide(2, 4) && returnVal; returnVal = testDivide(5, 2) && returnVal; returnVal = testExponentiate(0, 1) && returnVal; returnVal = testExponentiate(1, 0) && returnVal; returnVal = testExponentiate(2, 0) && returnVal; returnVal = testExponentiate(3, 2) && returnVal; returnVal = testExponentiate(2, 3) && returnVal; // test relational operators, small numbers returnVal = testLT(0, 2) && returnVal; returnVal = testLT(2, 0) && returnVal; returnVal = testLT(2, 3) && returnVal; returnVal = testLT(3, 2) && returnVal; returnVal = testLT(0, 0) && returnVal; returnVal = testLT(2, 2) && returnVal; returnVal = testGT(0, 2) && returnVal; returnVal = testGT(2, 0) && returnVal; returnVal = testGT(2, 3) && returnVal; returnVal = testGT(3, 2) && returnVal; returnVal = testGT(0, 0) && returnVal; returnVal = testGT(2, 2) && returnVal; returnVal = testEQ(0, 2) && returnVal; returnVal = testEQ(2, 0) && returnVal; returnVal = testEQ(2, 3) && returnVal; returnVal = testEQ(3, 2) && returnVal; returnVal = testEQ(0, 0) && returnVal; returnVal = testEQ(2, 2) && returnVal; returnVal = testNE(0, 2) && returnVal; returnVal = testNE(2, 0) && returnVal; returnVal = testNE(2, 3) && returnVal; returnVal = testNE(3, 2) && returnVal; returnVal = testNE(0, 0) && returnVal; returnVal = testNE(2, 2) && returnVal; returnVal = testLE(0, 2) && returnVal; returnVal = testLE(2, 0) && returnVal; returnVal = testLE(2, 3) && returnVal; returnVal = testLE(3, 2) && returnVal; returnVal = testLE(0, 0) && returnVal; returnVal = testLE(2, 2) && returnVal; returnVal = testGE(0, 2) && returnVal; returnVal = testGE(2, 0) && returnVal; returnVal = testGE(2, 3) && returnVal; returnVal = testGE(3, 2) && returnVal; returnVal = testGE(0, 0) && returnVal; returnVal = testGE(2, 2) && returnVal; // test arithmetic operators, bigger numbers returnVal = testAdd(2345, 10000-2345) && returnVal; returnVal = testSubtract(10000, 5432) && returnVal; returnVal = testMultiply(1234, 10000/1234) && returnVal; returnVal = testDivide(10000, 23) && returnVal; returnVal = testExponentiate(4, 6) && returnVal; // test relational operators, bigger numbers returnVal = testLT(10000, 10002) && returnVal; returnVal = testGT(10000, 10002) && returnVal; returnVal = testEQ(10000, 10002) && returnVal; returnVal = testNE(10000, 10002) && returnVal; returnVal = testLE(10000, 10002) && returnVal; returnVal = testGE(10000, 10002) && returnVal; // test one complicated expression returnVal = testExpression() && returnVal; if (returnVal) cout << "Perfect score! Congratulations!\n"; return EXIT_SUCCESS; }