diff --git a/tests/hard_coded/integer_division_zero.m b/tests/hard_coded/integer_division_zero.m index e07e93c69..2e6052732 100644 --- a/tests/hard_coded/integer_division_zero.m +++ b/tests/hard_coded/integer_division_zero.m @@ -23,77 +23,90 @@ :- import_module string. main(!IO) :- - check("canonical exact remainder", - ((pred) is semidet :- - build_check_exponent_offset_shift_rem(27, 0, 28, integer.zero) - ), !IO), - check("canonical nonzero remainder", - ((pred) is semidet :- - build_check_exponent_offset_shift_rem(27, 0, 28, integer.one) - ), !IO), - check("significant digits after zero partial remainder", - ((pred) is semidet :- - B = integer.one << 27, - build_check_signed_variants((B << 70) + B + integer.one, B, - (integer.one << 70) + integer.one, integer.one) - ), !IO), - check("scaled and unscaled divisors", - ((pred) is semidet :- - list.all_true(build_check_exponent_values, - [13, 14, 15, 26, 27, 28, 41, 55, 83]) - ), !IO), - check("zero and small dividends", - ((pred) is semidet :- - B = integer.one << 55, - build_check_signed_variants(integer.zero, B, integer.zero, - integer.zero), - build_check_signed_variants(integer.one, B, integer.zero, - integer.one), - build_check_signed_variants(B - integer.one, B, integer.zero, - B - integer.one) - ), !IO). + Zero = integer.zero, + One = integer.one, -:- pred build_check_exponent_values(int::in) is semidet. + build_check_exponent_offset_shift_rem(27, 0, 28, Zero, + [], ExactFails), + report_results("canonical exact remainder", ExactFails, !IO), -build_check_exponent_values(Exponent) :- - list.all_true( - (pred(Offset::in) is semidet :- + build_check_exponent_offset_shift_rem(27, 0, 28, One, + [], NonZeroFails), + report_results("canonical nonzero remainder", NonZeroFails, !IO), + + Shift27 = integer.one << 27, + build_check_signed_variants((Shift27 << 70) + Shift27 + integer.one, + Shift27, (integer.one << 70) + integer.one, integer.one, + [], DigitFails), + report_results("significant digits after zero partial remainder", + DigitFails, !IO), + + list.foldl(build_check_exponent_values, + [13, 14, 15, 26, 27, 28, 41, 55, 83], + [], ScaledFails), + report_results("scaled and unscaled divisors", ScaledFails, !IO), + + Shift55 = integer.one << 55, + build_check_signed_variants(Zero, Shift55, Zero, Zero, + [], ZeroSmallFails1), + build_check_signed_variants(One, Shift55, Zero, One, + ZeroSmallFails1, ZeroSmallFails2), + build_check_signed_variants(Shift55 - One, Shift55, Zero, Shift55 - One, + ZeroSmallFails2, ZeroSmallFails), + report_results("zero and small dividends", ZeroSmallFails, !IO). + +%---------------------------------------------------------------------------% + +:- pred build_check_exponent_values(int::in, + list(a_b_q_r)::in, list(a_b_q_r)::out) is det. + +build_check_exponent_values(Exponent, !Fails) :- + list.foldl(build_check_exponent_offset_values(Exponent), + [-1, 0, 1], !Fails). + +:- pred build_check_exponent_offset_values(int::in, int::in, + list(a_b_q_r)::in, list(a_b_q_r)::out) is det. + +build_check_exponent_offset_values(Exponent, Offset, !Fails) :- + list.foldl(build_check_exponent_offset_shift_values(Exponent, Offset), + [1, 14, 28, 56], !Fails). + +:- pred build_check_exponent_offset_shift_values(int::in, int::in, int::in, + list(a_b_q_r)::in, list(a_b_q_r)::out) is det. + +build_check_exponent_offset_shift_values(Exponent, Offset, Shift, !Fails) :- B = (integer.one << Exponent) + integer(Offset), - list.all_true( - (pred(Shift::in) is semidet :- - list.all_true( - (pred(R::in) is semidet :- - build_check_exponent_offset_shift_rem(Exponent, - Offset, Shift, R)), - [integer.zero, integer.one, B - integer.one]) - ), - [1, 14, 28, 56]) - ), - [-1, 0, 1]). + list.foldl(build_check_exponent_offset_shift_rem(Exponent, Offset, Shift), + [integer.zero, integer.one, B - integer.one], !Fails). :- pred build_check_exponent_offset_shift_rem(int::in, int::in, int::in, - integer::in) is semidet. + integer::in, list(a_b_q_r)::in, list(a_b_q_r)::out) is det. -build_check_exponent_offset_shift_rem(Exponent, Offset, Shift, R) :- +build_check_exponent_offset_shift_rem(Exponent, Offset, Shift, R, !Fails) :- B = (integer.one << Exponent) + integer(Offset), Q = integer.one << Shift, A = B * Q + R, - build_check_signed_variants(A, B, Q, R). + build_check_signed_variants(A, B, Q, R, !Fails). + +%---------------------------------------------------------------------------% :- pred build_check_signed_variants(integer::in, integer::in, - integer::in, integer::in) is semidet. + integer::in, integer::in, list(a_b_q_r)::in, list(a_b_q_r)::out) is det. -build_check_signed_variants(A, B, Q, R) :- - check_division(A, B, Q, R), - check_division(-A, B, -Q, -R), - check_division(A, -B, -Q, R), - check_division(-A, -B, Q, -R). +build_check_signed_variants(A, B, Q, R, !Fails) :- + check_division(A, B, Q, R, !Fails), + check_division(-A, B, -Q, -R, !Fails), + check_division(A, -B, -Q, R, !Fails), + check_division(-A, -B, Q, -R, !Fails). -:- pred check_division(integer::in, integer::in, integer::in, integer::in) - is semidet. +%---------------------------------------------------------------------------% -check_division(A, B, ExpectedQ, ExpectedR) :- +:- pred check_division(integer::in, integer::in, integer::in, integer::in, + list(a_b_q_r)::in, list(a_b_q_r)::out) is det. + +check_division(A, B, ExpectedQ, ExpectedR, !Fails) :- integer.divide_with_rem(A, B, Q, R), + ( if Q = ExpectedQ, R = ExpectedR, A // B = ExpectedQ, @@ -120,14 +133,38 @@ check_division(A, B, ExpectedQ, ExpectedR) :- else A div B = ExpectedQ, A mod B = ExpectedR - ). - -:- pred check(string::in, (pred)::in((pred) is semidet), - io::di, io::uo) is det. - -check(Label, Test, !IO) :- - ( if Test then - io.write_string("PASS " ++ Label ++ "\n", !IO) + ) + then + true else - io.write_string("FAIL " ++ Label ++ "\n", !IO) + !:Fails = [a_b_q_r(A, B, Q, R) | !.Fails] ). + +%---------------------------------------------------------------------------% + +:- type a_b_q_r + ---> a_b_q_r(integer, integer, integer, integer). + +:- pred report_results(string::in, list(a_b_q_r)::in, io::di, io::uo) is det. + +report_results(Label, Fails, !IO) :- + ( + Fails = [], + io.write_string("PASS " ++ Label ++ "\n", !IO) + ; + Fails = [_ | _], + io.write_string("FAIL " ++ Label ++ "\n", !IO), + list.foldl(write_a_b_q_r, Fails, !IO) + ). + +:- pred write_a_b_q_r(a_b_q_r::in, io::di, io::uo) is det. + +write_a_b_q_r(a_b_q_r(A, B, Q, R), !IO) :- + AStr = integer.to_string(A), + BStr = integer.to_string(B), + QStr = integer.to_string(Q), + RStr = integer.to_string(R), + io.format("a_b_q_r(%s, %s, %s, %s)\n", + [s(AStr), s(BStr), s(QStr), s(RStr)], !IO). + +%---------------------------------------------------------------------------%