Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file owl_utils_array.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525# 1 "src/base/misc/owl_utils_array.ml"(*
* OWL - OCaml Scientific and Engineering Computing
* Copyright (c) 2016-2020 Liang Wang <liang.wang@cl.cam.ac.uk>
*)(* An extended version of OCaml's array for Owl's internal use. *)includeArray(* concatenate two arrays *)let(@)ab=Array.appendab(* pretty-print an array to string *)letto_string?(prefix="")?(suffix="")?(sep=",")elt_to_strx=lets=Array.to_listx|>List.mapelt_to_str|>String.concatsepinPrintf.sprintf"%s%s%s"prefixssuffix(* set multiple elements to the same value a in x *)letset_nxidxa=Array.iter(funi->x.(i)<-a)idx(* Generate an array of continuous integers *)letrangeab=letr=Array.make(b-a+1)0infori=atobdor.(i-a)<-idone;r(* flatten an array array to array *)letflattenx=letr=Owl_utils_stack.make()initer(funy->iter(funz->Owl_utils_stack.pushrz)y)x;Owl_utils_stack.to_arrayr(* count the number of occurrence of a in x *)letcountxa=letc=ref0inArray.iter(funb->ifa=bthenc:=!c+1)x;!c(* insert an array y into x starting at the position pos in x *)letinsertxypos=letn=Array.lengthxinleterror()=lets=Printf.sprintf"insert requires 0 <= pos < n, but pos = %i and n = %i"posninOwl_exception.INVALID_ARGUMENTsinOwl_exception.verify(pos>=0&&pos<n)error;Array.(subx0pos@y@subxpos(n-pos))(* remove the element at position pos *)letremovexpos=letn=Array.lengthxinleterror()=lets=Printf.sprintf"remove requires 0 <= pos < n, but pos = %i and n = %i"posninOwl_exception.INVALID_ARGUMENTsinOwl_exception.verify(pos>=0&&pos<n)error;letx0=Array.subx0posinletx1=Array.subx(pos+1)(n-pos-1)inx0@x1(* replace a subarray starting from ofs of length len in x with y *)letreplaceofslenxy=letn=Array.lengthxinleterror()=lets=Printf.sprintf"replaec requires ofs + len <= n, but ofs = %i, len = %i, and n = %i"ofslenninOwl_exception.INVALID_ARGUMENTsinOwl_exception.verify(ofs+len<=n)error;letx0=Array.subx0ofsinletx1=Array.subx(ofs+len)(n-ofs-len)inx0@y@x1(* filter array, f : int -> 'a -> bool * 'b *)letfilteri_vfx=letr=Owl_utils_stack.make()initeri(funia->lety,z=fiainify=truethenOwl_utils_stack.pushrz)x;Owl_utils_stack.to_arrayr(* filter array, f : 'a -> bool * 'b *)letfilter_vfx=filteri_v(fun_y->fy)x(* filter array, f : int -> 'a -> bool *)letfilterifx=ifArray.lengthx=0then[||]else(letr=Owl_utils_stack.make()initeri(funia->iffiathenOwl_utils_stack.pushra)x;Owl_utils_stack.to_arrayr)(* filter array, f : 'a -> bool *)letfilterfx=filteri(fun_y->fy)xletmapifx=letn=Array.lengthxinifn=0then[||]else(letr=Owl_utils_stack.make()initeri(funia->Owl_utils_stack.pushr(fia))x;Owl_utils_stack.to_arrayr)letmapfx=mapi(fun_y->fy)x(* deal with the issue: OCaml 4.02.3 does not have Array.iter2
eventually we need to move to OCaml 4.03.0 *)letiter2fxy=letc=min(Array.lengthx)(Array.lengthy)infori=0toc-1dofx.(i)y.(i)doneletiter2ifxy=letc=min(Array.lengthx)(Array.lengthy)infori=0toc-1dofix.(i)y.(i)doneletiter3fxyz=letc=min(Array.lengthx)(Array.lengthy)|>min(Array.lengthz)infori=0toc-1dofx.(i)y.(i)z.(i)doneletiter3ifxyz=letc=min(Array.lengthx)(Array.lengthy)|>min(Array.lengthz)infori=0toc-1dofix.(i)y.(i)z.(i)doneletiter4ifwxyz=letnw=Array.lengthwinletnx=Array.lengthxinletny=Array.lengthyinletnz=Array.lengthzinassert(nw=nx&&nx=ny&&ny=nz);fori=0tonw-1dofiw.(i)x.(i)y.(i)z.(i)doneletiter4fwxyz=iter4i(fun_abcd->fabcd)wxyzletmap2ifxy=letc=min(Array.lengthx)(Array.lengthy)inArray.initc(funi->fix.(i)y.(i))(* map two arrays, and split into two arrays, f returns 2-tuple *)letmap2i_split2fxy=letc=min(Array.lengthx)(Array.lengthy)inmatchcwith|0->[||],[||]|_->letz0=Owl_utils_stack.make()inletz1=Owl_utils_stack.make()infori=1toc-1doleta,b=fix.(i)y.(i)inOwl_utils_stack.pushz0a;Owl_utils_stack.pushz1bdone;Owl_utils_stack.(to_arrayz0,to_arrayz1)letfilter2ifxy=letx_len=Array.lengthxinlety_len=Array.lengthyinletexn=Owl_exception.DIFFERENT_SIZE(x_len,y_len)inOwl_exception.check(x_len=y_len)exn;ifx_len=0then[||]else(letr=Owl_utils_stack.make()initer2i(funiab->iffiabthenOwl_utils_stack.pushr(a,b))xy;Owl_utils_stack.to_arrayr)letfilter2fxy=filter2i(fun_ab->fab)xyletfilter2i_ifxy=letlen_x=Array.lengthxinletlen_y=Array.lengthyinletexn=Owl_exception.DIFFERENT_SIZE(len_x,len_y)inOwl_exception.check(len_x=len_y)exn;iflen_x=0then[||]else(letr=Owl_utils_stack.make()initer2i(funiab->iffiabthenOwl_utils_stack.pushri)xy;Owl_utils_stack.to_arrayr)letfilter2_ifxy=filter2i_i(fun_ab->fab)xyletfilter2_splitfxy=letz=filter2fxyinArray.(mapfstz,mapsndz)letresize?(head=true)vnx=letm=Array.lengthxinifn<mthenArray.(subx0n|>copy)elseifn>mthen(lety=Array.makenvinifhead=truethenArray.blitx0y0melseArray.blitx0y(n-m)m;y)elseArray.copyxletmap3ifxyz=letnx=Array.lengthxinletny=Array.lengthyinletnz=Array.lengthzinassert(nx=ny&&ny=nz);Array.initnx(funi->fix.(i)y.(i)z.(i))letmap3fxyz=map3i(fun_abc->fabc)xyzletmap4ifwxyz=letnw=Array.lengthwinletnx=Array.lengthxinletny=Array.lengthyinletnz=Array.lengthzinassert(nw=nx&&nx=ny&&ny=nz);Array.initnx(funi->fiw.(i)x.(i)y.(i)z.(i))letmap4fwxyz=map4i(fun_abcd->fabcd)wxyzletfold2faxy=letacc=refainiter2(funuv->acc:=f!accuv)xy;!acc(* pad n value of v to the left/right of array x *)letpadsvnx=letl=Array.lengthxinlety=Array.make(l+n)vinlet_=matchswith|`Left->Array.blitx0ynl|`Right->Array.blitx0y0linyletalignsvxy=letlen_x=Array.lengthxinletlen_y=Array.lengthyiniflen_x<len_ythenpadsv(len_y-len_x)x,Array.copyyelseiflen_x>len_ythenArray.copyx,padsv(len_x-len_y)yelseArray.copyx,Array.copyyletalign3svxyz=letlen_x=Array.lengthxinletlen_y=Array.lengthyinletlen_z=Array.lengthzinletlen=maxlen_x(maxlen_ylen_z)inletx=iflen_x<lenthenpadsv(len-len_x)xelseArray.copyxinlety=iflen_y<lenthenpadsv(len-len_y)yelseArray.copyyinletz=iflen_z<lenthenpadsv(len-len_z)zelseArray.copyzinx,y,z(* [x] is greater or equal than [y] elementwise *)letgreater_eqaulxy=letla=Array.lengthxinletlb=Array.lengthyinassert(la=lb);letb=reftruein(tryfori=0tola-1doifx.(i)<y.(i)thenfailwith"found"donewith|_->b:=false);!b(* swap the ith and jth element in an array *)letswapxij=leta=x.(i)inx.(i)<-x.(j);x.(j)<-a(* permute an array x based on the permutation array p, such that y.(i) = x.(p.(i)) *)letpermutepx=letn=Array.lengthxinArray.initn(funi->x.(p.(i)))letget_sliceslicex=assert(Array.lengthslice=3);letn=Array.lengthxinletstart=ifslice.(0)<0thenn+slice.(0)elseslice.(0)inletstop=ifslice.(1)<0thenn+slice.(1)elseslice.(1)inletstep=slice.(2)inassert(absstep<=n&&start<n&&stop<n);letm=abs(stop-start)/absstepinletstack=Owl_utils_stack.make()inletidx=refstartinfor_i=0tomdoOwl_utils_stack.pushstackx.(!idx);idx:=!idx+stepdone;Owl_utils_stack.to_arraystackletset_sliceslicexy=assert(Array.lengthslice=3);letn=Array.lengthxinletstart=ifslice.(0)<0thenn+slice.(0)elseslice.(0)inletstop=ifslice.(1)<0thenn+slice.(1)elseslice.(1)inletstep=slice.(2)inassert(absstep<=n&&start<n&&stop<n);letidx=refstartinfori=0toArray.lengthy-1doassert(!idx<n);x.(!idx)<-y.(i);idx:=!idx+stepdone(* convert a list of tuples into array *)letof_tuplesx=lets=Owl_utils_stack.make()inArray.iter(fun(i,j)->Owl_utils_stack.pushsi;Owl_utils_stack.pushsj)x;Owl_utils_stack.to_arrays(* given set x and y, return complement of y, i.e. x \ y *)letcomplementxy=leth=Hashtbl.create64inArray.iter(funa->Hashtbl.addhaa)x;Array.iter(funa->Hashtbl.removeha)y;lets=Owl_utils_stack.make()inHashtbl.iter(funa_->Owl_utils_stack.pushsa)h;Owl_utils_stack.to_arraysletbalance_lastmassx=letk=Array.lengthx-1inletq=refmassinArray.mapi(funia->assert(!q>=0.);ifi<kthen(q:=!q-.a;a)else!q)xletindex_ofxa=letpos=ref(-1)inletr=tryiteri(funib->ifa=bthen(pos:=i;raiseOwl_exception.FOUND))x;!poswith|_->!posinifr<0thenraiseOwl_exception.NOT_FOUNDelser(* Binary search. Adapted from CCArray.bsearch in containers.
* Bin edges are taken as left-inclusive, right-exclusive *)letbsearch~cmpkbin_edges=letrecauxij=ifi>jthenjelse(letmiddle=i+((j-i)/2)in(* avoid overflow *)matchcmpkbin_edges.(middle)with|0->middle|nwhenn<0->auxi(middle-1)|_->aux(middle+1)j)inletn=Array.lengthbin_edges-1inifn<0thenfailwith"empty array"else(matchcmpbin_edges.(0)k,cmpbin_edges.(n)kwith|c,_whenc>0->-1|_,cwhenc<=0->n|_->aux0n)(* remove the duplicates in the array *)letuniquex=lethtbl=Hashtbl.create(Array.lengthx)infilter(funa->letnot_found=not(Hashtbl.memhtbla)inifnot_foundthenHashtbl.addhtblaNone;not_found)x(* merge two arrays, duplicates will be removed *)letmergexy=Array.appendxy|>uniqueletreversex=letn=Array.lengthx-1inletm=(Array.lengthx/2)-1infori=0tomdolett=x.(n-i)inx.(n-i)<-x.(i);x.(i)<-tdone(* sort then fill the holes *)letsort_fill?min?max?fillx=letx=copyxinArray.sortStdlib.comparex;letn=Array.lengthxinletmin=matchminwith|Somea->a|None->x.(0)inletmax=matchmaxwith|Somea->a|None->x.(n-1)inletfill=matchfillwith|Somea->a|None->0inassert(min<=x.(0)&&max>=x.(n-1));lety=Array.make(max-min+1)fillinArray.iter(funi->y.(i-min)<-i)x;yletargsort?(cmp=Stdlib.compare)x=letcmp_funab=cmp(fsta)(fstb)inletn=Array.lengthxinlety=Array.initn(funi->x.(i),i)inArray.sortcmp_funy;Array.mapsndyletmin_i?(cmp=Stdlib.compare)x=assert(Array.lengthx>0);letidx=ref0inletacc=refx.(0)inArray.iteri(funia->ifcmpa!acc=-1then(idx:=i;acc:=a))x;!idxletmax_i?(cmp=Stdlib.compare)x=assert(Array.lengthx>0);letidx=ref0inletacc=refx.(0)inArray.iteri(funia->ifcmpa!acc=1then(idx:=i;acc:=a))x;!idx(* ends here *)