1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Growable, mutable vector} *)typerw=[`RW]typero=[`RO]type'aiter=('a->unit)->unittype'agen=unit->'aoptiontype'aequal='a->'a->booltype'aord='a->'a->inttype'aprinter=Format.formatter->'a->unit(** A vector of 'a. *)type('a,'mut)t={mutablesize:int;mutablevec:'aarray;}type'avector=('a,rw)ttype'aro_vector=('a,ro)texternalas_float_arr:'aarray->floatarray="%identity"externalas_obj_arr:'aarray->Obj.tarray="%identity"letfill_with_junk_(a:_array)ilen:unit=ifObj.(tag(repra)=double_array_tag)then(Array.fill(as_float_arra)ilen0.;)else(Array.fill(as_obj_arra)ilen(Obj.repr());)letfreezev={size=v.size;vec=v.vec;}letfreeze_copyv={size=v.size;vec=Array.subv.vec0v.size;}letcreate()={size=0;vec=[||];}letcreate_with?(capacity=128)x=letvec=Array.makecapacityxinfill_with_junk_vec0capacity;{size=0;vec}(*$T
(create_with ~capacity:200 1 |> capacity) >= 200
*)letreturnx={size=1;vec=[|x|];}(*$T
return 42 |> to_list = [42]
return 42 |> length = 1
*)letmakenx={size=n;vec=Array.makenx;}letinitnf={size=n;vec=Array.initnf;}(* is the underlying array empty? *)letarray_is_empty_v=Array.lengthv.vec=0(* resize the underlying array using x to temporarily fill the array *)letresize_vnewcapacityx=assert(newcapacity>=v.size);assert(not(array_is_empty_v));letnew_vec=Array.makenewcapacityxinArray.blitv.vec0new_vec0v.size;fill_with_junk_new_vecv.size(newcapacity-v.size);v.vec<-new_vec;()(*$T
let v = create_with ~capacity:10 1 in \
ensure v 200; capacity v >= 200
*)(*$T
let v = create() in push v 0.; push v 1.; push v 2.; 3=length v
let v = create() in push v 1.; push v 2.; push v 3.; 6. = (get v 0 +. get v 1 +. get v 2)
let v = create() in push v 0; push v 1; push v 2; 3=length v
let v = create() in push v 1; push v 2; push v 3; 6 = (get v 0 + get v 1 + get v 2)
let v = create() in push v "a"; push v "b"; push v "c"; 3=length v
let v = create() in push v "a"; push v "b"; push v "c"; "abc" = String.concat "" (to_list v)
*)(*$R
let v = create() in
push v 0.; push v 1.;
clear v;
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
truncate v 2;
assert_equal 1. (fold (+.) 0. v);
clear v;
assert_equal 0 (size v);
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
assert_equal (1. +. 7. +. 10. +. 12.) (fold (+.) 0. v);
*)(* grow the array, using [x] as a filler if required *)letgrow_with_v~filler:x=ifarray_is_empty_vthen(letlen=4inv.vec<-Array.makelenx;(* do not really use [x], it was just for knowing the type *)fill_with_junk_v.vec0len;)else(letn=Array.lengthv.vecinletsize=min(2*n+3)Sys.max_array_lengthinifsize=nthenfailwith"vec: can't grow any further";resize_vsizev.vec.(0))(* v is not empty; ensure it has at least [size] slots.
Use a doubling-size strategy so that calling many times [ensure] will
behave well *)letensure_assuming_not_empty_v~size=ifsize>Sys.max_array_lengththenfailwith"vec.ensure: size too big"else(letn=ref(max8(Array.lengthv.vec))inwhile!n<sizedon:=minSys.max_array_length(2*!n)done;resize_v!nv.vec.(0))letensure_with~initvsize=ifarray_is_empty_vthen(v.vec<-Array.makesizeinit;fill_with_junk_v.vec0size)else(ensure_assuming_not_empty_v~size)letensurevsize=ifnot(array_is_empty_v)then(ensure_assuming_not_empty_v~size)letclearv=v.size<-0(*$R
let v = of_iter Iter.(1 -- 10) in
OUnit.assert_equal 10 (size v);
clear v;
OUnit.assert_equal 0 (size v);
OUnit.assert_bool "empty_after_clear" (Iter.is_empty (to_iter v));
*)letclear_and_resetv=v.size<-0;v.vec<-[||](* TODO*)(*
let v = create() in
let a = Weak.create 1 in
push v ("hello"^"world");
Weak.set a 0 (Some (get v 0));
Gc.full_major(); Gc.compact();
OUnit.assert_bool "is alive" (Weak.check a 0);
Gc.full_major(); Gc.compact();
OUnit.assert_equal None (Weak.get a 0);
*)letis_emptyv=v.size=0letpush_unsafe_vx=Array.unsafe_setv.vecv.sizex;v.size<-v.size+1letpushvx=ifv.size=Array.lengthv.vecthengrow_with_v~filler:x;push_unsafe_vx(*$T
let v = create () in push v 1; to_list v = [1]
let v = of_list [1;2;3] in push v 4; to_list v = [1;2;3;4]
*)(** Add all elements of b to a *)letappendab=ifarray_is_empty_athen(ifarray_is_empty_bthen()else(a.vec<-Array.copyb.vec;a.size<-b.size))else(ensure_assuming_not_empty_a~size:(a.size+b.size);assert(Array.lengtha.vec>=a.size+b.size);Array.blitb.vec0a.veca.sizeb.size;a.size<-a.size+b.size)(*$T
let v1 = init 5 (fun i->i) and v2 = init 5 (fun i->i+5) in \
append v1 v2; to_list v1 = CCList.(0--9)
let empty = create () and v2 = init 5 (fun i->i) in \
append empty v2; to_list empty = CCList.(0--4)
let v1 = init 5 (fun i->i) and empty = create () in \
append v1 empty; to_list v1 = CCList.(0--4)
let v = init 3 (fun i->i) in \
append v v; to_list v = [0; 1; 2; 0; 1; 2]
let empty = create () in \
append empty empty; to_list empty = []
*)(*$R
let a = of_iter Iter.(1 -- 5) in
let b = of_iter Iter.(6 -- 10) in
append a b;
OUnit.assert_equal 10 (size a);
OUnit.assert_equal (Iter.to_array Iter.(1 -- 10)) (to_array a);
OUnit.assert_equal (Iter.to_array Iter.(6 -- 10)) (to_array b);
*)letgetvi=ifi<0||i>=v.sizetheninvalid_arg"CCVector.get";Array.unsafe_getv.veciletsetvix=ifi<0||i>=v.sizetheninvalid_arg"CCVector.set";Array.unsafe_setv.vecixletremove_and_shiftvi=ifi<0||i>=v.sizetheninvalid_arg"CCVector.remove";(* if v.(i) not the last element, then put last element at index i *)ifi<v.size-1thenArray.blitv.vec(i+1)v.veci(v.size-i-1);(* remove one element *)v.size<-v.size-1;fill_with_junk_v.vecv.size1letremove_unorderedvi=ifi<0||i>=v.sizetheninvalid_arg"CCVector.remove_unordered";(* if v.(i) not the last element, then put last element at index i *)ifi<v.size-1thenv.vec.(i)<-v.vec.(v.size-1);(* remove one element *)v.size<-v.size-1;fill_with_junk_v.vecv.size1(*$Q remove_and_shift
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let v1 = of_list l and v2 = of_list l in \
remove_and_shift v1 9; \
remove_unordered v2 9; \
to_list v1 = (to_list v2))
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let l = List.sort CCInt.compare l in \
let v = of_list l in\
remove_and_shift v 3; \
to_list v = (List.sort CCInt.compare (to_list v)))
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let l = List.sort CCInt.compare l in \
let v1 = of_list l and v2 = of_list l in \
remove_and_shift v1 3; \
remove_unordered v2 3; \
to_list v1 = (List.sort CCInt.compare (to_list v2)))
*)letappend_iterai=i(funx->pushax)letappend_seqaseq=Seq.iter(funx->pushax)seqletappend_arrayab=letlen_b=Array.lengthbinifarray_is_empty_athen(a.vec<-Array.copyb;a.size<-len_b;)else(ensure_assuming_not_empty_a~size:(a.size+len_b);Array.blitb0a.veca.sizelen_b;a.size<-a.size+len_b)(*$T
let v1 = init 5 (fun i->i) and v2 = Array.init 5 (fun i->i+5) in \
append_array v1 v2; to_list v1 = CCList.(0--9)
let empty = create () in \
append_array empty CCArray.(0--5); to_list empty = CCList.(0--5)
let v1 = init 5 (fun i->i) in \
append_array v1 [| |]; to_list v1 = CCList.(0--4)
let empty = create () in \
append_array empty [| |]; to_list empty = []
*)letappend_listab=matchbwith|[]->()|x::_->(* need to push at least one elem *)letlen_a=a.sizeinletlen_b=List.lengthbinensure_with~init:xa(len_a+len_b);List.iter(push_unsafe_a)b;()(*$Q
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_list v l2; \
to_list v = (l1 @ l2))
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_list v l2; \
length v = List.length l1 + List.length l2)
*)letrecappend_genab=matchb()with|None->()|Somex->pushax;append_genab(*$Q
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_gen v (Gen.of_list l2); \
to_list v = (l1 @ l2))
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_gen v (Gen.of_list l2); \
length v = List.length l1 + List.length l2)
*)(*$inject
let gen x =
let small = length in
let print = CCOption.map (fun p x -> Q.Print.list p (CCVector.to_list x)) x.Q.print in
Q.make ?print ~small Q.Gen.(list x.Q.gen >|= of_list)
*)(*$QR
(Q.pair (gen Q.int) (gen Q.int)) (fun (v1,v2) ->
let l1 = to_list v1 in
append v1 v2;
Iter.to_list (to_iter v1) =
Iter.(to_list (append (of_list l1) (to_iter v2)))
)
*)letequaleqv1v2=v1.size=v2.size&&letn=v1.sizeinletrecchecki=i=n||(eq(getv1i)(getv2i)&&check(i+1))incheck0(*$T
equal (=) (create ()) (create ())
equal (=) (return 42) (return 42)
not (equal (=) (create ()) (return 42))
not (equal (=) (return 42) (create ()))
*)(*$Q
Q.(let g = list_of_size Gen.(0--10) small_int in pair g g) (fun (l1,l2) -> \
equal (=) (of_list l1) (of_list l2) = (l1=l2))
*)(*$QR
Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
equal (=) v1 v2 = (l1=l2))
*)letcomparecmpv1v2=letn=minv1.sizev2.sizeinletrecchecki=ifi=nthencomparev1.sizev2.sizeelse(letc=cmp(getv1i)(getv2i)inifc=0thencheck(i+1)elsec)incheck0(*$QR
Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
compare Stdlib.compare v1 v2 = CCList.compare Stdlib.compare l1 l2)
*)exceptionEmptyletpop_exnv=ifv.size=0thenraiseEmpty;letnew_size=v.size-1inv.size<-new_size;letx=v.vec.(new_size)in(* free last element *)fill_with_junk_v.vecnew_size1;xletpopv=trySome(pop_exnv)withEmpty->Nonelettopv=ifv.size=0thenNoneelseSomev.vec.(v.size-1)lettop_exnv=ifv.size=0thenraiseEmpty;v.vec.(v.size-1)(*$T
1 -- 10 |> top = Some 10
create () |> top = None
1 -- 10 |> top_exn = 10
*)letcopyv={size=v.size;vec=Array.subv.vec0v.size;}(*$T
(let v = of_list [1;2;3] in let v' = copy v in \
to_list v' = [1;2;3])
create () |> copy |> is_empty
*)(*$R
let v = of_iter Iter.(1 -- 100) in
OUnit.assert_equal 100 (size v);
let v' = copy v in
OUnit.assert_equal 100 (size v');
clear v';
OUnit.assert_bool "empty" (is_empty v');
OUnit.assert_bool "not_empty" (not (is_empty v));
*)(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
let v' = copy v in
equal (=) v v')
*)lettruncatevn=letold_size=v.sizeinifn<old_sizethen(v.size<-n;(* free elements by erasing them *)fill_with_junk_v.vecn(old_size-n);)(*$R
let v = of_iter Iter.(1 -- 10) in
truncate v 5;
OUnit.assert_equal [1;2;3;4;5] (to_list v);
*)(*$QR
(gen Q.small_int) (fun v ->
let n = size v / 2 in
let l = to_list v in
let h = Iter.(to_list (take n (of_list l))) in
let v' = copy v in
truncate v' n;
h = to_list v'
)
*)letshrink_to_fitv:unit=ifv.size=0then(v.vec<-[||])elseifv.size<Array.lengthv.vecthen(v.vec<-Array.subv.vec0v.size)(*$QR
(gen Q.small_int) (fun v ->
let v' = copy v in
shrink_to_fit v;
to_list v = to_list v'
)
*)letsort'cmpv=(* possibly copy array (to avoid junk at its end), then sort the array *)leta=ifArray.lengthv.vec=v.sizethenv.vecelseArray.subv.vec0v.sizeinArray.fast_sortcmpa;v.vec<-aletsortcmpv=letv'={size=v.size;vec=Array.subv.vec0v.size;}inArray.sortcmpv'.vec;v'(*$QR
(gen Q.small_int) (fun v ->
let v' = copy v in
sort' Stdlib.compare v';
let l = to_list v' in
List.sort Stdlib.compare l = l
)
*)letuniq_sortcmpv=sort'cmpv;letn=v.sizein(* traverse to remove duplicates. i= current index,
j=current append index, j<=i. new_size is the size
the vector will have after removing duplicates. *)letrectraverseprevij=ifi>=nthen()(* done traversing *)elseifcmpprevv.vec.(i)=0then(v.size<-v.size-1;traverseprev(i+1)j)(* duplicate, remove it *)else(v.vec.(j)<-v.vec.(i);traversev.vec.(i)(i+1)(j+1))(* keep it *)inifv.size>0thentraversev.vec.(0)11(* start at 1, to get the first element in hand *)(*$T
let v = of_list [1;4;5;3;2;4;1] in \
uniq_sort Stdlib.compare v; to_list v = [1;2;3;4;5]
*)(*$QR & ~long_factor:10
Q.(small_list small_int) (fun l ->
let v = of_list l in
uniq_sort Stdlib.compare v;
to_list v = (CCList.sort_uniq ~cmp:Stdlib.compare l))
*)letiterkv=letn=v.sizeinfori=0ton-1dok(Array.unsafe_getv.veci)doneletiterikv=letn=v.sizeinfori=0ton-1doki(Array.unsafe_getv.veci)done(*$T
let v = (0--6) in \
iteri (fun i x -> if i = 3 then remove_unordered v i) v; length v = 6
*)letmapfv=ifarray_is_empty_vthencreate()else(letvec=Array.initv.size(funi->f(Array.unsafe_getv.veci))in{size=v.size;vec;})(*$T
let v = create() in push v 1; push v 2; push v 3; \
to_list (map string_of_int v) = ["1"; "2"; "3"]
*)(*$QR
Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (map f v) = List.map f l)
*)letmapifv=ifarray_is_empty_vthencreate()else(letvec=Array.initv.size(funi->fi(Array.unsafe_getv.veci))in{size=v.size;vec;})(*$T mapi
let v = create() in push v 1; push v 2; push v 3; \
to_list (mapi (fun i e -> Printf.sprintf "%i %i" i e) v) = ["0 1"; "1 2"; "2 3"]
*)(*$QR mapi
Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int))
(fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (mapi f v) = List.mapi f l)
*)letmap_in_placefv=iteri(funix->Array.unsafe_setv.veci(fx))v(*$QR
Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
map_in_place f v;
to_list v = List.map f l)
*)letfilter_in_placepv=leti=ref0in(* cur element *)letj=ref0in(* cur insertion point *)letn=v.sizeinwhile!i<ndoifpv.vec.(!i)then((* move element i at the first empty slot.
invariant: i >= j*)if!i>!jthenv.vec.(!j)<-v.vec.(!i);incri;incrj)elseincridone;(* free elements *)fill_with_junk_v.vec!j(v.size-!j);v.size<-!j(*$T
let v = 1 -- 10 in filter_in_place (fun x->x<4) v; \
to_list v = [1;2;3]
*)(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_in_place f v;
to_list v = List.filter f l)
*)letfilterpv=ifarray_is_empty_vthen(create())else(letv'=create_with~capacity:v.sizev.vec.(0)initer(funx->ifpxthenpush_unsafe_v'x)v;v')(*$T
filter (fun x-> x mod 2=0) (of_list [1;2;3;4;5]) |> to_list = [2;4]
filter (fun x-> x mod 2=0) (1 -- 1_000_000) |> length = 500_000
*)(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter f v) = List.filter f l)
*)letfoldfaccv=letrecfoldacci=ifi=v.sizethenaccelseletx=Array.unsafe_getv.veciinfold(faccx)(i+1)infoldacc0(*$T
fold (+) 0 (of_list [1;2;3;4;5]) = 15
fold (+) 0 (create ()) = 0
*)(*$QR
Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
fold f 0 v = List.fold_left f 0 l)
*)letexistspv=letn=v.sizeinletrecchecki=ifi=nthenfalseelsepv.vec.(i)||check(i+1)incheck0(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
exists f v = List.exists f l)
*)letfor_allpv=letn=v.sizeinletrecchecki=ifi=nthentrueelsepv.vec.(i)&&check(i+1)incheck0(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
for_all f v = List.for_all f l)
*)letmember~eqxv=exists(eqx)vletfind_internal_pv=letn=v.sizeinletrecchecki=ifi=nthenraise_notraceNot_foundelse(letx=v.vec.(i)inifpxthenxelsecheck(i+1))incheck0letfind_exnpv=tryfind_internal_pvwithNot_found->raiseNot_foundletfindpv=trySome(find_internal_pv)withNot_found->None(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
find f v = CCList.find_pred f l)
*)letfind_mapfv=letn=v.sizeinletrecsearchi=ifi=nthenNoneelsematchfv.vec.(i)with|None->search(i+1)|Some_asres->resinsearch0(*$Q
Q.(list small_int) (fun l -> \
let v = of_list l in \
let f x = x>30 && x < 35 in \
find_map (fun x -> if f x then Some x else None) v = find f v)
*)letfilter_mapfv=letv'=create()initer(funx->matchfxwith|None->()|Somey->pushv'y)v;v'(*$QR
Q.(pair (fun1 Observable.int (option bool)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter_map f v) = CCList.filter_map f l)
*)letfilter_map_in_placefv=leti=ref0in(* cur element *)letj=ref0in(* cur insertion point *)letn=v.sizeinwhile!i<ndomatchfv.vec.(!i)with|None->incri(* drop *)|Somey->(* move element i at the first empty slot.
invariant: i >= j*)v.vec.(!j)<-y;incri;incrjdone;(* free elements *)fill_with_junk_v.vec!j(v.size-!j);v.size<-!j(*$QR
Q.(pair (fun1 Observable.int (option small_int)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_map_in_place f v;
to_list v = CCList.filter_map f l)
*)(* check it frees memory properly *)(*$R
let s = "coucou" ^ "lol" in
let w = Weak.create 1 in
Weak.set w 0 (Some s);
let v = of_list ["a"; s] in
filter_in_place (fun s -> String.length s <= 1) v;
assert_equal 1 (length v);
assert_equal "a" (get v 0);
Gc.full_major();
assert_equal None (Weak.get w 0);
*)letflat_mapfv=letv'=create()initer(funx->iter(pushv')(fx))v;v'letflat_map_iterfv=letv'=create()initer(funx->letseq=fxinappend_iterv'seq)v;v'letflat_map_seqfv=letv'=create()initer(funx->letseq=fxinappend_seqv'seq)v;v'letflat_map_listfv=letv'=create()initer(funx->letl=fxinappend_listv'l)v;v'letmonoid_productfa1a2:_t=letna1=a1.sizeininit(na1*a2.size)(funi_prod->leti=i_prodmodna1inletj=i_prod/na1infa1.vec.(i)a2.vec.(j))(*$= & ~cmp:(=) ~printer:Q.Print.(list int)
[ 11; 12; 21; 22 ] (List.sort CCInt.compare @@ \
to_list @@ monoid_product (+) (of_list [10; 20]) (of_list [1; 2]))
[ 11; 12; 13; 14 ] (List.sort CCInt.compare @@ \
to_list @@ monoid_product (+) (of_list [10]) (of_list [1; 2; 3; 4]))
*)let(>>=)xf=flat_mapfxlet(>|=)xf=mapfxletrev_in_placev=ifv.size>0then(letn=v.sizeinletvec=v.vecinfori=0to(n-1)/2doletx=Array.unsafe_getveciinlety=Array.unsafe_getvec(n-i-1)inArray.unsafe_setveciy;Array.unsafe_setvec(n-i-1)x;done)(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
rev_in_place v;
to_list v = List.rev l)
*)letrevv=letv'=copyvinrev_in_placev';v'(*$T
rev (of_list [1;2;3;4]) |> to_list = [4;3;2;1]
rev (of_list [1;2;3;4;5]) |> to_list = [5;4;3;2;1]
rev (create ()) |> to_list = []
*)(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
to_list (rev v) = List.rev l)
*)letrev_iterfv=letn=v.sizeinfori=n-1downto0dof(Array.unsafe_getv.veci)done(*$T
let v = of_list [1;2;3] in (fun f->rev_iter f v) |> Iter.to_list = [3;2;1]
*)(*$Q
Q.(list int) (fun l -> \
let v = of_list l in \
(fun f->rev_iter f v) |> Iter.to_list = List.rev l)
*)letsizev=v.sizeletlengthv=v.sizeletcapacityv=Array.lengthv.vecletunsafe_get_arrayv=v.vecletof_iter?(init=create())seq=append_iterinitseq;initletof_seq?(init=create())seq=append_seqinitseq;init(*$T
of_iter Iter.(1 -- 10) |> to_list = CCList.(1 -- 10)
*)letto_itervk=iterkvletto_iter_revvk=letn=v.sizeinfori=n-1downto0dok(Array.unsafe_getv.veci)doneletto_seqv=letrecauxi()=ifi>=sizevthenSeq.NilelseSeq.Cons(v.vec.(i),aux(i+1))inaux0letto_seq_revv=letrecauxi()=ifi<0||i>sizevthenSeq.NilelseSeq.Cons(v.vec.(i),aux(i-1))inaux(sizev-1)(*$Q
Q.(list int) (fun l -> \
let v= of_list l in v |> to_iter_rev |> Iter.to_rev_list = l)
*)letslice_itervstartlen=assert(start>=0&&len>=0);funk->assert(start+len<=v.size);fori=starttostart+len-1doletx=Array.unsafe_getv.veciinkxdone(*$T
slice_iter (of_list [0;1;2;3;4]) 1 3 |> CCList.of_iter = [1;2;3]
slice_iter (of_list [0;1;2;3;4]) 1 4 |> CCList.of_iter = [1;2;3;4]
slice_iter (of_list [0;1;2;3;4]) 0 5 |> CCList.of_iter = [0;1;2;3;4]
*)letslicev=(v.vec,0,v.size)let(--)ij=ifi>jtheninit(i-j+1)(funk->i-k)elseinit(j-i+1)(funk->i+k)(*$T
(1 -- 4) |> to_list = [1;2;3;4]
(4 -- 1) |> to_list = [4;3;2;1]
(0 -- 0) |> to_list = [0]
*)(*$Q
Q.(pair small_int small_int) (fun (a,b) -> \
(a -- b) |> to_list = CCList.(a -- b))
*)let(--^)ij=ifi=jthencreate()elseifi>jtheninit(i-j)(funk->i-k)elseinit(j-i)(funk->i+k)(*$Q
Q.(pair small_int small_int) (fun (a,b) -> \
(a --^ b) |> to_list = CCList.(a --^ b))
*)letof_arraya=ifArray.lengtha=0thencreate()else{size=Array.lengtha;vec=Array.copya;}letof_listl=matchlwith|[]->create()|[x]->returnx|[x;y]->{size=2;vec=[|x;y|]}|x::_->letv=create_with~capacity:(List.lengthl)xinList.iter(push_unsafe_v)l;v(*$T
of_list CCList.(1--300_000) |> to_list = CCList.(1--300_000)
*)letto_arrayv=Array.subv.vec0v.sizeletto_listv=List.rev(fold(funaccx->x::acc)[]v)letof_gen?(init=create())g=letrecauxg=matchg()with|None->init|Somex->pushinitx;auxginauxgletto_genv=leti=ref0infun()->if!i<v.sizethen(letx=v.vec.(!i)inincri;Somex)elseNone(*$T
let v = (1--10) in to_list v = Gen.to_list (to_gen v)
*)letto_string?(start="")?(stop="")?(sep=", ")item_to_stringv=start^(to_listv|>List.mapitem_to_string|>String.concatsep)^stopletpp?(pp_start=fun_()->())?(pp_stop=fun_()->())?(pp_sep=funfmt()->Format.fprintffmt",@ ")pp_itemfmtv=pp_startfmt();iteri(funix->ifi>0thenpp_sepfmt();pp_itemfmtx)v;pp_stopfmt()includeCCShimsMkLet_.Make2(structtypenonrec('a,'e)t=('a,'e)tlet(>|=)=(>|=)let(>>=)=(>>=)letmonoid_producta1a2=monoid_product(funxy->x,y)a1a2end)