Commit 8bfe4cbb authored by Ari Trachtenberg's avatar Ari Trachtenberg
Browse files

Adding additional corner cases.

parent 3a5a8234
Loading
Loading
Loading
Loading
+47 −15
Original line number Diff line number Diff line
// -------------------- Corner cases: representation of 1 and trailing zeros --------------------
bool test_9() {
    const char* T = "Corner: multiple representations of 1";

    IntegerP one_default;

    // These also represent 1 mathematically, but internal vectors differ.
    IntegerP one_zero_list({0});
    IntegerP one_many_zeros({0,0,0});
    IntegerP empty({});

    // All should truncate to 1
    if (one_default.trunc() != 1) return failExample(T, "default one trunc()","1",to_string(one_default.trunc()));
    if (one_zero_list.trunc() != 1) return failExample(T, "IntegerP({0}).trunc()","1",to_string(one_zero_list.trunc()));
    if (one_many_zeros.trunc() != 1) return failExample(T, "IntegerP({0,0,0}).trunc()","1",to_string(one_many_zeros.trunc()));
    if (empty.trunc() != 1) return failExample(T, "IntegerP({}).trunc()","1",to_string(empty.trunc()));

    // Check equality of 1's
    if (!(one_zero_list==one_many_zeros)) return failExample(T, "{0}=={0,0,0}", 1, one_many_zeros==one_many_zeros);
    if (!(one_zero_list==empty)) return failExample(T, "{0}=={}", 1, one_zero_list==empty);
    if (!(one_many_zeros==empty)) return failExample(T, "{0,0,0}=={}", 1, one_many_zeros==empty);

    return true;
}

// -------------------- Corner cases: identity element through operations --------------------
bool test_10() {
  const char* T = "Trunc overflow/underflow";
    const char* T = "Corner: identity element via * and / with 1";

    IntegerP one_default;                // empty vector in your implementation
    IntegerP one_zero_list({0});         // vector {0}
    IntegerP x = IntegerP::valueOf(30);  // 30 = 2 * 3 * 5

  // Huge positive exponent: 2^20000 is astronomically large; trunc likely becomes inf
  RationalP huge_pos({20000});
  long double v1 = huge_pos.trunc();
    // Multiplying by 1 should keep the value
    IntegerP p1 = x * one_default;
    if (p1.trunc() != 30) return failExample(T, "x * one_default trunc()","30",to_string(p1.trunc()));

  if (v1 < 0)
    return failExample(T, "2^20000 trunc() should not be negative","non-negative",to_string(v1));
    IntegerP p2 = x * one_zero_list;
    if (p2.trunc() != 30) return failExample(T, "x * IntegerP({0}) trunc()","30",to_string(p2.trunc()));

  // Huge negative exponent: 2^-20000 ~ 0; trunc may underflow to 0
  RationalP huge_neg({-20000});
  long double v2 = huge_neg.trunc();
    // Dividing by 1 should keep the value
    IntegerP q1 = x / one_default;
    if (q1.trunc() != 30) return failExample(T, "x / one_default trunc()","30",to_string(q1.trunc()));

  if (v2 < 0)
    return failExample(T, "2^-20000 trunc() should not be negative","non-negative",to_string(v2));
    IntegerP q2 = x / one_zero_list;
    if (q2.trunc() != 30) return failExample(T, "x / IntegerP({0}) trunc()","30",to_string(q2.trunc()));

  RationalP prod = huge_pos * huge_neg;
  if (!approxEq(prod.trunc(), 1.0L))
    return failExample(T, "(2^20000)*(2^-20000) trunc()","1",to_string(prod.trunc()));
    // Also check divisibleBy(1) is true for both representations of 1
    if (!x.divisibleBy(one_default))
        return failExample(T, "x.divisibleBy(one_default)","true","false");
    if (!x.divisibleBy(one_zero_list))
        return failExample(T, "x.divisibleBy(IntegerP({0}))","true","false");

    return true;
}