Update Iter.ml to use mutable fields instead of refs (#44)

Update Iter.ml to use mutable fields instead of refs

`type 'a node = Nil | Cons of 'a array * int ref * 'a node ref` was changed to `type 'a node = Nil | Cons of { a : 'a array; mutable n : int; mutable tl : 'a node }` and all functions in MList were updated accordingly
This commit is contained in:
ilo Kali 2024-01-09 17:38:47 -05:00 committed by GitHub
parent 4f47de66fe
commit 92d0022079
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -189,63 +189,73 @@ let keep_error seq k =
(** Mutable unrolled list to serve as intermediate storage *) (** Mutable unrolled list to serve as intermediate storage *)
module MList = struct module MList = struct
type 'a node = Nil | Cons of 'a array * int ref * 'a node ref type 'a node = Nil | Cons of { a : 'a array; mutable n : int; mutable tl : 'a node }
(* build and call callback on every element *) (* build and call callback on every element *)
let of_iter_with seq k = let of_iter_with seq k =
let start = ref Nil in
let chunk_size = ref 8 in let chunk_size = ref 8 in
(* fill the list. prev: tail-reference from previous node *) let acc = ref Nil in
let prev, cur = ref start, ref Nil in let cur = ref Nil in
let tail = ref Nil in
let[@inline] replace_tail () =
match !acc with
| Nil -> acc := !cur
| _ ->
match !tail with
| Nil -> ()
| Cons r -> r.tl <- !cur
in
seq (fun x -> seq (fun x ->
k x; k x;
(* callback *) (* callback *)
match !cur with match !cur with
| Nil -> | Nil ->
let n = !chunk_size in let n = !chunk_size in
if n < 4096 then chunk_size := 2 * !chunk_size; if n < 4096 then chunk_size := 2 * n;
cur := Cons (Array.make n x, ref 1, ref Nil) cur := Cons {a=Array.make n x; n = 1; tl = Nil}
| Cons (a, n, next) -> | Cons r ->
assert (!n < Array.length a); assert (r.n < Array.length r.a);
a.(!n) <- x; r.a.(r.n) <- x;
incr n; r.n <- succ r.n;
if !n = Array.length a then ( if r.n = Array.length r.a then (
!prev := !cur; replace_tail ();
prev := next; tail := !cur;
cur := Nil cur := Nil
)); ));
!prev := !cur; replace_tail ();
!start !acc
let of_iter seq = of_iter_with seq (fun _ -> ()) let of_iter seq = of_iter_with seq (fun _ -> ())
let rec iter f l = let rec iter f l =
match l with match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons {a; n; tl} ->
for i = 0 to !n - 1 do for i = 0 to n - 1 do
f a.(i) f a.(i)
done; done;
iter f !tl iter f tl
let iteri f l = let iteri f l =
let rec iteri i f l = let rec iteri i f l =
match l with match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons {a; n; tl} ->
for j = 0 to !n - 1 do for j = 0 to n - 1 do
f (i + j) a.(j) f (i + j) a.(j)
done; done;
iteri (i + !n) f !tl iteri (i + n) f tl
in in
iteri 0 f l iteri 0 f l
let rec iter_rev f l = let rec iter_rev f l =
match l with match l with
| Nil -> () | Nil -> ()
| Cons (a, n, tl) -> | Cons {a; n; tl} ->
iter_rev f !tl; iter_rev f tl;
for i = !n - 1 downto 0 do for i = n - 1 downto 0 do
f a.(i) f a.(i)
done done
@ -253,7 +263,7 @@ module MList = struct
let rec len acc l = let rec len acc l =
match l with match l with
| Nil -> acc | Nil -> acc
| Cons (_, n, tl) -> len (acc + !n) !tl | Cons {n; tl; _} -> len (acc + n) tl
in in
len 0 l len 0 l
@ -261,8 +271,8 @@ module MList = struct
let rec get l i = let rec get l i =
match l with match l with
| Nil -> raise (Invalid_argument "MList.get") | Nil -> raise (Invalid_argument "MList.get")
| Cons (a, n, _) when i < !n -> a.(i) | Cons {a; n; _} when i < n -> a.(i)
| Cons (_, n, tl) -> get !tl (i - !n) | Cons {n; tl; _} -> get tl (i - n)
let to_iter l k = iter k l let to_iter l k = iter k l
@ -273,11 +283,11 @@ module MList = struct
let rec get_next _ = let rec get_next _ =
match !cur with match !cur with
| Nil -> None | Nil -> None
| Cons (_, n, tl) when !i = !n -> | Cons {n; tl; _} when !i = n ->
cur := !tl; cur := tl;
i := 0; i := 0;
get_next arg get_next arg
| Cons (a, _, _) -> | Cons {a; _} ->
let x = a.(!i) in let x = a.(!i) in
incr i; incr i;
Some x Some x
@ -290,8 +300,8 @@ module MList = struct
let rec make (l, i) () = let rec make (l, i) () =
match l with match l with
| Nil -> Seq.Nil | Nil -> Seq.Nil
| Cons (_, n, tl) when i = !n -> make (!tl, 0) () | Cons {n; tl; _} when i = n -> make (tl, 0) ()
| Cons (a, _, _) -> Seq.Cons (a.(i), make (l, i + 1)) | Cons {a;_} -> Seq.Cons (a.(i), make (l, i + 1))
in in
make (l, 0) make (l, 0)
end end