123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331# 1 "Camomile/internal/iSet.ml"(** Set of integers *)(* Copyright (C) 2003 Yamagata Yoriyuki. distributed with LGPL *)(* This library 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 2 of *)(* the License, or (at your option) any later version. *)(* As a special exception to the GNU Library General Public License, you *)(* may link, statically or dynamically, a "work that uses this library" *)(* with a publicly distributed version of this library to produce an *)(* executable file containing portions of this library, and distribute *)(* that executable file under terms of your choice, without any of the *)(* additional requirements listed in clause 6 of the GNU Library General *)(* Public License. By "a publicly distributed version of this library", *)(* we mean either the unmodified Library as distributed by the authors, *)(* or a modified version of this library that is distributed under the *)(* conditions defined in clause 3 of the GNU Library General Public *)(* License. This exception does not however invalidate any other reasons *)(* why the executable file might be covered by the GNU Library General *)(* Public License . *)(* This library 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 library; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *)(* USA *)(* You can contact the authour by sending email to *)(* yoriyuki.y@gmail.com *)includeAvlTreelet(>!)=(>)letcompare_uintn1n2=letsgn1=(n1lsr24)-(n2lsr24)inifsgn1=0then(n1land0xffffff)-(n2land0xffffff)elsesgn1let(>)n1n2=compare_uintn1n2>0let(<)n1n2=compare_uintn1n2<0let(<=)n1n2=compare_uintn1n2<=0letcompare=compare_uintletmax_int=~-1letmin_int=0typet=(int*int)treetypeelt=intletrecmemns=ifis_emptysthenfalseelseletv1,v2=rootsinifn<v1thenmemn(left_branchs)elseifv1<=n&&n<=v2thentrueelsememn(right_branchs)letrecaddns=ifis_emptysthenmake_treeempty(n,n)emptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifv1<>min_int&&n<v1-1thenmake_tree(addns0)vs1elseifv2<>max_int&&n>v2+1thenmake_trees0v(addns1)elseifn+1=v1thenifnot(is_emptys0)thenlet(u1,u2),s0'=split_rightmosts0inifu2<>max_int&&u2+1=nthenmake_trees0'(u1,v2)s1elsemake_trees0(n,v2)s1elsemake_trees0(n,v2)s1elseifv2+1=nthenifnot(is_emptys1)thenlet(u1,u2),s1'=split_leftmosts1inifn<>max_int&&n+1=u1thenmake_trees0(v1,u2)s1'elsemake_trees0(v1,n)s1elsemake_trees0(v1,n)s1elsesletrecfromns=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifn<v1thenmake_tree(fromns0)vs1elseifn>v2thenfromns1elsemake_treeempty(n,v2)s1letafterns=ifn=max_intthenemptyelsefrom(n+1)sletrecuntilns=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifn>v2thenmake_trees0v(untilns1)elseifn<v1thenuntilns0elsemake_trees0(v1,n)emptyletbeforens=ifn=min_intthenemptyelseuntil(n-1)sletadd_rangen1n2s=ifn1>n2theninvalid_arg"ISet.add_range"elseletn1,l=ifn1=min_intthenn1,emptyelseletl=until(n1-1)sinifis_emptylthenn1,emptyelselet(v1,v2),l'=split_rightmostlinifv2+1=n1thenv1,l'elsen1,linletn2,r=ifn2=max_intthenn2,emptyelseletr=from(n2+1)sinifis_emptyrthenn2,emptyelselet(v1,v2),r'=split_leftmostrinifn2+1=v1thenv2,r'elsen2,rinmake_treel(n1,n2)rletsingletonn=singleton_tree(n,n)letrecremovens=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets1=left_branchsinlets2=right_branchsinifn<v1thenmake_tree(removens1)vs2elseifn=v1thenifv1=v2thenconcats1s2elsemake_trees1(v1+1,v2)s2elseifn>v1&&n<v2thenlets=make_trees1(v1,n-1)emptyinmake_trees(n+1,v2)s2elseifn=v2thenmake_trees1(v1,v2-1)s2elsemake_trees1v(removens2)letremove_rangen1n2s=ifn1>n2theninvalid_arg"ISet.remove_range"elseconcat(beforen1s)(aftern2s)letrecunions1s2=ifis_emptys1thens2elseifis_emptys2thens1elselets1,s2=ifheights1>!heights2thens1,s2elses2,s1inletn1,n2=roots1inletl1=left_branchs1inletr1=right_branchs1inletl2=beforen1s2inletr2=aftern2s2inletn1,l=ifn1=min_intthenn1,emptyelseletl=unionl1l2inifis_emptylthenn1,lelselet(v1,v2),l'=split_rightmostlinifv2+1=n1thenv1,l'elsen1,linletn2,r=ifn1=max_intthenn2,emptyelseletr=unionr1r2inifis_emptyrthenn2,relselet(v1,v2),r'=split_leftmostrinifn2+1=v1thenv2,r'elsen2,rinmake_treel(n1,n2)rletrecinters1s2=ifis_emptys1thenemptyelseifis_emptys2thenemptyelselets1,s2=ifheights1>!heights2thens1,s2elses2,s1inletn1,n2=roots1inletl1=left_branchs1inletr1=right_branchs1inletl2=beforen1s2inletr2=aftern2s2inletm=untiln2(fromn1s2)inconcat(concat(interl1l2)m)(interr1r2)letreccompl_auxn1n2s=ifis_emptysthenadd_rangen1n2emptyelseletv1,v2=rootsinletl=left_branchsinletr=right_branchsinletl=ifv1=min_intthenemptyelsecompl_auxn1(v1-1)linletr=ifv2=max_intthenemptyelsecompl_aux(v2+1)n2rinconcatlrletcompls=compl_auxmin_intmax_intsletdiffs1s2=inters1(compls2)letreccompare_auxx1x2=matchx1,x2with[],[]->0|`Sets::rest,x->ifis_emptysthencompare_auxrestx2elseletl=left_branchsinletv=rootsinletr=right_branchsincompare_aux(`Setl::`Rangev::`Setr::rest)x|_,`Sets::rest->ifis_emptysthencompare_auxx1restelseletl=left_branchsinletv=rootsinletr=right_branchsincompare_auxx1(`Setl::`Rangev::`Setr::rest)|`Range((v1,v2))::rest1,`Range((v3,v4))::rest2->letsgn=comparev1v3inifsgn<>0thensgnelseletsgn=comparev2v4inifsgn<>0thensgnelsecompare_auxrest1rest2|[],_->~-1|_,[]->1letcompares1s2=compare_aux[`Sets1][`Sets2]letequals1s2=compares1s2=0letrecsubsets1s2=ifis_emptys1thentrueelseifis_emptys2thenfalseelseletv1,v2=roots2inletl2=left_branchs2inletr2=right_branchs2inletl1=beforev1s1inletr1=afterv2s1in(subsetl1l2)&&(subsetr1r2)letfold_rangef=AvlTree.fold(fun(n1,n2)x->fn1n2x)letfoldf=letrecgn1n2a=ifn1=n2thenfn1aelseg(n1+1)n2(fn1a)infold_rangegletiterprocs=fold(funn()->procn)s()letiter_rangeproc=AvlTree.iter(fun(n1,n2)->procn1n2)letfor_allps=letrectest_rangen1n2=ifn1=n2thenpn1elsepn1&&test_range(n1+1)n2inletrectest_sets=ifis_emptysthentrueelseletn1,n2=rootsintest_rangen1n2&&test_set(left_branchs)&&test_set(right_branchs)intest_setsletexistsps=letrectest_rangen1n2=ifn1=n2thenpn1elsepn1||test_range(n1+1)n2inletrectest_sets=ifis_emptysthenfalseelseletn1,n2=rootsintest_rangen1n2||test_set(left_branchs)||test_set(right_branchs)intest_setsletfilter_rangepn1n2a=letrecloopn1n2a=functionNone->ifn1=n2thenmake_treea(n1,n1)emptyelseloop(n1+1)n2a(ifpn1thenSomen1elseNone)|Somev1asx->ifn1=n2thenmake_treea(v1,n1)emptyelseifpn1thenloop(n1+1)n2axelseloop(n1+1)n2(make_treea(v1,n1-1)empty)Noneinloopn1n2aNoneletfilterps=fold_range(filter_rangep)emptysletpartition_rangepn1n2(a,b)=letrecloopn1n2acc=letacc=leta,b,(v,n)=accinifpn1=vthenaccelseifvthen(make_treea(n,n1)empty,b,(notv,n1))else(a,make_treeb(n,n1)empty,(notv,n1))inifn1=n2thenleta,b,(v,n)=accinifvthen(make_treea(n,n1)empty,b)else(a,make_treeb(n,n1)empty)elseloop(n1+1)n2accinloopn1n2(a,b,(pn1,n1))letpartitionps=fold_range(partition_rangep)s(empty,empty)letcardinals=fold_range(funn1n2c->c+n2-n1+1)s0letrev_rangess=fold_range(funn1n2a->(n1,n2)::a)s[]letrecburst_rangen1n2a=ifn1=n2thenn1::aelseburst_rangen1(n2-1)(n2::a)letelementss=letfa(n1,n2)=burst_rangen1n2ainList.fold_leftf[](rev_rangess)letrangess=List.rev(rev_rangess)letmin_elts=let(n,_),_=split_leftmostsinnletmax_elts=let(_,n),_=split_rightmostsinnletchooses=fst(roots)