123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207(* Copyright (C) 2017 Hongbo Zhang, Authors of ReScript
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition to the permissions granted to you by the LGPL, you may combine
* or link a "work that uses the Library" with a publicly distributed version
* of this file to produce a combined library or application, then distribute
* that combined work under the terms of your choosing, with no requirement
* to comply with the obligations normally placed on you by section 4 of the
* LGPL version 3 (or the corresponding section of a later version of the LGPL
* should you choose to use a later version).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)moduleN=Belt_internalAVLsetmoduleA=Belt_Arraytype('k,'id)t='kN.ttype('key,'id)cmp=('key,'id)Belt_Id.cmp(* here we relies on reference transparence
address equality means everything equal across time
no need to call [bal] again
*)letrecadd(t:_t)x~cmp:_t=matchtwith|None->N.singletonx|Soment->letk=nt.valueinletc=((Belt_Id.getCmpInternalcmp)xk[@u])inifc=0thentelselet{N.left=l;right=r;_}=ntinifc<0thenletll=add~cmplxinifll==lthentelseN.balllkrelseletrr=add~cmprxinifrr==rthentelseN.ballkrrletrecremove(t:_t)x~cmp:_t=matchtwith|None->t|Somen->let{N.left=l;value=v;right=r;_}=ninletc=((Belt_Id.getCmpInternalcmp)xv[@u])inifc=0thenmatch(l,r)with|None,_->r|_,None->l|_,Somern->letv=refrn.valueinletr=N.removeMinAuxWithRefrnvinN.ballv.contentsrelseifc<0thenletll=remove~cmplxinifll==lthentelseN.balllvrelseletrr=remove~cmprxinifrr==rthentelseN.ballvrrletmergeManyharr~cmp=letlen=A.lengtharrinletv=refhinfori=0tolen-1doletkey=A.getUnsafearriinv.contents<-addv.contents~cmpkeydone;v.contentsletremoveManyharr~cmp=letlen=A.lengtharrinletv=refhinfori=0tolen-1doletkey=A.getUnsafearriinv.contents<-removev.contents~cmpkeydone;v.contentsletrecsplitAuxNoPivot~cmp(n:_N.node)x:_*_=let{N.left=l;value=v;right=r;_}=ninletc=((Belt_Id.getCmpInternalcmp)xv[@u])inifc=0then(l,r)elseifc<0thenmatchlwith|None->(None,Somen)|Somel->letll,rl=splitAuxNoPivot~cmplxin(ll,N.joinSharedrlvr)elsematchrwith|None->(Somen,None)|Somer->letlr,rr=splitAuxNoPivot~cmprxin(N.joinSharedlvlr,rr)letrecsplitAuxPivot~cmp(n:_N.node)xpres:_*_=let{N.left=l;value=v;right=r;_}=ninletc=((Belt_Id.getCmpInternalcmp)xv[@u])inifc=0then(pres.contents<-true;(l,r))elseifc<0thenmatchlwith|None->(None,Somen)|Somel->letll,rl=splitAuxPivot~cmplxpresin(ll,N.joinSharedrlvr)elsematchrwith|None->(Somen,None)|Somer->letlr,rr=splitAuxPivot~cmprxpresin(N.joinSharedlvlr,rr)letsplit(t:_t)x~cmp=matchtwith|None->((None,None),false)|Somen->letpres=reffalseinletv=splitAuxPivot~cmpnxpresin(v,pres.contents)(* [union s1 s2]
Use the pivot to split the smaller collection
*)letrecunion(s1:_t)(s2:_t)~cmp:_t=match(s1,s2)with|None,_->s2|_,None->s1|Somen1,Somen2->leth1,h2=(n1.height,n2.height)inifh1>=h2thenifh2=1thenadd~cmps1n2.valueelselet{N.left=l1;value=v1;right=r1;_}=n1inletl2,r2=splitAuxNoPivot~cmpn2v1inN.joinShared(union~cmpl1l2)v1(union~cmpr1r2)elseifh1=1thenadds2~cmpn1.valueelselet{N.left=l2;value=v2;right=r2;_}=n2inletl1,r1=splitAuxNoPivot~cmpn1v2inN.joinShared(union~cmpl1l2)v2(union~cmpr1r2)letrecintersect(s1:_t)(s2:_t)~cmp=match(s1,s2)with|None,_|_,None->None|Somen1,Somen2->let{N.left=l1;value=v1;right=r1;_}=n1inletpres=reffalseinletl2,r2=splitAuxPivot~cmpn2v1presinletll=intersect~cmpl1l2inletrr=intersect~cmpr1r2inifpres.contentsthenN.joinSharedllv1rrelseN.concatSharedllrrletrecdiffs1s2~cmp=match(s1,s2)with|None,_|_,None->s1|Somen1,Somen2->let{N.left=l1;value=v1;right=r1;_}=n1inletpres=reffalseinletl2,r2=splitAuxPivot~cmpn2v1presinletll=diff~cmpl1l2inletrr=diff~cmpr1r2inifpres.contentsthenN.concatSharedllrrelseN.joinSharedllv1rrletempty=NoneletfromArray=N.fromArrayletisEmpty=N.isEmptyletcmp=N.cmpleteq=N.eqlethas=N.hasletforEachU=N.forEachUletforEach=N.forEachletreduceU=N.reduceUletreduce=N.reduceleteveryU=N.everyUletevery=N.everyletsomeU=N.someUletsome=N.someletsize=N.sizelettoList=N.toListlettoArray=N.toArrayletminimum=N.minimumletmaximum=N.maximumletmaxUndefined=N.maxUndefinedletminUndefined=N.minUndefinedletget=N.getletgetExn=N.getExnletgetUndefined=N.getUndefinedletfromSortedArrayUnsafe=N.fromSortedArrayUnsafeletsubset=N.subsetletkeep=N.keepSharedletkeepU=N.keepSharedUletpartitionU=N.partitionSharedUletpartition=N.partitionSharedletcheckInvariantInternal=N.checkInvariantInternal