123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Array Slice} *)openCCShims_type'aiter=('a->unit)->unittype'asequence=('a->unit)->unittype'aklist=unit->[`Nil|`Consof'a*'aklist]type'agen=unit->'aoptiontype'aequal='a->'a->booltype'aord='a->'a->inttype'arandom_gen=Random.State.t->'atype'aprinter=Format.formatter->'a->unit(*$inject
let (--) = CCArray.(--)
*)type'at={arr:'aarray;i:int;(** Start index (included) *)j:int;(** Stop index (excluded) *)}letempty={arr=[||];i=0;j=0;}letmakearri~len=ifi<0||i+len>Array.lengtharrtheninvalid_arg"CCArray_slice.make";{arr;i;j=i+len;}letof_slice(arr,i,len)=makearri~lenletto_slicea=a.arr,a.i,a.j-a.iletfullarr={arr;i=0;j=Array.lengtharr;}letunderlyinga=a.arrletlengtha=a.j-a.iletcopya=Array.suba.arra.i(lengtha)letsubailen=makea.arr(a.i+i)~len(*$=
[ 3;4 ] \
(let a = make (0--10) 2 5 in sub a 1 2 |> to_list)
[ ] \
(let a = make (0--10) 2 5 in sub a 1 0 |> to_list)
[ 5 ] \
(let a = make (0--10) 1 9 in sub a 4 1 |> to_list)
*)letrec_foldifaccaij=ifi=jthenaccelse_foldif(faccia.(i))a(i+1)jlet_reverse_in_placeai~len=iflen=0then()elsefork=0to(len-1)/2dolett=a.(i+k)ina.(i+k)<-a.(i+len-1-k);a.(i+len-1-k)<-t;doneletrec_equaleqa1i1j1a2i2j2=ifi1=j1then(assert(i1=j1&&i2=j2);true)elseeqa1.(i1)a2.(i2)&&_equaleqa1(i1+1)j1a2(i2+1)j2letrec_comparecmpa1i1j1a2i2j2=ifi1=j1thenifi2=j2then0else-1elseifi2=j2then1elseletc=cmpa1.(i1)a2.(i2)inifc=0then_comparecmpa1(i1+1)j1a2(i2+1)j2elsecletequaleqab=lengtha=lengthb&&_equaleqa.arra.ia.jb.arrb.ib.jletcompare_int(a:int)b=Stdlib.compareabletcomparecmpab=_comparecmpa.arra.ia.jb.arrb.ib.jletfoldfacca=letrec_foldaccij=ifi=jthenaccelse_fold(facca.arr.(i))(i+1)jin_foldacca.ia.jletto_lista=letl=fold(funlx->x::l)[]ainList.revlletfoldifacca=_foldifacca.arra.ia.jletfold_whilefacca=letrecfold_while_ifacci=ifi<Array.lengtha.arr&&i<a.jthenletacc,cont=facca.arr.(i)inmatchcontwith|`Stop->acc|`Continue->fold_while_ifacc(i+1)elseaccinfold_while_ifacca.iletgetai=letj=a.i+iinifi<0||j>=a.jtheninvalid_arg"CCArray_slice.get";a.arr.(j)letget_safeai=trySome(getai)withInvalid_argument_->None(*$inject
let sub_a = make [|1;2;3;4;5|] 1 ~len:3
*)(*$=
(Some 2) (get_safe sub_a 0)
(Some 3) (get_safe sub_a 1)
(Some 4) (get_safe sub_a 2)
None (get_safe sub_a 4)
None (get_safe sub_a max_int)
None (get_safe sub_a ~-1)
None (get_safe sub_a ~-42)
*)letsetaix=letj=a.i+iinifi<0||j>=a.jtheninvalid_arg"CCArray_slice.set";a.arr.(j)<-xletiterfa=fork=a.itoa.j-1dofa.arr.(k)doneletiterifa=fork=0tolengtha-1dofka.arr.(a.i+k)doneletblitaibjlen=ifi+len>lengtha||j+len>lengthbtheninvalid_arg"CCArray_slice.blit";Array.blita.arr(a.i+i)b.arr(b.i+j)lenletrec_findfaij=ifi=jthenNoneelsematchfia.(i)with|Some_asres->res|None->_findfa(i+1)jletrec_lookup_rec~cmpkaij=ifi>jthenraiseNot_foundelseifi=jthenifcmpka.(i)=0thenielseraiseNot_foundelseletmiddle=(j+i)/2inmatchcmpka.(middle)with|0->middle|nwhenn<0->_lookup_rec~cmpkai(middle-1)|_->_lookup_rec~cmpka(middle+1)jlet_lookup_exn~cmpkaij=ifi>jthenraiseNot_found;matchcmpka.(i)with|0->i|nwhenn<0->raiseNot_found(* too low *)|_wheni=j->raiseNot_found(* too high *)|_->matchcmpka.(j)with|0->j|nwhenn<0->_lookup_rec~cmpka(i+1)(j-1)|_->raiseNot_found(* too high *)letbsearch_~cmpxarrij=letrecauxij=ifi>jthen`Just_afterjelseletmiddle=i+(j-i)/2in(* avoid overflow *)matchcmpxarr.(middle)with|0->`Atmiddle|nwhenn<0->auxi(middle-1)|_->aux(middle+1)jinifi>=jthen`Emptyelsematchcmparr.(i)x,cmparr.(j)xwith|n,_whenn>0->`All_bigger|_,nwhenn<0->`All_lower|_->auxijletrec_for_allpaij=i=j||(pa.(i)&&_for_allpa(i+1)j)letrec_existspaij=i<>j&&(pa.(i)||_existspa(i+1)j)letrec_for_all2pa1a2i1i2~len=len=0||(pa1.(i1)a2.(i2)&&_for_all2pa1a2(i1+1)(i2+1)~len:(len-1))letrec_exists2pa1a2i1i2~len=len>0&&(pa1.(i1)a2.(i2)||_exists2pa1a2(i1+1)(i2+1)~len:(len-1))(* shuffle a[i...j[ using the given int random generator
See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle *)let_shuffle_rand_intaij=fork=j-1downtoi+1doletl=_rand_int(k+1)inlettmp=a.(l)ina.(l)<-a.(k);a.(k)<-tmp;done(*$T
let st = Random.State.make [||] in let a = 0--10000 in \
let b = Array.copy a in CCArray.shuffle_with st a; a <> b
*)let_sort_indicescmpaij=letlen=j-iinletb=Array.initlen(funk->k)inArray.sort(funk1k2->cmpa.(k1+i)a.(k2+i))b;blet_sortedcmpaij=letlen=j-iinletb=Array.subaileninArray.sortcmpb;blet_chooseaijst=ifi>=jthenraiseNot_found;a.(i+Random.State.intst(j-i))let_pp~seppp_itemoutaij=fork=itoj-1doifk>ithen(Format.pp_print_stringoutsep;Format.pp_print_cutout());pp_itemouta.(k)donelet_pp_i~seppp_itemoutaij=fork=itoj-1doifk>ithen(Format.pp_print_stringoutsep;Format.pp_print_cutout());pp_itemkouta.(k)donelet_to_genaij=letk=refiinfun()->if!k<jthen(letx=a.(!k)inincrk;Somex)elseNoneletrec_to_std_seqaij()=ifi=jthenSeq.NilelseSeq.Cons(a.(i),_to_std_seqa(i+1)j)letrec_to_klistaij()=ifi=jthen`Nilelse`Cons(a.(i),_to_klista(i+1)j)letreverse_in_placea=_reverse_in_placea.arra.i~len:(lengtha)(*$T
let a = 1--6 in let s = make a 2 ~len:3 in \
reverse_in_place s; a = [| 1; 2; 5; 4; 3; 6 |]
*)letsortedcmpa=_sortedcmpa.arra.ia.j(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] \
(let a = 1--6 in let s = make a 2 ~len:0 in \
sorted Stdlib.compare s)
[|2;3;4|] \
(let a = [|6;5;4;3;2;1|] in let s = make a 2 ~len:3 in \
sorted Stdlib.compare s)
*)(*$Q
Q.(array int) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = Array.sub a 5 5 in \
Array.sort Stdlib.compare b; b = sorted Stdlib.compare s))
*)letsort_rankingcmpa=letidx=_sort_indicescmpa.arra.ia.jinletsort_indicescmpa=_sort_indicescmpa0(Array.lengtha)insort_indicescompare_intidx(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] \
(let a = 1--6 in let s = make a 2 ~len:0 in \
sort_ranking Stdlib.compare s)
[|2;1;3;0|] \
(let a = [|"d";"c";"b";"e";"a"|] in let s = make a 1 ~len:4 in \
sort_ranking Stdlib.compare s)
*)(*$Q
Q.(array_of_size Gen.(0--50) printable_string) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = sort_indices String.compare s in \
sorted String.compare s = Array.map (get s) b))
*)letsort_indicescmpa=_sort_indicescmpa.arra.ia.j(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
[||] \
(let a = 1--6 in let s = make a 2 ~len:0 in \
sort_indices Stdlib.compare s)
[|3;1;0;2|] \
(let a = [|"d";"c";"b";"e";"a"|] in let s = make a 1 ~len:4 in \
sort_indices Stdlib.compare s)
*)(*$Q
Q.(array_of_size Gen.(0--60) printable_string) (fun a -> \
Array.length a > 10 ==> ( Array.length a > 10 && \
let s = make a 5 ~len:5 in \
let b = sort_ranking String.compare s in \
let a_sorted = sorted String.compare s in \
copy s = Array.map (Array.get a_sorted) b))
*)letfindfa=_find(fun_->f)a.arra.ia.jletfindifa=_find(funi->f(i-a.i))a.arra.ia.jletfind_idxpa=_find(funix->ifpxthenSome(i-a.i,x)elseNone)a.arra.ia.j(*$=
(Some (1,"c")) (find_idx ((=) "c") (make [| "a"; "b"; "c" |] 1 2))
*)letlookup_exn~cmpka=_lookup_exn~cmpka.arra.i(a.j-1)-a.iletlookup~cmpka=trySome(_lookup_exn~cmpka.arra.i(a.j-1)-a.i)withNot_found->None(*$=
(Some 1) (lookup ~cmp:CCString.compare "c" (make [| "a"; "b"; "c" |] 1 2))
*)letbsearch~cmpka=matchbsearch_~cmpka.arra.i(a.j-1)with|`Atm->`At(m-a.i)|`Just_afterm->`Just_after(m-a.i)|res->resletfor_allpa=_for_allpa.arra.ia.jletexistspa=_existspa.arra.ia.jletfor_all2pab=lengtha=lengthb&&_for_all2pa.arrb.arra.ib.i~len:(lengtha)letexists2pab=_exists2pa.arrb.arra.ib.i~len:(min(lengtha)(lengthb))(*$T
exists2 (=) (make [| 1;2;3;4 |] 1 ~len:2) (make [| 0;1;3;4 |] 1 ~len:3)
*)let_iter2fabij~len=foro=0tolen-1dof(Array.geta(i+o))(Array.getb(j+o))doneletiter2fab=iflengtha<>lengthbtheninvalid_arg"CCArray_slice_iter2";_iter2fa.arrb.arra.ib.i~len:(lengtha)let_fold2faccabij~len=letrecauxacco=ifo=lenthenaccelseletacc=facc(Array.geta(i+o))(Array.getb(j+o))inauxacc(o+1)inauxacc0letfold2faccab=iflengtha<>lengthbtheninvalid_arg"CCArray_slice_fold2";_fold2facca.arrb.arra.ib.i~len:(lengtha)letshufflea=_shuffleRandom.inta.arra.ia.jletshuffle_withsta=_shuffle(Random.State.intst)a.arra.ia.jletrandom_chooseast=_choosea.arra.ia.jstletpp?(sep=", ")pp_itembufa=_pp~seppp_itembufa.arra.ia.jletpp_i?(sep=", ")pp_itemouta=_pp_i~sep(funkoutx->pp_item(k-a.i)outx)outa.arra.ia.jletto_iterak=iterkaletto_seq=to_iterletto_gena=_to_gena.arra.ia.jletto_std_seqa=_to_std_seqa.arra.ia.jletto_klista=_to_klista.arra.ia.j(* test consistency of interfaces *)(*$inject
module type L = module type of CCArray_slice
module type LL = module type of CCArray_sliceLabels
*)(*$R
ignore (module CCArray_sliceLabels : L)
*)(*$R
ignore (module CCArray_slice : LL)
*)