[m-rev.] diff: minor improvement to equality and comparison for arrays

Julien Fischer jfischer at opturion.com
Wed Aug 15 09:45:30 AEST 2018


Minor improvement to equality and comparison for arrays.

library/array.m:
     Use unsafe lookups in the implementation of equality and
     comparison.  In these cases the lookups are safe since
     the necessary bounds checks are done by the caller.

     Avoid unnecessary module qualification.

tests/hard_coded/Mmakefile:
tests/hard_coded/array_unify_compare.{m,exp}:
     Add a systematic test for array equality and comparison.

Julien.

diff --git a/library/array.m b/library/array.m
index f02a9dd..fe07597 100644
--- a/library/array.m
+++ b/library/array.m
@@ -874,22 +874,22 @@ array_equal(Array1, Array2) :-
          array.size(Array1, Size),
          array.size(Array2, Size)
      then
-        array.equal_elements(0, Size, Array1, Array2)
+        equal_elements(0, Size, Array1, Array2)
      else
          fail
      ).

-:- pred array.equal_elements(int, int, array(T), array(T)).
-:- mode array.equal_elements(in, in, in, in) is semidet.
+:- pred equal_elements(int, int, array(T), array(T)).
+:- mode equal_elements(in, in, in, in) is semidet.

  equal_elements(N, Size, Array1, Array2) :-
      ( if N = Size then
          true
      else
-        array.lookup(Array1, N, Elem),
-        array.lookup(Array2, N, Elem),
+        array.unsafe_lookup(Array1, N, Elem),
+        array.unsafe_lookup(Array2, N, Elem),
          N1 = N + 1,
-        array.equal_elements(N1, Size, Array1, Array2)
+        equal_elements(N1, Size, Array1, Array2)
      ).

  array_compare(A1, A2) = C :-
