perf(bag): remove constant-time size

This commit is contained in:
Simon Cruanes 2019-02-16 13:38:43 -06:00
parent eea95346eb
commit c06e4025fa
2 changed files with 15 additions and 24 deletions

View file

@ -9,59 +9,53 @@
type 'a t = type 'a t =
| E | E
| L of 'a | L of 'a
| N of 'a t * 'a t * int (* size *) | N of 'a t * 'a t (* size *)
let empty = E let empty = E
let is_empty = function let[@inline] is_empty = function
| E -> true | E -> true
| L _ | N _ -> false | L _ | N _ -> false
let size = function let[@inline] return x = L x
| E -> 0
| L _ -> 1
| N (_,_,sz) -> sz
let return x = L x let[@inline] append a b = match a, b with
let append a b = match a, b with
| E, _ -> b | E, _ -> b
| _, E -> a | _, E -> a
| _ -> N (a, b, size a + size b) | _ -> N (a, b)
let cons x t = match t with let cons x t = match t with
| E -> L x | E -> L x
| L _ -> N (L x, t, 2) | L _ -> N (L x, t)
| N (_,_,sz) -> N (L x, t, sz+1) | N (_,_) -> N (L x, t)
let rec fold f acc = function let rec fold f acc = function
| E -> acc | E -> acc
| L x -> f acc x | L x -> f acc x
| N (a,b,_) -> fold f (fold f acc a) b | N (a,b) -> fold f (fold f acc a) b
let rec to_seq t yield = match t with let[@unroll 2] rec to_seq t yield = match t with
| E -> () | E -> ()
| L x -> yield x | L x -> yield x
| N (a,b,_) -> to_seq a yield; to_seq b yield | N (a,b) -> to_seq a yield; to_seq b yield
let iter f t = to_seq t f let[@inline] iter f t = to_seq t f
let equal f a b = let equal f a b =
let rec push x l = match x with let rec push x l = match x with
| E -> l | E -> l
| L _ -> x :: l | L _ -> x :: l
| N (a,b,_) -> push a (b::l) | N (a,b) -> push a (b::l)
in in
(* same-fringe traversal, using two stacks *) (* same-fringe traversal, using two stacks *)
let rec aux la lb = match la, lb with let rec aux la lb = match la, lb with
| [], [] -> true | [], [] -> true
| E::_, _ | _, E::_ -> assert false | E::_, _ | _, E::_ -> assert false
| N (x,y,_)::la, _ -> aux (push x (y::la)) lb | N (x,y)::la, _ -> aux (push x (y::la)) lb
| _, N(x,y,_)::lb -> aux la (push x (y::lb)) | _, N(x,y)::lb -> aux la (push x (y::lb))
| L x :: la, L y :: lb -> f x y && aux la lb | L x :: la, L y :: lb -> f x y && aux la lb
| [], L _::_ | [], L _::_
| L _::_, [] -> false | L _::_, [] -> false
in in
size a = size b &&
aux (push a []) (push b []) aux (push a []) (push b [])

View file

@ -9,7 +9,7 @@
type +'a t = private type +'a t = private
| E | E
| L of 'a | L of 'a
| N of 'a t * 'a t * int (* size *) | N of 'a t * 'a t
val empty : 'a t val empty : 'a t
@ -17,9 +17,6 @@ val is_empty : _ t -> bool
val return : 'a -> 'a t val return : 'a -> 'a t
val size : _ t -> int
(** Constant time *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
val append : 'a t -> 'a t -> 'a t val append : 'a t -> 'a t -> 'a t