[m-rev.] for review: add array.all_{true,false}.2
Julien Fischer
jfischer at opturion.com
Sun Jul 21 01:27:00 AEST 2013
For review by anyone.
Add all_{true,false}/2 and is_empty/1 to array and version_array.
library/array.m:
library/version_array.m:
Add the above predicates.
NEWS:
Announce the new predicates.
tests/hard_coded/Mmakefile:
tests/hard_coded/array_all_tf.{m,exp}:
Test the new predicates.
tests/hard_coded/version_array_test.{m,exp}:
Extend this test case to cover the new predicates.
Julien.
diff --git a/NEWS b/NEWS
index 8f74aa6..187ab51 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ Changes to the Mercury standard library:
* We have added the function cord.condense/1.
+* We have added the following predicates to the array and version_array
+ modules: is_empty/1, all_true/2 and all_false/2.
+
NEWS for Mercury 13.05.2
------------------------
diff --git a/library/array.m b/library/array.m
index b65f79c..8d0fa33 100644
--- a/library/array.m
+++ b/library/array.m
@@ -189,6 +189,13 @@
%:- mode array.in_bounds(array_ui, in) is semidet.
:- mode array.in_bounds(in, in) is semidet.
+ % array.is_empty(Array):
+ % True iff Array is an array of size zero.
+ %
+:- pred array.is_empty(array(_T)).
+%:- mode array.is_empty(array_ui) is semidet.
+:- mode array.is_empty(in) is semidet.
+
%-----------------------------------------------------------------------------%
% array.lookup returns the Nth element of an array.
@@ -651,6 +658,20 @@
in(pred(in, in, out, in, out) is semidet),
in, in, array_uo, in, out) is semidet.
+ % array.all_true(Pred, Array):
+ % True iff Pred is true for every element of Array.
+ %
+:- pred array.all_true(pred(T), array(T)).
+%:- mode array.all_true(in(pred(in) is semidet), array_ui) is semidet.
+:- mode array.all_true(in(pred(in) is semidet), in) is semidet.
+
+ % array.all_false(Pred, Array):
+ % True iff Pred is false for every element of Array.
+ %
+:- pred array.all_false(pred(T), array(T)).
+%:- mode array.all_false(in(pred(in) is semidet), array_ui) is semidet.
+:- mode array.all_false(in(pred(in) is semidet), in) is semidet.
+
% array.append(A, B) = C:
%
% Make C a concatenation of the arrays A and B.
@@ -1467,6 +1488,9 @@ array.in_bounds(Array, Index) :-
array.bounds(Array, Min, Max),
Min =< Index, Index =< Max.
+array.is_empty(Array) :-
+ array.size(Array, 0).
+
array.semidet_set(Index, Item, !Array) :-
( array.in_bounds(!.Array, Index) ->
array.unsafe_set(Index, Item, !Array)
@@ -2612,6 +2636,40 @@ array.map_corresponding_foldl_2(P, I, N, A, B, !C, !D) :-
).
%-----------------------------------------------------------------------------%
+
+array.all_true(Pred, Array) :-
+ do_all_true(Pred, array.min(Array), array.max(Array), Array).
+
+:- pred do_all_true(pred(T), int, int, array(T)).
+%:- mode do_all_true(in(pred(in) is semidet), in, in, array_ui) is semidet.
+:- mode do_all_true(in(pred(in) is semidet), in, in, in) is semidet.
+
+do_all_true(Pred, I, UB, Array) :-
+ ( if I =< UB then
+ Elem = Array ^ unsafe_elem(I),
+ Pred(Elem),
+ do_all_true(Pred, I + 1, UB, Array)
+ else
+ true
+ ).
+
+array.all_false(Pred, Array) :-
+ do_all_false(Pred, array.min(Array), array.max(Array), Array).
+
+:- pred do_all_false(pred(T), int, int, array(T)).
+%:- mode do_all_false(in(pred(in) is semidet), in, in, array_ui) is semidet.
+:- mode do_all_false(in(pred(in) is semidet), in, in, in) is semidet.
+
+do_all_false(Pred, I, UB, Array) :-
+ ( if I =< UB then
+ Elem = Array ^ unsafe_elem(I),
+ not Pred(Elem),
+ do_all_false(Pred, I + 1, UB, Array)
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% SAMsort (smooth applicative merge) invented by R.A. O'Keefe.
diff --git a/library/version_array.m b/library/version_array.m
index c1c0b3d..255311d 100644
--- a/library/version_array.m
+++ b/library/version_array.m
@@ -140,6 +140,10 @@
%
:- func max(version_array(T)) = int.
+ % is_empty(Array) is true iff Array is the empty array.
+ %
+:- pred is_empty(version_array(T)::in) is semidet.
+
% resize(A, N, X) returns a new array whose items from
% 0..min(size(A), N - 1) are taken from A and whose items
% from min(size(A), N - 1)..(N - 1) (if any) are initialised to X.
@@ -215,6 +219,18 @@
:- mode foldr2(pred(in, in, out, di, uo) is semidet, in,
in, out, di, uo) is semidet.
+ % version_array.all_true(Pred, Array):
+ % True iff Pred is true for every element of Array.
+ %
+:- pred all_true(pred(T)::in(pred(in) is semidet), version_array(T)::in)
+ is semidet.
+
+ % version_array.all_false(Pred, Array):
+ % True iff Pred is false for every element of Array.
+ %
+:- pred all_false(pred(T)::in(pred(in) is semidet), version_array(T)::in)
+ is semidet.
+
% copy(A) is a copy of array A. Access to the copy is O(1).
%
:- func copy(version_array(T)) = version_array(T).
@@ -443,6 +459,38 @@ do_foldr2(P, VA, I, !Acc1, !Acc2) :-
%-----------------------------------------------------------------------------%
+all_true(Pred, VA) :-
+ do_all_true(Pred, 0, size(VA), VA).
+
+:- pred do_all_true(pred(T)::in(pred(in) is semidet), int::in, int::in,
+ version_array(T)::in) is semidet.
+
+do_all_true(Pred, I, N, VA) :-
+ ( if I < N then
+ Elem = VA ^ elem(I),
+ Pred(Elem),
+ do_all_true(Pred, I + 1, N, VA)
+ else
+ true
+ ).
+
+all_false(Pred, VA) :-
+ do_all_false(Pred, 0, size(VA), VA).
+
+:- pred do_all_false(pred(T)::in(pred(in) is semidet), int::in, int::in,
+ version_array(T)::in) is semidet.
+
+do_all_false(Pred, I, N, VA) :-
+ ( if I < N then
+ Elem = VA ^ elem(I),
+ not Pred(Elem),
+ do_all_false(Pred, I + 1, N, VA)
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+
unsafe_rewind(VA, unsafe_rewind(VA)).
%-----------------------------------------------------------------------------%
@@ -751,6 +799,9 @@ resize(N, X, VA, resize(VA, N, X)).
N = VA.size();
").
+is_empty(VA) :-
+ size(VA) = 0.
+
:- pred get_if_in_range(version_array(T)::in, int::in, T::out) is semidet.
:- pragma foreign_proc("C",
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index acecc02..240d173 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -11,6 +11,7 @@ ORDINARY_PROGS= \
array_gen \
array_test \
array_test2 \
+ array_all_tf \
backquoted_qualified_ops \
bag_various \
bidirectional \
diff --git a/tests/hard_coded/array_all_tf.exp b/tests/hard_coded/array_all_tf.exp
new file mode 100644
index 0000000..65cf96c
--- /dev/null
+++ b/tests/hard_coded/array_all_tf.exp
@@ -0,0 +1,4 @@
+TEST: all_true(even, array([2, 4, 6, 8, 10]): PASSED
+TEST: all_false(odd, array([2, 4, 6, 8, 10]): PASSED
+TEST: all_true(even, array([]): PASSED
+TEST: all_false(even, array([]): PASSED
diff --git a/tests/hard_coded/array_all_tf.m b/tests/hard_coded/array_all_tf.m
new file mode 100644
index 0000000..1347a4c
--- /dev/null
+++ b/tests/hard_coded/array_all_tf.m
@@ -0,0 +1,49 @@
+% Test array.all_{true,false}/2.
+
+:- module array_all_tf.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module array.
+:- import_module int.
+:- import_module list.
+
+main(!IO) :-
+ EvensArray = array([2, 4, 6, 8, 10]),
+ io.write_string("TEST: all_true(even, ", !IO),
+ io.write(EvensArray, !IO),
+ io.write_string(": ", !IO),
+ ( if array.all_true(int.even, EvensArray)
+ then io.write_string("PASSED\n", !IO)
+ else io.write_string("FAILED\n", !IO)
+ ),
+
+ io.write_string("TEST: all_false(odd, ", !IO),
+ io.write(EvensArray, !IO),
+ io.write_string(": ", !IO),
+ ( if array.all_false(int.odd, EvensArray)
+ then io.write_string("PASSED\n", !IO)
+ else io.write_string("FAILED\n", !IO)
+ ),
+
+ array.make_empty_array(EmptyArray : array(int)),
+ io.write_string("TEST: all_true(even, ", !IO),
+ io.write(EmptyArray, !IO),
+ io.write_string(": ", !IO),
+ ( if array.all_true(int.even, EmptyArray)
+ then io.write_string("PASSED\n", !IO)
+ else io.write_string("FAILED\n", !IO)
+ ),
+
+ io.write_string("TEST: all_false(even, ", !IO),
+ io.write(EmptyArray, !IO),
+ io.write_string(": ", !IO),
+ ( if array.all_false(int.even, EmptyArray)
+ then io.write_string("PASSED\n", !IO)
+ else io.write_string("FAILED\n", !IO)
+ ).
diff --git a/tests/hard_coded/version_array_test.exp b/tests/hard_coded/version_array_test.exp
index e08410c..e2ee5be 100644
--- a/tests/hard_coded/version_array_test.exp
+++ b/tests/hard_coded/version_array_test.exp
@@ -17,3 +17,7 @@ Found exception as expected: index_out_of_bounds("version_array.set: index -1 no
Found exception as expected: index_out_of_bounds("version_array.set: index -1 not in range [0, 3]")
Found exception as expected: index_out_of_bounds("version_array.lookup: index -1 not in range [0, 3]")
Found exception as expected: index_out_of_bounds("version_array.lookup: index 4 not in range [0, 3]")
+all_true(int.even A8): passed
+all_false(int.odd, A8): passed
+all_true(int.even, A0): passed
+all_false(int.even, A0): passed
diff --git a/tests/hard_coded/version_array_test.m b/tests/hard_coded/version_array_test.m
index d517ec7..8449088 100644
--- a/tests/hard_coded/version_array_test.m
+++ b/tests/hard_coded/version_array_test.m
@@ -88,6 +88,32 @@ main(!IO) :-
((pred) is semidet :-
_ = A7 ^ elem(4)
), !IO),
+
+ A8 = version_array([2, 4, 6, 8]),
+ io.write_string("all_true(int.even A8): ", !IO),
+ ( if version_array.all_true(int.even, A8)
+ then io.write_string("passed\n", !IO)
+ else io.write_string("failed\n", !IO)
+ ),
+
+ io.write_string("all_false(int.odd, A8): ", !IO),
+ ( if version_array.all_false(int.odd, A8)
+ then io.write_string("passed\n", !IO)
+ else io.write_string("failed\n", !IO)
+ ),
+
+ io.write_string("all_true(int.even, A0): ", !IO),
+ ( if version_array.all_true(int.even, A0)
+ then io.write_string("passed\n", !IO)
+ else io.write_string("failed\n", !IO)
+ ),
+
+ io.write_string("all_false(int.even, A0): ", !IO),
+ ( if version_array.all_false(int.even, A0)
+ then io.write_string("passed\n", !IO)
+ else io.write_string("failed\n", !IO)
+ ),
+
true.
:- pred test_exception((pred)::in((pred) is semidet),
More information about the reviews
mailing list