@@ -907,7 +907,7 @@ array_compare(Result, Array1, Array2) :-
      compare(SizeResult, Size1, Size2),
      (
          SizeResult = (=),
-        array.compare_elements(0, Size1, Array1, Array2, Result)
+        compare_elements(0, Size1, Array1, Array2, Result)
      ;
          ( SizeResult = (<)
          ; SizeResult = (>)
@@ -922,13 +922,13 @@ compare_elements(N, Size, Array1, Array2, Result) :-
      ( if N = Size then
          Result = (=)
      else
-        array.lookup(Array1, N, Elem1),
-        array.lookup(Array2, N, Elem2),
+        array.unsafe_lookup(Array1, N, Elem1),
+        array.unsafe_lookup(Array2, N, Elem2),
          compare(ElemResult, Elem1, Elem2),
          (
              ElemResult = (=),
              N1 = N + 1,
-            array.compare_elements(N1, Size, Array1, Array2, Result)
+            compare_elements(N1, Size, Array1, Array2, Result)
          ;
              ( ElemResult = (<)
              ; ElemResult = (>)
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index a418d8c..3880f06 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -16,6 +16,7 @@ ORDINARY_PROGS = \
  	array_all_tf \
  	array_gen \
  	array_sort \
+	array_unify_compare \
  	array_test \
  	array_test2 \
  	bag_various \
diff --git a/tests/hard_coded/array_unify_compare.exp b/tests/hard_coded/array_unify_compare.exp
index e69de29..348dc49 100644
--- a/tests/hard_coded/array_unify_compare.exp
+++ b/tests/hard_coded/array_unify_compare.exp
@@ -0,0 +1,51 @@
+unify(array([]), array([])) ==> true
+unify(array([]), array([1])) ==> false
+unify(array([]), array([1, 2])) ==> false
+unify(array([]), array([2, 1])) ==> false
+unify(array([]), array([2])) ==> false
+unify(array([1]), array([])) ==> false
+unify(array([1]), array([1])) ==> true
+unify(array([1]), array([1, 2])) ==> false
+unify(array([1]), array([2, 1])) ==> false
+unify(array([1]), array([2])) ==> false
+unify(array([1, 2]), array([])) ==> false
+unify(array([1, 2]), array([1])) ==> false
+unify(array([1, 2]), array([1, 2])) ==> true
+unify(array([1, 2]), array([2, 1])) ==> false
+unify(array([1, 2]), array([2])) ==> false
+unify(array([2, 1]), array([])) ==> false
+unify(array([2, 1]), array([1])) ==> false
+unify(array([2, 1]), array([1, 2])) ==> false
+unify(array([2, 1]), array([2, 1])) ==> true
+unify(array([2, 1]), array([2])) ==> false
+unify(array([2]), array([])) ==> false
+unify(array([2]), array([1])) ==> false
+unify(array([2]), array([1, 2])) ==> false
+unify(array([2]), array([2, 1])) ==> false
+unify(array([2]), array([2])) ==> true
+
+compare(array([]), array([])) ==> '='
+compare(array([]), array([1])) ==> '<'
+compare(array([]), array([1, 2])) ==> '<'
+compare(array([]), array([2, 1])) ==> '<'
+compare(array([]), array([2])) ==> '<'
+compare(array([1]), array([])) ==> '>'
+compare(array([1]), array([1])) ==> '='
+compare(array([1]), array([1, 2])) ==> '<'
+compare(array([1]), array([2, 1])) ==> '<'
+compare(array([1]), array([2])) ==> '<'
+compare(array([1, 2]), array([])) ==> '>'
+compare(array([1, 2]), array([1])) ==> '>'
+compare(array([1, 2]), array([1, 2])) ==> '='
+compare(array([1, 2]), array([2, 1])) ==> '<'
+compare(array([1, 2]), array([2])) ==> '>'
+compare(array([2, 1]), array([])) ==> '>'
+compare(array([2, 1]), array([1])) ==> '>'
+compare(array([2, 1]), array([1, 2])) ==> '>'
+compare(array([2, 1]), array([2, 1])) ==> '='
+compare(array([2, 1]), array([2])) ==> '>'
+compare(array([2]), array([])) ==> '>'
+compare(array([2]), array([1])) ==> '>'
+compare(array([2]), array([1, 2])) ==> '<'
+compare(array([2]), array([2, 1])) ==> '<'
+compare(array([2]), array([2])) ==> '='
diff --git a/tests/hard_coded/array_unify_compare.m b/tests/hard_coded/array_unify_compare.m
index e69de29..47b236d 100644
--- a/tests/hard_coded/array_unify_compare.m
+++ b/tests/hard_coded/array_unify_compare.m
@@ -0,0 +1,84 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%---------------------------------------------------------------------------%
+%
+% Test unification and comparison for arrays.
+%
+%---------------------------------------------------------------------------%
+
+:- module array_unify_compare.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module array.
+:- import_module list.
+:- import_module string.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+   test_unify(test_arrays, test_arrays, !IO),
+   io.nl(!IO),
+   test_compare(test_arrays, test_arrays, !IO).
+
+:- pred test_unify(list(list(int))::in, list(list(int))::in,
+    io::di, io::uo) is det.
+
+test_unify([], _, !IO).
+test_unify([A | As], Bs, !IO) :-
+    do_test_unify(array(A), Bs, !IO),
+    test_unify(As, Bs, !IO).
+
+:- pred do_test_unify(array(int)::in, list(list(int))::in, io::di, io::uo) is det.
+
+do_test_unify(_, [], !IO).
+do_test_unify(ArrayA, [B | Bs], !IO) :-
+    ArrayB = array(B),
+    ( if ArrayA = ArrayB then
+        Result  = "true"
+    else
+        Result = "false"
+    ),
+    io.format("unify(%s, %s) ==> %s\n",
+        [s(string(ArrayA)), s(string(ArrayB)), s(Result)], !IO),
+    do_test_unify(ArrayA, Bs, !IO).
+
+:- pred test_compare(list(list(int))::in, list(list(int))::in,
+    io::di, io::uo) is det.
+
+test_compare([], _, !IO).
+test_compare([A | As], Bs, !IO) :-
+    do_test_compare(array(A), Bs, !IO),
+    test_compare(As, Bs, !IO).
+
+:- pred do_test_compare(array(int)::in, list(list(int))::in, io::di, io::uo)
+    is det.
+
+do_test_compare(_, [], !IO).
+do_test_compare(ArrayA, [B | Bs], !IO) :-
+    ArrayB = array(B),
+    compare(Result, ArrayA, ArrayB),
+    io.format("compare(%s, %s) ==> %s\n",
+        [s(string(ArrayA)), s(string(ArrayB)), s(string(Result))], !IO),
+    do_test_compare(ArrayA, Bs, !IO).
+
+:- func test_arrays = list(list(int)).
+
+test_arrays = [
+    [],
+    [1],
+    [1, 2],
+    [2, 1],
+    [2]
+].
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%


More information about the reviews mailing list