mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 09:53:36 +00:00
tests/accumulator/*.m:
tests/analysis_*/*.m:
tests/benchmarks*/*.m:
tests/debugger*/*.{m,exp,inp}:
tests/declarative_debugger*/*.{m,exp,inp}:
tests/dppd*/*.m:
tests/exceptions*/*.m:
tests/general*/*.m:
tests/grade_subdirs*/*.m:
tests/hard_coded*/*.m:
Make these tests use four-space indentation, and ensure that
each module is imported on its own line. (I intend to use the latter
to figure out which subdirectories' tests can be executed in parallel.)
These changes usually move code to different lines. For the debugger tests,
specify the new line numbers in .inp files and expect them in .exp files.
325 lines
11 KiB
Mathematica
325 lines
11 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%
|
|
% Test the array.[approx_]binary_search predicates.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module array_binsearch.
|
|
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module array.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
main(!IO) :-
|
|
SortedList = [1, 1, 1, 3, 3, 3, 5, 5, 7, 7, 8, 8, 10, 10, 11, 11,
|
|
13, 13, 13, 16, 16, 19, 20, 20, 21, 21, 23, 27, 28, 28, 28, 29, 31],
|
|
DistractedSortedList = [401, 1, 301, 403, 103, 303, 5, 5, 207, 307,
|
|
408, 108, 210, 10, 411, 311,
|
|
113, 213, 213, 316, 216, 319, 420, 220, 321, 121,
|
|
323, 227, 28, 228, 28, 29, 231],
|
|
Max = 32,
|
|
run_undistracted_tests(SortedList, Max, !IO),
|
|
run_distracted_tests(DistractedSortedList, Max, !IO).
|
|
|
|
:- func distraction_ordering(int, int) = comparison_result.
|
|
|
|
distraction_ordering(A, B) = R :-
|
|
UndistractedA = A rem 100,
|
|
UndistractedB = B rem 100,
|
|
R = ordering(UndistractedA, UndistractedB).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred run_undistracted_tests(list(int)::in, int::in, io::di, io::uo) is det.
|
|
|
|
run_undistracted_tests(SortedList, Max, !IO) :-
|
|
array.from_list(SortedList, Array),
|
|
io.write_string("Undistracted tests\n", !IO),
|
|
io.write(SortedList, !IO),
|
|
io.nl(!IO),
|
|
io.nl(!IO),
|
|
undistracted_exact_test_loop(Array, 0, Max, !IO),
|
|
undistracted_approx_test_loop(Array, 0, Max, !IO).
|
|
|
|
:- pred undistracted_exact_test_loop(array(int)::in, int::in, int::in,
|
|
io::di, io::uo) is det.
|
|
|
|
undistracted_exact_test_loop(Array, Cur, Max, !IO) :-
|
|
( if Cur > Max then
|
|
io.nl(!IO)
|
|
else
|
|
io.format("exact search for %3d ", [i(Cur)], !IO),
|
|
( if array.binary_search(ordering, Array, Cur, Index) then
|
|
( if
|
|
exact_verify_success(ordering, Array, Max, Cur, Index,
|
|
First, Last)
|
|
then
|
|
io.format("succeeds correctly at %3d", [i(Index)], !IO),
|
|
io.format(", first %3d, last %3d\n", [i(First), i(Last)], !IO)
|
|
else
|
|
io.format("succeeds INCORRECTLY at %3d\n", [i(Index)], !IO)
|
|
)
|
|
else
|
|
( if exact_verify_failure(ordering, Array, Max, Cur) then
|
|
io.format("fails correctly\n", [], !IO)
|
|
else
|
|
io.format("fails INCORRECTLY\n", [], !IO)
|
|
)
|
|
),
|
|
undistracted_exact_test_loop(Array, Cur + 1, Max, !IO)
|
|
).
|
|
|
|
:- pred undistracted_approx_test_loop(array(int)::in, int::in, int::in,
|
|
io::di, io::uo) is det.
|
|
|
|
undistracted_approx_test_loop(Array, Cur, Max, !IO) :-
|
|
( if Cur > Max then
|
|
io.nl(!IO)
|
|
else
|
|
io.format("approx search for %3d ", [i(Cur)], !IO),
|
|
( if
|
|
array.approx_binary_search(ordering, Array, Cur, Index)
|
|
then
|
|
( if
|
|
approx_verify_success(distraction_ordering, Array, Max, Cur,
|
|
Index, First, Last)
|
|
then
|
|
io.format("succeeds correctly at %3d", [i(Index)], !IO),
|
|
io.format(", first %3d, last %3d\n", [i(First), i(Last)], !IO)
|
|
else
|
|
io.format("succeeds INCORRECTLY at %3d\n", [i(Index)], !IO)
|
|
)
|
|
else
|
|
( if
|
|
approx_verify_failure(distraction_ordering, Array, Max, Cur)
|
|
then
|
|
io.format("fails correctly\n", [], !IO)
|
|
else
|
|
io.format("fails INCORRECTLY\n", [], !IO)
|
|
)
|
|
),
|
|
undistracted_approx_test_loop(Array, Cur + 1, Max, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred run_distracted_tests(list(int)::in, int::in, io::di, io::uo) is det.
|
|
|
|
run_distracted_tests(SortedList, Max, !IO) :-
|
|
array.from_list(SortedList, Array),
|
|
io.write_string("Distracted tests\n", !IO),
|
|
io.write(SortedList, !IO),
|
|
io.nl(!IO),
|
|
io.nl(!IO),
|
|
distracted_exact_test_loop(Array, 0, 0, Max, !IO),
|
|
distracted_exact_test_loop(Array, 1, 0, Max, !IO),
|
|
distracted_exact_test_loop(Array, 2, 0, Max, !IO),
|
|
distracted_exact_test_loop(Array, 3, 0, Max, !IO),
|
|
distracted_exact_test_loop(Array, 4, 0, Max, !IO),
|
|
distracted_approx_test_loop(Array, 0, 0, Max, !IO),
|
|
distracted_approx_test_loop(Array, 1, 0, Max, !IO),
|
|
distracted_approx_test_loop(Array, 2, 0, Max, !IO),
|
|
distracted_approx_test_loop(Array, 3, 0, Max, !IO),
|
|
distracted_approx_test_loop(Array, 4, 0, Max, !IO).
|
|
|
|
:- pred distracted_exact_test_loop(array(int)::in, int::in, int::in, int::in,
|
|
io::di, io::uo) is det.
|
|
|
|
distracted_exact_test_loop(Array, Distraction, Cur, Max, !IO) :-
|
|
( if Cur > Max then
|
|
io.nl(!IO)
|
|
else
|
|
DCur = Distraction * 100 + Cur,
|
|
io.format("exact search for %3d ", [i(DCur)], !IO),
|
|
( if
|
|
array.binary_search(distraction_ordering, Array, DCur, Index)
|
|
then
|
|
( if
|
|
exact_verify_success(distraction_ordering, Array, Max, DCur,
|
|
Index, First, Last)
|
|
then
|
|
io.format("succeeds correctly at %3d", [i(Index)], !IO),
|
|
io.format(", first %3d, last %3d\n", [i(First), i(Last)], !IO)
|
|
else
|
|
io.format("succeeds INCORRECTLY at %3d\n", [i(Index)], !IO)
|
|
)
|
|
else
|
|
( if
|
|
exact_verify_failure(distraction_ordering, Array, Max, DCur)
|
|
then
|
|
io.format("fails correctly\n", [], !IO)
|
|
else
|
|
io.format("fails INCORRECTLY\n", [], !IO)
|
|
)
|
|
),
|
|
distracted_exact_test_loop(Array, Distraction, Cur + 1, Max, !IO)
|
|
).
|
|
|
|
:- pred distracted_approx_test_loop(array(int)::in, int::in, int::in, int::in,
|
|
io::di, io::uo) is det.
|
|
|
|
distracted_approx_test_loop(Array, Distraction, Cur, Max, !IO) :-
|
|
( if Cur > Max then
|
|
io.nl(!IO)
|
|
else
|
|
DCur = Distraction * 100 + Cur,
|
|
io.format("approx search for %3d ", [i(DCur)], !IO),
|
|
( if
|
|
array.approx_binary_search(distraction_ordering, Array,
|
|
DCur, Index)
|
|
then
|
|
( if
|
|
approx_verify_success(distraction_ordering, Array, Max, DCur,
|
|
Index, First, Last)
|
|
then
|
|
io.format("succeeds correctly at %3d", [i(Index)], !IO),
|
|
io.format(", first %3d, last %3d\n", [i(First), i(Last)], !IO)
|
|
else
|
|
io.format("succeeds INCORRECTLY at %3d\n", [i(Index)], !IO)
|
|
)
|
|
else
|
|
( if
|
|
approx_verify_failure(distraction_ordering, Array, Max, DCur)
|
|
then
|
|
io.format("fails correctly\n", [], !IO)
|
|
else
|
|
io.format("fails INCORRECTLY\n", [], !IO)
|
|
)
|
|
),
|
|
distracted_approx_test_loop(Array, Distraction, Cur + 1, Max, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred exact_verify_success(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::in, int::out, int::out) is semidet.
|
|
|
|
exact_verify_success(Cmp, Array, Max, Value, FoundIndex,
|
|
FirstIndex, LastIndex) :-
|
|
array.lookup(Array, FoundIndex, ValueAtFoundIndex),
|
|
Cmp(ValueAtFoundIndex, Value) = Res,
|
|
Res = (=),
|
|
require_det (
|
|
exact_search_back(Cmp, Array, Value, FoundIndex, FirstIndex),
|
|
exact_search_forward(Cmp, Array, Max, Value, FoundIndex, LastIndex)
|
|
).
|
|
|
|
:- pred exact_search_back(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::out) is det.
|
|
|
|
exact_search_back(Cmp, Array, Value, CurIndex, FirstIndex) :-
|
|
% invariant: Array[CurIndex] = Value
|
|
NextIndex = CurIndex - 1,
|
|
( if NextIndex >= 0 then
|
|
array.lookup(Array, NextIndex, ValueAtNextIndex),
|
|
( if Cmp(ValueAtNextIndex, Value) = (=) then
|
|
exact_search_back(Cmp, Array, Value, NextIndex, FirstIndex)
|
|
else
|
|
FirstIndex = CurIndex
|
|
)
|
|
else
|
|
FirstIndex = CurIndex
|
|
).
|
|
|
|
:- pred exact_search_forward(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::in, int::out) is det.
|
|
|
|
exact_search_forward(Cmp, Array, Max, Value, CurIndex, LastIndex) :-
|
|
% invariant: Array[CurIndex] = Value
|
|
NextIndex = CurIndex + 1,
|
|
( if NextIndex < Max then
|
|
array.lookup(Array, NextIndex, ValueAtNextIndex),
|
|
( if Cmp(ValueAtNextIndex, Value) = (=) then
|
|
exact_search_forward(Cmp, Array, Max, Value, NextIndex, LastIndex)
|
|
else
|
|
LastIndex = CurIndex
|
|
)
|
|
else
|
|
LastIndex = CurIndex
|
|
).
|
|
|
|
:- pred exact_verify_failure(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in) is semidet.
|
|
|
|
exact_verify_failure(Cmp, Array, Max, Value) :-
|
|
exact_verify_failure_loop(Cmp, Array, 0, Max, Value).
|
|
|
|
:- pred exact_verify_failure_loop(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::in) is semidet.
|
|
|
|
exact_verify_failure_loop(Cmp, Array, Cur, Max, Value) :-
|
|
( if Cur = Max then
|
|
true
|
|
else
|
|
array.lookup(Array, Cur, CurValue),
|
|
Cmp(CurValue, Value) \= (=),
|
|
exact_verify_failure_loop(Cmp, Array, Cur + 1, Max, Value)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred approx_verify_success(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::in, int::out, int::out) is semidet.
|
|
|
|
approx_verify_success(Cmp, Array, Max, Value, FoundIndex,
|
|
FirstIndex, LastIndex) :-
|
|
array.lookup(Array, FoundIndex, ValueAtFoundIndex),
|
|
Cmp(ValueAtFoundIndex, Value) = Res,
|
|
(
|
|
Res = (=),
|
|
require_det (
|
|
exact_search_back(Cmp, Array, Value, FoundIndex, FirstIndex),
|
|
exact_search_forward(Cmp, Array, Max, Value, FoundIndex, LastIndex)
|
|
)
|
|
;
|
|
Res = (<),
|
|
require_det (
|
|
exact_search_back(Cmp, Array, ValueAtFoundIndex,
|
|
FoundIndex, FirstIndex),
|
|
exact_search_forward(Cmp, Array, Max, ValueAtFoundIndex,
|
|
FoundIndex, LastIndex)
|
|
),
|
|
FollowIndex = LastIndex + 1,
|
|
( if FollowIndex < Max then
|
|
array.lookup(Array, FollowIndex, ValueAtFollowIndex),
|
|
Cmp(Value, ValueAtFollowIndex) = (<)
|
|
else
|
|
true
|
|
)
|
|
).
|
|
|
|
:- pred approx_verify_failure(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in) is semidet.
|
|
|
|
approx_verify_failure(Cmp, Array, Max, Value) :-
|
|
approx_verify_failure_loop(Cmp, Array, 0, Max, Value).
|
|
|
|
:- pred approx_verify_failure_loop(comparison_func(int)::in, array(int)::in,
|
|
int::in, int::in, int::in) is semidet.
|
|
|
|
approx_verify_failure_loop(Cmp, Array, Cur, Max, Value) :-
|
|
( if Cur = Max then
|
|
true
|
|
else
|
|
array.lookup(Array, Cur, CurValue),
|
|
Cmp(CurValue, Value) = (>),
|
|
approx_verify_failure_loop(Cmp, Array, Cur + 1, Max, Value)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|