[m-rev.] for review: conversion from array/1 to array2d/1
Julien Fischer
jfischer at opturion.com
Mon Nov 19 16:11:27 AEDT 2018
For review by anyone.
Conversion from array/1 to array2d/1.
Add a function that uses an array/1 value to construct an array2d/1 value
without allocating new memory for the element storage or traversing the
elements.
library/array2d.m:
Add a function that creates an array2d/1 from an array/1 value
Fix minor documentation issues:
- re-order the declarations so that of from_lists/1 is directly below
that of array2d/1.
- s/a/an/ in a few spots.
- add missing apostrophes.
NEWS:
Announce the new function.
tests/hard_coded/Mmakefile:
tests/hard_coded/array2d_from_array.{m,exp}:
Add a test case.
Julien.
diff --git a/NEWS b/NEWS
index 88d36a7..8463bba 100644
--- a/NEWS
+++ b/NEWS
@@ -474,10 +474,11 @@ Changes to the Mercury standard library:
- least_index/1
- greatest_index/1
-* The following predicates have been added to the array2d module:
+* The following predicates and functions have been added to the array2d module:
- is_empty/1
- fill/3
+ - from_array/3
* The following predicates have been added to the time module:
diff --git a/library/array2d.m b/library/array2d.m
index c84a081..61f9837 100644
--- a/library/array2d.m
+++ b/library/array2d.m
@@ -25,7 +25,7 @@
%---------------------------------------------------------------------------%
- % A array2d is a two-dimensional array stored in row-major order
+ % An array2d is a two-dimensional array stored in row-major order
% (that is, the elements of the first row in left-to-right
% order, followed by the elements of the second row and so forth.)
%
@@ -46,7 +46,7 @@
:- func init(int, int, T) = array2d(T).
:- mode init(in, in, in) = array2d_uo is det.
- % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a array2d
+ % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs an array2d
% of size M * N, with the special case that bounds(array2d([]), 0, 0).
%
% An exception is thrown if the sublists are not all the same length.
@@ -54,6 +54,20 @@
:- func array2d(list(list(T))) = array2d(T).
:- mode array2d(in) = array2d_uo is det.
+ % A synonym for the above.
+ %
+:- func from_lists(list(list(T))) = array2d(T).
+:- mode from_lists(in) = array2d_uo is det.
+
+ % from_array(M, N, Array) constructs an array2d of size M * N whose
+ % elements are taken from Array. The elements in Array are added to
+ % the array2d in row-major order (see above).
+ % Throws an exception if M < or N < 0, or if the number of elements in
+ % Array does not equal M * N.
+ %
+:- func from_array(int, int, array(T)) = array2d(T).
+:- mode from_array(in, in, array_di) = array2d_uo is det.
+
% is_empty(Array):
% True iff Array contains zero elements.
%
@@ -61,11 +75,6 @@
%:- mode is_empty(array2d_ui) is semidet.
:- mode is_empty(in) is semidet.
- % A synonym for the above.
- %
-:- func from_lists(list(list(T))) = array2d(T).
-:- mode from_lists(in) = array2d_uo is det.
-
% bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), M, N)
%
:- pred bounds(array2d(T), int, int).
@@ -80,7 +89,7 @@
:- mode in_bounds(in, in, in ) is semidet.
% array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = X
- % where X is the J+1th element of the I+1th row (that is, indices
+ % where X is the J+1'th element of the I+1'th row (that is, indices
% start from zero.)
%
% An exception is thrown unless 0 =< I < M, 0 =< J < N.
@@ -175,11 +184,34 @@ array2d(Xss @ [Xs | _]) = T :-
else func_error("array2d.array2d/1: non-rectangular list of lists")
).
+from_lists(Xss) = array2d(Xss).
+
+from_array(M, N, Array) = Array2d :-
+ ( if
+ M >= 0,
+ N >= 0
+ then
+ array.size(Array, Size),
+ compare(Result, Size, M * N),
+ (
+ Result = (=),
+ Array2d = array2d(M, N, Array)
+ ;
+ Result = (>),
+ error("array2d.from_array: too many elements")
+ ;
+ Result = (<),
+ error("array2d.from_array: too few elements")
+ )
+ else
+ error("array2d.from_array: bounds must be non-negative")
+ ).
+
+%---------------------------------------------------------------------------%
+
is_empty(array2d(_, _, A)) :-
array.is_empty(A).
-from_lists(Xss) = array2d(Xss).
-
%---------------------------------------------------------------------------%
bounds(array2d(M, N, _A), M, N).
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index bbbbc97..dd39c13 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -676,6 +676,7 @@ ifeq "$(findstring profdeep,$(GRADE))" ""
array_resize \
array_shrink \
array_swap \
+ array2d_from_array \
allow_stubs \
arith_int16 \
arith_int32 \
diff --git a/tests/hard_coded/array2d_from_array.exp b/tests/hard_coded/array2d_from_array.exp
index e69de29..511ecf9 100644
--- a/tests/hard_coded/array2d_from_array.exp
+++ b/tests/hard_coded/array2d_from_array.exp
@@ -0,0 +1,45 @@
+------FROM ARRAY------
+Array = array([])
+M = -1
+N = -1
+EXCEPTION: "array2d.from_array: bounds must be non-negative"
+------FROM ARRAY------
+Array = array([])
+M = 0
+N = -1
+EXCEPTION: "array2d.from_array: bounds must be non-negative"
+------FROM ARRAY------
+Array = array([])
+M = -1
+N = 0
+EXCEPTION: "array2d.from_array: bounds must be non-negative"
+------FROM ARRAY------
+Array = array([])
+M = 2
+N = 2
+EXCEPTION: "array2d.from_array: too few elements"
+------FROM ARRAY------
+Array = array([1, 2, 3, 4, 5])
+M = 2
+N = 2
+EXCEPTION: "array2d.from_array: too many elements"
+------FROM ARRAY------
+Array = array([])
+M = 0
+N = 0
+Array2d = array2d(0, 0, array([]))
+------FROM ARRAY------
+Array = array([1])
+M = 1
+N = 1
+Array2d = array2d(1, 1, array([1]))
+------FROM ARRAY------
+Array = array([1, 2, 3, 4])
+M = 2
+N = 2
+Array2d = array2d(2, 2, array([1, 2, 3, 4]))
+------FROM ARRAY------
+Array = array([1, 2, 3, 4, 5, 6])
+M = 2
+N = 3
+Array2d = array2d(2, 3, array([1, 2, 3, 4, 5, 6]))
diff --git a/tests/hard_coded/array2d_from_array.m b/tests/hard_coded/array2d_from_array.m
index e69de29..219bb3c 100644
--- a/tests/hard_coded/array2d_from_array.m
+++ b/tests/hard_coded/array2d_from_array.m
@@ -0,0 +1,56 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+%
+% Test array2d.from_array/3.
+%
+
+:- module array2d_from_array.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module array.
+:- import_module array2d.
+:- import_module exception.
+:- import_module list.
+
+main(!IO) :-
+ test_from_array([], -1, -1, !IO),
+ test_from_array([], 0, -1, !IO),
+ test_from_array([], -1, 0, !IO),
+ test_from_array([], 2, 2, !IO), % Too few elements.
+ test_from_array([1, 2, 3, 4, 5], 2, 2, !IO), % Too many elements.
+ test_from_array([], 0, 0, !IO),
+ test_from_array([1], 1, 1, !IO),
+ test_from_array([1, 2, 3, 4], 2, 2, !IO),
+ test_from_array([1, 2, 3, 4, 5, 6], 2, 3, !IO).
+
+:- pred test_from_array(list(int)::in, int::in, int::in,
+ io::di, io::uo) is cc_multi.
+
+test_from_array(Elems, M, N, !IO) :-
+ io.write_string("------FROM ARRAY------\n", !IO),
+ Array = array.from_list(Elems),
+ io.write_string("Array = ", !IO),
+ io.write_line(Array, !IO),
+ io.write_string("M = ", !IO),
+ io.write_line(M, !IO),
+ io.write_string("N = ", !IO),
+ io.write_line(N, !IO),
+ ( try []
+ Array2d = array2d.from_array(M, N, Array)
+ then
+ io.write_string("Array2d = ", !IO),
+ io.write_line(Array2d, !IO)
+ catch software_error(E) ->
+ io.write_string("EXCEPTION: ", !IO),
+ io.write_line(E, !IO)
+ ).
More information about the reviews
mailing list