diff --git a/benchs/run_benchs.ml b/benchs/run_benchs.ml index dddf908ed..b565e6687 100644 --- a/benchs/run_benchs.ml +++ b/benchs/run_benchs.ml @@ -166,6 +166,9 @@ module L = struct let s1 = Sek.Persistent.of_array 0 (Array.of_list l1) in let s2 = Sek.Persistent.of_array 0 (Array.of_list l2) in let s3 = Sek.Persistent.of_array 0 (Array.of_list l3) in + let q1 = CCFQueue.of_list l1 in + let q2 = CCFQueue.of_list l2 in + let q3 = CCFQueue.of_list l3 in let bench_list l1 l2 l3 () = opaque_ignore List.(append (append l1 l2) l3) in @@ -181,6 +184,12 @@ module L = struct let bench_sek l1 l2 l3 () = opaque_ignore Sek.Persistent.(concat (concat l1 l2) l3) in + let bench_ccfqueue l1 l2 l3 () = + opaque_ignore CCFQueue.(append (append l1 l2) l3) + in + let bench_ccfqueue_r l1 l2 l3 () = + opaque_ignore CCFQueue.(append l1 (append l2 l3)) + in B.throughputN time ~repeat [ "CCList.append", bench_list l1 l2 l3, (); @@ -188,6 +197,8 @@ module L = struct "CCFun_vec.append", bench_funvec v1 v2 v3, (); "Pvec.append", bench_pvec pv1 pv2 pv3, (); "Sek.concat", bench_sek s1 s2 s3, (); + "CCFQueue.append", bench_ccfqueue q1 q2 q3, (); + "CCFQueue.append (r-assoc)", bench_ccfqueue_r q1 q2 q3, (); ] (* FLATTEN *) diff --git a/src/data/CCFQueue.ml b/src/data/CCFQueue.ml index 2fdf0234c..67be65b17 100644 --- a/src/data/CCFQueue.ml +++ b/src/data/CCFQueue.ml @@ -240,6 +240,11 @@ let add_iter_front seq q = seq (fun x -> l := x :: !l); List.fold_left (fun q x -> cons x q) q !l +let add_iter_front_rev q seq = + let q = ref q in + seq (fun x -> q := cons x !q); + !q + let add_iter_back q seq = let q = ref q in seq (fun x -> q := snoc !q x); @@ -269,11 +274,39 @@ let rec to_iter : 'a. 'a t -> 'a iter = k y); _digit_to_iter tail k +let _digit_to_iter_rev : type l. ('a, l) digit -> 'a iter = + fun d k -> + match d with + | Zero -> () + | One x -> k x + | Two (x, y) -> + k y; + k x + | Three (x, y, z) -> + k z; + k y; + k x + +let rec to_iter_rev : 'a. 'a t -> 'a iter = + fun q k -> + match q with + | Shallow d -> _digit_to_iter_rev d k + | Deep (_, hd, (lazy q'), tail) -> + _digit_to_iter_rev tail k; + to_iter_rev q' (fun (x, y) -> + k y; + k x); + _digit_to_iter_rev hd k + let append q1 q2 = match q1, q2 with | Shallow Zero, _ -> q2 | _, Shallow Zero -> q1 - | _ -> add_iter_back q1 (to_iter q2) + | _ -> + if size q1 < size q2 then + add_iter_front_rev q2 (to_iter_rev q1) + else + add_iter_back q1 (to_iter q2) let add_seq_front seq q = (* reversed seq *) diff --git a/src/data/CCFQueue.mli b/src/data/CCFQueue.mli index eaaad54b5..364866df2 100644 --- a/src/data/CCFQueue.mli +++ b/src/data/CCFQueue.mli @@ -86,7 +86,7 @@ val init : 'a t -> 'a t val append : 'a t -> 'a t -> 'a t (** Append two queues. Elements from the second one come after elements of the first one. - Linear in the size of the second queue. *) + Linear in the size of the shorter queue. *) val rev : 'a t -> 'a t (** Reverse the queue, [O(n)] complexity.