mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 23:05:21 +00:00
279 lines
7.2 KiB
Mathematica
279 lines
7.2 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% array.nl
|
|
|
|
% Main author: conway.
|
|
|
|
% this file contains a set of predicates for generating an manipulating
|
|
% an array data structure. The implementation uses 2-3 trees to yield
|
|
% O(logN) performance for accesses and updates. Array creation is an
|
|
% O(NlogN) process.
|
|
|
|
% arrays are created with any two integer bounds on the indices.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module array.
|
|
:- interface.
|
|
:- import_module int, list.
|
|
|
|
:- type array(T).
|
|
|
|
% array__init creates an array with bounds from Low to High, with each
|
|
% element initialized to Init.
|
|
:- pred array__init(int, int, T, array(T)).
|
|
:- mode array__init(in, in, in, out) is det. % want an array_skeleton?
|
|
|
|
% array__bounds returns the upper and lower bounds of an array.
|
|
:- pred array__bounds(array(_T), int, int).
|
|
:- mode array__bounds(in, out, out) is det.
|
|
|
|
% array__lookup returns the Nth element of an array
|
|
% or fails if the index is out of bounds.
|
|
:- pred array__lookup(array(T), int, T).
|
|
:- mode array__lookup(in, in, out) is det.
|
|
|
|
% array__set sets the nth element of an array, and returns the resulting
|
|
% array (good oppertunity for destructive update ;-). It fails if the
|
|
% index is out of bounds.
|
|
:- pred array__set(array(T), int, T, array(T)).
|
|
:- mode array__set(in, in, in, out) is det.
|
|
|
|
% array__resize takes an array and new lower and upper bounds.
|
|
% the array is expanded or shrunk at each end to make it fit
|
|
% the new bounds.
|
|
:- pred array__resize(array(T), int, int, array(T)).
|
|
:- mode array__resize(in, in, in, out) is det.
|
|
|
|
% array__from_list takes a list (of nonzero length),
|
|
% and returns an array containing those elements in
|
|
% the same order that they occured in the list.
|
|
:- pred array__from_list(list(T), array(T)).
|
|
:- mode array__from_list(in, out) is det.
|
|
|
|
% array__to_list takes an array and returns a list containing the
|
|
% elements of the array in the same order that they
|
|
% occured in the array.
|
|
:- pred array__to_list(array(T), list(T)).
|
|
:- mode array__to_list(in, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module require.
|
|
|
|
:- type array(T) ---> node(T)
|
|
; two(
|
|
int,
|
|
int,
|
|
array(T),
|
|
array(T)
|
|
)
|
|
; three(
|
|
int,
|
|
int,
|
|
array(T),
|
|
array(T),
|
|
array(T)
|
|
).
|
|
|
|
array__init(Low, High, Init, Array) :-
|
|
Size0 is High - Low,
|
|
Size is Size0 + 1,
|
|
(
|
|
Size = 0
|
|
->
|
|
error("Cannot have a zero length array")
|
|
;
|
|
Size = 1
|
|
->
|
|
Array = node(Init)
|
|
;
|
|
Size = 2
|
|
->
|
|
Array = two(Low, High, node(Init), node(Init))
|
|
;
|
|
Size = 3
|
|
->
|
|
Array = three(Low, High, node(Init), node(Init), node(Init))
|
|
;
|
|
Mod2 is Size mod 2,
|
|
Mod2 = 0,
|
|
Mod3 is Size mod 3,
|
|
Mod3 \= 0
|
|
->
|
|
N is Size // 2,
|
|
L2 is Low + N,
|
|
H1 is L2 - 1,
|
|
array__init(Low, H1, Init, A1),
|
|
array__init(L2, High, Init, A2),
|
|
Array = two(Low, High, A1, A2)
|
|
;
|
|
N is Size // 3,
|
|
L2 is Low + N,
|
|
L3 is L2 + N,
|
|
H1 is L2 - 1,
|
|
H2 is L3 - 1,
|
|
array__init(Low, H1, Init, A1),
|
|
array__init(L2, H2, Init, A2),
|
|
array__init(L3, High, Init, A3),
|
|
Array = three(Low, High, A1, A2, A3)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__bounds(node(_), 0, 0).
|
|
array__bounds(two(Low, High, _, _), Low, High).
|
|
array__bounds(three(Low, High, _, _, _), Low, High).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__lookup(Array, Index, Item) :-
|
|
array__bounds(Array, Low, High),
|
|
(
|
|
Index < Low
|
|
->
|
|
error("Array index below lower bound")
|
|
;
|
|
Index > High
|
|
->
|
|
error("Array index above upper bound")
|
|
;
|
|
array__search_2(Array, Index, Item)
|
|
).
|
|
|
|
:- pred array__search_2(array(T), int, T).
|
|
:- mode array__search_2(in, in, out) is det.
|
|
|
|
array__search_2(node(Item), _Index, Item).
|
|
array__search_2(two(Low, High, Left, Right), Index, Item) :-
|
|
Size is High - Low,
|
|
Half is Size // 2,
|
|
Mid is Low + Half,
|
|
(
|
|
Index =< Mid
|
|
->
|
|
array__search_2(Left, Index, Item)
|
|
;
|
|
array__search_2(Right, Index, Item)
|
|
).
|
|
array__search_2(three(Low, High, Left, Middle, Right), Index, Item) :-
|
|
Size is High - Low,
|
|
Size1 is Size + 1,
|
|
Third is Size1 // 3,
|
|
Mid1 is Low + Third,
|
|
Mid2 is Mid1 + Third,
|
|
(
|
|
Index < Mid1
|
|
->
|
|
array__search_2(Left, Index, Item)
|
|
;
|
|
Index < Mid2
|
|
->
|
|
array__search_2(Middle, Index, Item)
|
|
;
|
|
array__search_2(Right, Index, Item)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__set(node(_), _Index, Item, node(Item)).
|
|
array__set(two(Low, High, Left, Right), Index, Item, A) :-
|
|
Size is High - Low,
|
|
Half is Size // 2,
|
|
Mid is Low + Half,
|
|
(
|
|
Index < Mid
|
|
->
|
|
array__set(Left, Index, Item, Left1),
|
|
A = two(Low, High, Left1, Right)
|
|
;
|
|
array__set(Right, Index, Item, Right1),
|
|
A = two(Low, High, Left, Right1)
|
|
).
|
|
array__set(three(Low, High, Left, Middle, Right), Index, Item, A) :-
|
|
Size is High - Low,
|
|
Size1 is Size + 1,
|
|
Third is Size1 // 3,
|
|
Mid1 is Low + Third,
|
|
Mid2 is Mid1 + Third,
|
|
(
|
|
Index < Mid1
|
|
->
|
|
array__set(Left, Index, Item, Left1),
|
|
A = three(Low, High, Left1, Middle, Right)
|
|
;
|
|
Index < Mid2
|
|
->
|
|
array__set(Middle, Index, Item, Middle1),
|
|
A = three(Low, High, Left, Middle1, Right)
|
|
;
|
|
array__set(Right, Index, Item, Right1),
|
|
A = three(Low, High, Left, Middle, Right1)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__resize(Array0, L, H, Array) :-
|
|
array__bounds(Array0, L0, H0),
|
|
array__lookup(Array0, L0, Item),
|
|
int__max(L, L0, L1),
|
|
int__min(H, H0, H1),
|
|
array__fetch_items(Array0, L1, H1, Items),
|
|
array__init(L, H, Item, Array1),
|
|
array__insert_items(Array1, L1, Items, Array).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__from_list(List, Array) :-
|
|
(
|
|
List = [Head | Tail]
|
|
->
|
|
list__length(List, Len),
|
|
Len1 is Len - 1,
|
|
array__init(0, Len1, Head, Array0),
|
|
array__insert_items(Array0, 1, Tail, Array)
|
|
;
|
|
error("Cannot create an array with zero elements")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred array__insert_items(array(T), int, list(T), array(T)).
|
|
:- mode array__insert_items(in, in, in, out) is det.
|
|
|
|
array__insert_items(Array, _N, [], Array).
|
|
array__insert_items(Array0, N, [Head|Tail], Array) :-
|
|
array__set(Array0, N, Head, Array1),
|
|
N1 is N + 1,
|
|
array__insert_items(Array1, N1, Tail, Array).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
array__to_list(Array, List) :-
|
|
array__bounds(Array, Low, High),
|
|
array__fetch_items(Array, Low, High, List).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred array__fetch_items(array(T), int, int, list(T)).
|
|
:- mode array__fetch_items(in, in, in, out) is det.
|
|
|
|
array__fetch_items(Array, Low, High, List) :-
|
|
(
|
|
Low > High
|
|
->
|
|
List = []
|
|
;
|
|
Low1 is Low + 1,
|
|
array__fetch_items(Array, Low1, High, List0),
|
|
array__search_2(Array, Low, Item),
|
|
List = [Item|List0]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|