[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