exception OVERFLOW
type 'data stack = {
mutable stack: 'data array;
mutable size: int;
null_element: 'data;
}
let inc_size (stack: 'data stack) : unit =
if stack.size = Array.length stack.stack then begin
if stack.size = Sys.max_array_length then begin
raise OVERFLOW;
end;
let new_size =
let desired_size =
Tools.max_int 16 (2 * (Array.length stack.stack))
in
Pervasives.min Sys.max_array_length desired_size
in
let new_array =
Array.make new_size stack.null_element
in
Array.blit stack.stack 0 new_array 0 stack.size;
stack.stack <- new_array;
end
let shrink (stack: 'data stack) : unit =
if stack.size < Array.length stack.stack then begin
let new_array =
Array.make stack.size stack.null_element
in
Array.blit stack.stack 0 new_array 0 stack.size;
stack.stack <- new_array;
end
let create (null_element: 'data) : 'data stack = {
stack = [| |];
size = 0;
null_element = null_element;
}
let clear (stack: 'data stack) : unit =
stack.stack <- [| |];
stack.size <- 0
let is_empty (stack: 'data stack) : bool =
stack.size = 0
let size (stack: 'data stack) : int =
stack.size
let push (stack: 'data stack) (data: 'data) : unit =
inc_size stack;
stack.stack.(stack.size) <- data;
stack.size <- stack.size + 1
let top (stack: 'data stack) : 'data =
if stack.size = 0 then
raise Not_found;
stack.stack.(stack.size - 1)
let pop (stack: 'data stack) : 'data =
if stack.size = 0 then
raise Not_found;
let element =
stack.stack.(stack.size - 1)
in
stack.size <- stack.size - 1;
stack.stack.(stack.size) <- stack.null_element;
element
let remove_top (stack: 'data stack) : unit =
if stack.size = 0 then
raise Not_found;
stack.size <- stack.size - 1;
stack.stack.(stack.size) <- stack.null_element
let iter (func: 'data -> unit) (stack: 'data stack) : unit =
for i = 0 to stack.size - 1 do
func stack.stack.(i)
done
let fold (func: 'acc -> 'data -> 'acc) (acc: 'acc) (stack: 'data stack) : 'acc =
let rec fold' acc' i =
if i >= stack.size then
acc'
else
fold' (func acc' stack.stack.(i)) (i + 1)
in
fold' acc 0
let iter_stop (apply: 'data -> unit) (stop: 'data -> bool) (stack: 'data stack) : unit =
try
for i = 0 to stack.size - 1 do
if stop stack.stack.(i) then
raise Exit
else
apply stack.stack.(i)
done
with
| Exit ->
()
let map (func: 'data -> 'data) (stack: 'data stack) : 'data stack =
{ stack with
stack = Array.map func stack.stack;
}
let sort (func: 'data -> 'data -> int) (stack: 'data stack) : unit =
shrink stack;
Array.sort func stack.stack
let find (stack: 'data stack) (func: 'data -> int) : 'data =
if stack.size = 0 then
raise Not_found
else
let rec exists' (left: int) (right : int) =
let mid =
(left + right) / 2
in
let cmp =
func stack.stack.(mid)
in
if cmp = 0 then
stack.stack.(mid)
else if left >= right then
raise Not_found
else if cmp < 0 then
exists' left (mid - 1)
else
exists' (mid + 1) right
in
exists' 0 (stack.size - 1)