12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Growable, mutable vector} *)typerw=[`RW]typero=[`RO]type'asequence=('a->unit)->unittype'aiter=('a->unit)->unittype'aklist=unit->[`Nil|`Consof'a*'aklist]type'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.;
shrink 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_seq 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_seq 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_seq Iter.(1 -- 5) in
let b = of_seq 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.vecixletremovevi=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-1thenv.vec.(i)<-v.vec.(v.size-1);(* remove one element *)v.size<-v.size-1;fill_with_junk_v.vecv.size1letappend_iterai=i(funx->pushax)letappend_std_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 = CCOpt.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_seq v1) =
Iter.(to_list (append (of_list l1) (to_seq 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_seq 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')
*)letshrinkvn=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_seq Iter.(1 -- 10) in
shrink 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
shrink 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 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'pv=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' (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' 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' (fun s -> String.length s <= 1) v;
assert_equal 1 (length v);
assert_equal "a" (get v 0);
Gc.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_std_seqfv=letv'=create()initer(funx->letseq=fxinappend_std_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_std_seq?(init=create())seq=append_std_seqinitseq;init(*$T
of_seq Iter.(1 -- 10) |> to_list = CCList.(1 -- 10)
*)letto_itervk=iterkvletto_iter_revvk=letn=v.sizeinfori=n-1downto0dok(Array.unsafe_getv.veci)doneletto_std_seqv=letrecauxi()=ifi>=sizevthenSeq.NilelseSeq.Cons(v.vec.(i),aux(i+1))inaux0letto_std_seq_revv=letrecauxi()=ifi<0||i>sizevthenSeq.NilelseSeq.Cons(v.vec.(i),aux(i-1))inaux(sizev-1)letof_seq=of_iterletto_seq=to_iterletto_seq_rev=to_iter_revletappend_seq=append_iterletflat_map_seq=flat_map_iter(*$Q
Q.(list int) (fun l -> \
let v= of_list l in v |> to_seq_rev |> Iter.to_rev_list = l)
*)letslice_seqvstartlen=assert(start>=0&&len>=0);funk->assert(start+len<=v.size);fori=starttostart+len-1doletx=Array.unsafe_getv.veciinkxdone(*$T
slice_seq (of_list [0;1;2;3;4]) 1 3 |> CCList.of_seq = [1;2;3]
slice_seq (of_list [0;1;2;3;4]) 1 4 |> CCList.of_seq = [1;2;3;4]
slice_seq (of_list [0;1;2;3;4]) 0 5 |> CCList.of_seq = [0;1;2;3;4]
*)letslicev=(v.vec,0,v.size)letfill_empty_slots_withvx:unit=ifcapacityv>lengthvthen(Array.fillv.vec(lengthv)(capacityv-lengthv)x;)(* 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
ignore (pop_exn v :string);
assert_equal ~printer:string_of_int 1 (length v);
assert_equal ~printer:CCFun.id "a" (get v 0);
fill_empty_slots_with v "";
Gc.major();
assert_equal None (Weak.get w 0);
*)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)
*)letof_klist?(init=create())l=letrecauxl=matchl()with|`Nil->init|`Cons(x,l')->pushinitx;auxl'inauxlletto_klistv=letrecauxi()=ifi=v.sizethen`Nilelse`Cons(v.vec.(i),aux(i+1))inaux0letto_string?(start="")?(stop="")?(sep=", ")item_to_stringv=start^(to_listv|>List.mapitem_to_string|>String.concatsep)^stopletpp?(start="")?(stop="")?(sep=", ")pp_itemfmtv=Format.pp_print_stringfmtstart;iteri(funix->ifi>0then(Format.pp_print_stringfmtsep;Format.pp_print_cutfmt());pp_itemfmtx)v;Format.pp_print_stringfmtstopincludeCCShimsMkLet_.Make2(structtypenonrec('a,'e)t=('a,'e)tlet(>|=)=(>|=)let(>>=)=(>>=)letmonoid_producta1a2=monoid_product(funxy->x,y)a1a2end)