Files
mercury/tests/hard_coded/rtree_test.m
2020-10-03 17:43:38 +10:00

224 lines
5.7 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
:- module rtree_test.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module bool.
:- import_module float.
:- import_module int.
:- import_module list.
:- import_module math.
:- import_module rtree.
:- import_module std_util.
:- import_module string.
%---------------------------------------------------------------------------%
:- type irtree == rtree(interval, int).
%---------------------------------------------------------------------------%
main(!IO) :-
some [!RTree] (
!:RTree = rtree.init,
add_integers(0, 100, !RTree),
% Find all integers between 33.0 and 66.0.
some [!Is] (
!:Is = rtree.search_intersects(!.RTree, interval(33.0, 66.0)),
list.sort(!Is),
io.write_string("Integers from 33 to 66:\n", !IO),
io.write(!.Is, !IO),
io.nl(!IO),
io.nl(!IO)
),
% Find integer 22.
some [!Is] (
!:Is = rtree.search_intersects(!.RTree, interval(22.0, 22.0)),
io.write_string("Integers from 22 to 22:\n", !IO),
io.write(!.Is, !IO),
io.nl(!IO),
io.nl(!IO)
),
% Find all prime numbers.
some [!Is] (
!:Is = rtree.search_general(any_is_prime, true1, !.RTree),
list.sort(!Is),
io.write_string("Primes from 0 to 100:\n", !IO),
io.write(!.Is, !IO),
io.nl(!IO),
io.nl(!IO)
),
% Find the first prime number.
io.write_string("First prime from 0 to 100:\n", !IO),
( if rtree.search_first(any_is_prime, id, !.RTree, 100.0, L, _) then
io.write(L, !IO),
io.nl(!IO),
io.nl(!IO)
else
io.write_string("search_first FAILED!\n\n", !IO)
),
% Delete all odd numbers.
io.write_string("All odds deleted, " ++
"remaining integers from 33 to 66:\n", !IO),
some [!Is] (
( if delete_odd(1, 100, !RTree) then
!:Is = rtree.search_intersects(!.RTree, interval(33.0, 66.0)),
list.sort(!Is),
io.write(!.Is, !IO),
io.nl(!IO),
io.nl(!IO)
else
io.write_string("delete FAILED!\n\n", !IO)
)
)
).
%---------------------------------------------------------------------------%
:- pred true1(T::in) is semidet.
true1(_) :-
semidet_succeed.
:- pred id(int::in, float::out) is semidet.
id(I, float(I)) :-
semidet_succeed.
%---------------------------------------------------------------------------%
:- pred add_integers(int::in, int::in, irtree::in, irtree::out) is det.
add_integers(N, M, !RTree) :-
( if N >= M then
true
else
NF = float(N),
K = interval(NF, NF),
insert(K, N, !RTree),
add_integers(N + 1, M, !RTree)
).
%---------------------------------------------------------------------------%
:- pred test_range(bool::in, int::in, int::in, irtree::in,
list(int)::out, bool::out) is det.
test_range(Cnts, Mn, Mx, RT, Is, P) :-
K = interval(float(Mn), float(Mx)),
(
Cnts = yes,
Is0 = search_contains(RT, K)
;
Cnts = no,
Is0 = search_intersects(RT, K)
),
list.sort(Is0, Is),
P = check_range(Mn, Mx, Is).
%---------------------------------------------------------------------------%
:- func check_range(int, int, list(int)) = bool.
check_range(N, M, Is) = P :-
( if N > M then
(
Is = [] ,
P = yes
;
Is = [_ | _],
P = no
)
else
( if Is = [N | Is1] then
P = check_range(N + 1, M, Is1)
else
P = no
)
).
%---------------------------------------------------------------------------%
% A very naive prime number test.
%
:- pred any_is_prime(interval::in) is semidet.
any_is_prime(I) :-
any_is_prime(I, _).
%---------------------------------------------------------------------------%
:- pred any_is_prime(interval::in, float::out) is semidet.
any_is_prime(interval(Min, Max), P) :-
Min1 = ceiling(Min),
Max1 = floor(Max),
any_is_prime(Min1, Max1, P).
%---------------------------------------------------------------------------%
:- pred any_is_prime(float::in, float::in, float::out) is semidet.
any_is_prime(Min, Max, P) :-
Min =< Max,
( if is_prime(Min) then
P = Min
else
any_is_prime(Min + 1.0, Max, P)
).
%---------------------------------------------------------------------------%
:- pred is_prime(float::in) is semidet.
is_prime(N) :-
NI = floor_to_int(N),
NI > 1,
MaxD = round_to_int(sqrt(N)),
none_divides(2, MaxD, NI).
%---------------------------------------------------------------------------%
:- pred none_divides(int::in, int::in, int::in) is semidet.
none_divides(N, M, I) :-
( if N > M then
true
else if I mod N = 0 then
false
else
none_divides(N + 1, M, I)
).
%---------------------------------------------------------------------------%
% Assumption: N is odd.
%
:- pred delete_odd(int::in, int::in, irtree::in, irtree::out) is semidet.
delete_odd(N, M, !RT) :-
( if N >= M then
true
else
NF = float(N),
I = interval(NF, NF),
delete(I, N, !RT),
delete_odd(N + 2, M, !RT)
).