12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516(***********************************************************************)(* *)(* Objective Caml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. All rights reserved. This file is distributed *)(* under the terms of the Apache 2.0 license. See ../THIRD-PARTY.txt *)(* for details. *)(* *)(***********************************************************************)open!ImportmoduleList=List0include(Map_intf:sigmoduleOr_duplicate=Map_intf.Or_duplicatemoduleContinue_or_stop=Map_intf.Continue_or_stopmoduleWith_comparator=Map_intf.With_comparatormoduleWith_first_class_module=Map_intf.With_first_class_modulemoduleWithout_comparator=Map_intf.Without_comparator(* The module susbstitutions below are needed for older versions of OCaml
(before 4.07), because back then [module type of] did not keep module
aliases. *)includemoduletypeofstructincludeMap_intfendwithmoduleFinished_or_unfinished:=Map_intf.Finished_or_unfinishedandmoduleOr_duplicate:=Or_duplicateandmoduleContinue_or_stop:=Continue_or_stopandmoduleWith_comparator:=With_comparatorandmoduleWith_first_class_module:=With_first_class_moduleandmoduleWithout_comparator:=Without_comparatorend)moduleFinished_or_unfinished=structincludeMap_intf.Finished_or_unfinished(* These two functions are tested in [test_map.ml] to make sure our use of
[Caml.Obj.magic] is correct and safe. *)letof_continue_or_stop:Continue_or_stop.t->t=Caml.Obj.magicletto_continue_or_stop:t->Continue_or_stop.t=Caml.Obj.magicendletwith_return=With_return.with_returnexceptionDuplicate[@@deriving_inlinesexp]let()=Ppx_sexp_conv_lib.Conv.Exn_converter.add[%extension_constructorDuplicate](function|Duplicate->Ppx_sexp_conv_lib.Sexp.Atom"map.ml.Duplicate"|_->assertfalse);;[@@@end]moduleTree0=structtype('k,'v)t=|Empty|Leafof'k*'v|Nodeof('k,'v)t*'k*'v*('k,'v)t*inttype('k,'v)tree=('k,'v)tletheight=function|Empty->0|Leaf_->1|Node(_,_,_,_,h)->h;;letinvariants=letin_rangeloweruppercompare_keyk=(matchlowerwith|None->true|Somelower->compare_keylowerk<0)&&matchupperwith|None->true|Someupper->compare_keykupper<0inletreclooploweruppercompare_keyt=matchtwith|Empty->true|Leaf(k,_)->in_rangeloweruppercompare_keyk|Node(l,k,_,r,h)->lethl=heightlandhr=heightrinabs(hl-hr)<=2&&h=maxhlhr+1&&in_rangeloweruppercompare_keyk&&looplower(Somek)compare_keyl&&loop(Somek)uppercompare_keyrinfunt~compare_key->loopNoneNonecompare_keyt;;(* precondition: |height(l) - height(r)| <= 2 *)letcreatelxdr=lethl=heightlandhr=heightrinifhl=0&&hr=0thenLeaf(x,d)elseNode(l,x,d,r,ifhl>=hrthenhl+1elsehr+1);;letsingletonkeydata=Leaf(key,data)(* We must call [f] with increasing indexes, because the bin_prot reader in
Core_kernel.Map needs it. *)letof_increasing_iterator_unchecked~len~f=letrecloopn~fi:(_,_)t=matchnwith|0->Empty|1->letk,v=fiinLeaf(k,v)|2->letkl,vl=fiinletk,v=f(i+1)inNode(Leaf(kl,vl),k,v,Empty,2)|3->letkl,vl=fiinletk,v=f(i+1)inletkr,vr=f(i+2)inNode(Leaf(kl,vl),k,v,Leaf(kr,vr),2)|n->letleft_length=nlsr1inletright_length=n-left_length-1inletleft=loopleft_length~fiinletk,v=f(i+left_length)inletright=loopright_length~f(i+left_length+1)increateleftkvrightinlooplen~f0;;letof_sorted_array_uncheckedarray~compare_key=letarray_length=Array.lengtharrayinletnext=ifarray_length<2||letk0,_=array.(0)inletk1,_=array.(1)incompare_keyk0k1<0thenfuni->array.(i)elsefuni->array.(array_length-1-i)inof_increasing_iterator_unchecked~len:array_length~f:next,array_length;;letof_sorted_arrayarray~compare_key=matcharraywith|[||]|[|_|]->Result.Ok(of_sorted_array_uncheckedarray~compare_key)|_->with_return(funr->letincreasing=matchcompare_key(fstarray.(0))(fstarray.(1))with|0->r.return(Or_error.error_string"of_sorted_array: duplicated elements")|i->i<0infori=1toArray.lengtharray-2domatchcompare_key(fstarray.(i))(fstarray.(i+1))with|0->r.return(Or_error.error_string"of_sorted_array: duplicated elements")|i->ifPoly.(<>)(i<0)increasingthenr.return(Or_error.error_string"of_sorted_array: elements are not ordered")done;Result.Ok(of_sorted_array_uncheckedarray~compare_key));;(* precondition: |height(l) - height(r)| <= 3 *)letballxdr=lethl=heightlinlethr=heightrinifhl>hr+2then(matchlwith|Empty->invalid_arg"Map.bal"|Leaf_->assertfalse(* height(Leaf) = 1 && 1 is not larger than hr + 2 *)|Node(ll,lv,ld,lr,_)->ifheightll>=heightlrthencreatelllvld(createlrxdr)else(matchlrwith|Empty->invalid_arg"Map.bal"|Leaf(lrv,lrd)->create(createlllvldEmpty)lrvlrd(createEmptyxdr)|Node(lrl,lrv,lrd,lrr,_)->create(createlllvldlrl)lrvlrd(createlrrxdr)))elseifhr>hl+2then(matchrwith|Empty->invalid_arg"Map.bal"|Leaf_->assertfalse(* height(Leaf) = 1 && 1 is not larger than hl + 2 *)|Node(rl,rv,rd,rr,_)->ifheightrr>=heightrlthencreate(createlxdrl)rvrdrrelse(matchrlwith|Empty->invalid_arg"Map.bal"|Leaf(rlv,rld)->create(createlxdEmpty)rlvrld(createEmptyrvrdrr)|Node(rll,rlv,rld,rlr,_)->create(createlxdrll)rlvrld(createrlrrvrdrr)))elsecreatelxdr;;letempty=Emptyletis_empty=function|Empty->true|_->false;;letraise_key_already_present~key~sexp_of_key=Error.raise_s(Sexp.message"[Map.add_exn] got key already present"["key",key|>sexp_of_key]);;moduleAdd_or_set=structtypet=|Add_exn_internal|Add_exn|Setendletrecfind_and_add_or_sett~length~key:x~data~compare_key~sexp_of_key~(add_or_set:Add_or_set.t)=matchtwith|Empty->Leaf(x,data),length+1|Leaf(v,d)->letc=compare_keyxvinifc=0then(matchadd_or_setwith|Add_exn_internal->Exn.raise_without_backtraceDuplicate|Add_exn->raise_key_already_present~key:x~sexp_of_key|Set->Leaf(x,data),length)elseifc<0thenNode(Leaf(x,data),v,d,Empty,2),length+1elseNode(Empty,v,d,Leaf(x,data),2),length+1|Node(l,v,d,r,h)->letc=compare_keyxvinifc=0then(matchadd_or_setwith|Add_exn_internal->Exn.raise_without_backtraceDuplicate|Add_exn->raise_key_already_present~key:x~sexp_of_key|Set->Node(l,x,data,r,h),length)elseifc<0then(letl,length=find_and_add_or_set~length~key:x~datal~compare_key~sexp_of_key~add_or_setinballvdr,length)else(letr,length=find_and_add_or_set~length~key:x~datar~compare_key~sexp_of_key~add_or_setinballvdr,length);;letadd_exnt~length~key~data~compare_key~sexp_of_key=find_and_add_or_sett~length~key~data~compare_key~sexp_of_key~add_or_set:Add_exn;;letadd_exn_internalt~length~key~data~compare_key~sexp_of_key=find_and_add_or_sett~length~key~data~compare_key~sexp_of_key~add_or_set:Add_exn_internal;;letsett~length~key~data~compare_key=find_and_add_or_sett~length~key~data~compare_key~sexp_of_key:(fun_->List[])~add_or_set:Set;;letset'tkeydata~compare_key=fst(sett~length:0~key~data~compare_key)moduleBuild_increasing=structmoduleFragment=structtypenonrec('k,'v)t={left_subtree:('k,'v)t;key:'k;data:'v}letsingleton_to_tree_exn=function|{left_subtree=Empty;key;data}->singletonkeydata|_->failwith"Map.singleton_to_tree_exn: not a singleton";;letsingleton~key~data={left_subtree=Empty;key;data}(* precondition: |height(l.left_subtree) - height(r)| <= 2,
max_key(l) < min_key(r)
*)letcollapselr=createl.left_subtreel.keyl.datar(* precondition: |height(l.left_subtree) - height(r.left_subtree)| <= 2,
max_key(l) < min_key(r)
*)letjoinlr={rwithleft_subtree=collapselr.left_subtree}letmax_keyt=t.keyend(** Build trees from singletons in a balanced way by using skew binary encoding.
Each level contains trees of the same height, consecutive levels have consecutive
heights. There are no gaps. The first level are single keys.
*)type('k,'v)t=|Zeroofunit(* [unit] to make pattern matching faster *)|Oneof('k,'v)t*('k,'v)Fragment.t|Twoof('k,'v)t*('k,'v)Fragment.t*('k,'v)Fragment.tletempty=Zero()letadd_unchecked=letrecgotx=matchtwith|Zero()->One(t,x)|One(t,y)->Two(t,y,x)|Two(t,z,y)->One(got(Fragment.joinzy),x)infunt~key~data->got(Fragment.singleton~key~data);;letto_tree=letrecgotr=matchtwith|Zero()->r|One(t,l)->got(Fragment.collapselr)|Two(t,ll,l)->got(Fragment.collapse(Fragment.joinlll)r)infunction|Zero()->Empty|One(t,r)->got(Fragment.singleton_to_tree_exnr)|Two(t,l,r)->go(One(t,l))(Fragment.singleton_to_tree_exnr);;letmax_key=function|Zero()->None|One(_,r)|Two(_,_,r)->Some(Fragment.max_keyr);;endletof_increasing_sequenceseq~compare_key=with_return(fun{return}->letbuilder,length=Sequence.foldseq~init:(Build_increasing.empty,0)~f:(fun(builder,length)(key,data)->matchBuild_increasing.max_keybuilderwith|Someprev_keywhencompare_keyprev_keykey>=0->return(Or_error.error_string"of_increasing_sequence: non-increasing key")|_->Build_increasing.add_uncheckedbuilder~key~data,length+1)inOk(Build_increasing.to_treebuilder,length));;(* Like [bal] but allows any difference in height between [l] and [r].
O(|height l - height r|) *)letrecjoinlkdr~compare_key=matchl,rwith|Empty,_->set'rkd~compare_key|_,Empty->set'lkd~compare_key|Leaf(lk,ld),_->set'(set'rkd~compare_key)lkld~compare_key|_,Leaf(rk,rd)->set'(set'lkd~compare_key)rkrd~compare_key|Node(ll,lk,ld,lr,lh),Node(rl,rk,rd,rr,rh)->(* [bal] requires height difference <= 3. *)iflh>rh+3(* [height lr >= height r],
therefore [height (join lr k d r ...)] is [height rl + 1] or [height rl]
therefore the height difference with [ll] will be <= 3 *)thenballllkld(joinlrkdr~compare_key)elseifrh>lh+3thenbal(joinlkdrl~compare_key)rkrdrrelseballkdr;;letrecsplittx~compare_key=matchtwith|Empty->Empty,None,Empty|Leaf(k,d)->letcmp=compare_keyxkinifcmp=0thenEmpty,Some(k,d),Emptyelseifcmp<0thenEmpty,None,telset,None,Empty|Node(l,k,d,r,_)->letcmp=compare_keyxkinifcmp=0thenl,Some(k,d),relseifcmp<0then(letll,maybe,lr=splitlx~compare_keyinll,maybe,joinlrkdr~compare_key)else(letrl,maybe,rr=splitrx~compare_keyinjoinlkdrl~compare_key,maybe,rr);;letsplit_and_reinsert_boundaryt~intox~compare_key=letleft,boundary_opt,right=splittx~compare_keyinmatchboundary_optwith|None->left,right|Some(key,data)->letinsert_intotree=fst(settree~key~data~length:0~compare_key)in(matchintowith|`Left->insert_intoleft,right|`Right->left,insert_intoright);;letsplit_ranget~(lower_bound:'aMaybe_bound.t)~(upper_bound:'aMaybe_bound.t)~compare_key=ifMaybe_bound.bounds_crossed~compare:compare_key~lower:lower_bound~upper:upper_boundthenempty,empty,emptyelse(letleft,mid_and_right=matchlower_boundwith|Unbounded->empty,t|Incllb->split_and_reinsert_boundary~into:`Righttlb~compare_key|Excllb->split_and_reinsert_boundary~into:`Lefttlb~compare_keyinletmid,right=matchupper_boundwith|Unbounded->mid_and_right,empty|Incllb->split_and_reinsert_boundary~into:`Leftmid_and_rightlb~compare_key|Excllb->split_and_reinsert_boundary~into:`Rightmid_and_rightlb~compare_keyinleft,mid,right);;letrecfindtx~compare_key=matchtwith|Empty->None|Leaf(v,d)->ifcompare_keyxv=0thenSomedelseNone|Node(l,v,d,r,_)->letc=compare_keyxvinifc=0thenSomedelsefind(ifc<0thenlelser)x~compare_key;;letadd_multit~length~key~data~compare_key=letdata=data::Option.value(findtkey~compare_key)~default:[]inset~length~key~datat~compare_key;;letfind_multitx~compare_key=matchfindtx~compare_keywith|None->[]|Somel->l;;letfind_exn=letif_not_foundkey~sexp_of_key=raise(Not_found_s(List[Atom"Map.find_exn: not found";sexp_of_keykey]))inletrecfind_exntx~compare_key~sexp_of_key=matchtwith|Empty->if_not_foundx~sexp_of_key|Leaf(v,d)->ifcompare_keyxv=0thendelseif_not_foundx~sexp_of_key|Node(l,v,d,r,_)->letc=compare_keyxvinifc=0thendelsefind_exn(ifc<0thenlelser)x~compare_key~sexp_of_keyin(* named to preserve symbol in compiled binary *)find_exn;;letmemtx~compare_key=Option.is_some(findtx~compare_key)letrecmin_elt=function|Empty->None|Leaf(k,d)->Some(k,d)|Node(Empty,k,d,_,_)->Some(k,d)|Node(l,_,_,_,_)->min_eltl;;exceptionMap_min_elt_exn_of_empty_map[@@deriving_inlinesexp]let()=Ppx_sexp_conv_lib.Conv.Exn_converter.add[%extension_constructorMap_min_elt_exn_of_empty_map](function|Map_min_elt_exn_of_empty_map->Ppx_sexp_conv_lib.Sexp.Atom"map.ml.Tree0.Map_min_elt_exn_of_empty_map"|_->assertfalse);;[@@@end]exceptionMap_max_elt_exn_of_empty_map[@@deriving_inlinesexp]let()=Ppx_sexp_conv_lib.Conv.Exn_converter.add[%extension_constructorMap_max_elt_exn_of_empty_map](function|Map_max_elt_exn_of_empty_map->Ppx_sexp_conv_lib.Sexp.Atom"map.ml.Tree0.Map_max_elt_exn_of_empty_map"|_->assertfalse);;[@@@end]letmin_elt_exnt=matchmin_elttwith|None->raiseMap_min_elt_exn_of_empty_map|Somev->v;;letrecmax_elt=function|Empty->None|Leaf(k,d)->Some(k,d)|Node(_,k,d,Empty,_)->Some(k,d)|Node(_,_,_,r,_)->max_eltr;;letmax_elt_exnt=matchmax_elttwith|None->raiseMap_max_elt_exn_of_empty_map|Somev->v;;letrecremove_min_eltt=matchtwith|Empty->invalid_arg"Map.remove_min_elt"|Leaf_->Empty|Node(Empty,_,_,r,_)->r|Node(l,x,d,r,_)->bal(remove_min_eltl)xdr;;letappend~lower_part~upper_part~compare_key=matchmax_eltlower_part,min_eltupper_partwith|None,_->`Okupper_part|_,None->`Oklower_part|Some(max_lower,_),Some(min_upper,v)whencompare_keymax_lowermin_upper<0->letupper_part_without_min=remove_min_eltupper_partin`Ok(join~compare_keylower_partmin_uppervupper_part_without_min)|_->`Overlapping_key_ranges;;letfold_range_inclusive=(* This assumes that min <= max, which is checked by the outer function. *)letrecgot~min~max~init~f~compare_key=matchtwith|Empty->init|Leaf(k,d)->ifcompare_keykmin<0||compare_keykmax>0then(* k < min || k > max *)initelsef~key:k~data:dinit|Node(l,k,d,r,_)->letc_min=compare_keykmininifc_min<0then(* if k < min, then this node and its left branch are outside our range *)gor~min~max~init~f~compare_keyelseifc_min=0then(* if k = min, then this node's left branch is outside our range *)gor~min~max~init:(f~key:k~data:dinit)~f~compare_keyelse((* k > min *)letz=gol~min~max~init~f~compare_keyinletc_max=compare_keykmaxin(* if k > max, we're done *)ifc_max>0thenzelse(letz=f~key:k~data:dzin(* if k = max, then we fold in this one last value and we're done *)ifc_max=0thenzelsegor~min~max~init:z~f~compare_key))infunt~min~max~init~f~compare_key->ifcompare_keyminmax<=0thengot~min~max~init~f~compare_keyelseinit;;letrange_to_alistt~min~max~compare_key=List.rev(fold_range_inclusivet~min~max~init:[]~f:(fun~key~datal->(key,data)::l)~compare_key);;letconcat_uncheckedt1t2=matcht1,t2with|Empty,t->t|t,Empty->t|_,_->letx,d=min_elt_exnt2inbalt1xd(remove_min_eltt2);;letrecremovetx~length~compare_key=matchtwith|Empty->Empty,length|Leaf(v,_)->ifcompare_keyxv=0thenEmpty,length-1elset,length|Node(l,v,d,r,_)->letc=compare_keyxvinifc=0thenconcat_uncheckedlr,length-1elseifc<0then(letl,length=removelx~length~compare_keyinballvdr,length)else(letr,length=removerx~length~compare_keyinballvdr,length);;(* Use exception to avoid tree-rebuild in no-op case *)exceptionChange_no_opletchangetkey~f~length~compare_key=letrecchange_coretkeyf=matchtwith|Empty->(matchfNonewith|None->raiseChange_no_op(* equivalent to returning: Empty *)|Somedata->Leaf(key,data),length+1)|Leaf(v,d)->letc=compare_keykeyvinifc=0then(matchf(Somed)with|None->Empty,length-1|Somed'->Leaf(v,d'),length)elseifc<0then(letl,length=change_coreEmptykeyfinballvdEmpty,length)else(letr,length=change_coreEmptykeyfinbalEmptyvdr,length)|Node(l,v,d,r,h)->letc=compare_keykeyvinifc=0then(matchf(Somed)with|None->concat_uncheckedlr,length-1|Somedata->Node(l,key,data,r,h),length)elseifc<0then(letl,length=change_corelkeyfinballvdr,length)else(letr,length=change_corerkeyfinballvdr,length)intrychange_coretkeyfwith|Change_no_op->t,length;;letupdatetkey~f~length~compare_key=letrecupdate_coretkeyf=matchtwith|Empty->letdata=fNoneinLeaf(key,data),length+1|Leaf(v,d)->letc=compare_keykeyvinifc=0then(letd'=f(Somed)inLeaf(v,d'),length)elseifc<0then(letl,length=update_coreEmptykeyfinballvdEmpty,length)else(letr,length=update_coreEmptykeyfinbalEmptyvdr,length)|Node(l,v,d,r,h)->letc=compare_keykeyvinifc=0then(letdata=f(Somed)inNode(l,key,data,r,h),length)elseifc<0then(letl,length=update_corelkeyfinballvdr,length)else(letr,length=update_corerkeyfinballvdr,length)inupdate_coretkeyf;;letremove_multitkey~length~compare_key=changetkey~length~compare_key~f:(function|None|Some([]|[_])->None|Some(_::(_::_asnon_empty_tail))->Somenon_empty_tail);;letreciter_keyst~f=matchtwith|Empty->()|Leaf(v,_)->fv|Node(l,v,_,r,_)->iter_keys~fl;fv;iter_keys~fr;;letrecitert~f=matchtwith|Empty->()|Leaf(_,d)->fd|Node(l,_,d,r,_)->iter~fl;fd;iter~fr;;letreciterit~f=matchtwith|Empty->()|Leaf(v,d)->f~key:v~data:d|Node(l,v,d,r,_)->iteri~fl;f~key:v~data:d;iteri~fr;;letiteri_until=letreciteri_until_loopt~f:Continue_or_stop.t=matchtwith|Empty->Continue|Leaf(v,d)->f~key:v~data:d|Node(l,v,d,r,_)->(matchiteri_until_loop~flwith|Stop->Stop|Continue->(matchf~key:v~data:dwith|Stop->Stop|Continue->iteri_until_loop~fr))infunt~f->Finished_or_unfinished.of_continue_or_stop(iteri_until_loopt~f);;letrecmapt~f=matchtwith|Empty->Empty|Leaf(v,d)->Leaf(v,fd)|Node(l,v,d,r,h)->letl'=map~flinletd'=fdinletr'=map~frinNode(l',v,d',r',h);;letrecmapit~f=matchtwith|Empty->Empty|Leaf(v,d)->Leaf(v,f~key:v~data:d)|Node(l,v,d,r,h)->letl'=mapi~flinletd'=f~key:v~data:dinletr'=mapi~frinNode(l',v,d',r',h);;letrecfoldt~init:accu~f=matchtwith|Empty->accu|Leaf(v,d)->f~key:v~data:daccu|Node(l,v,d,r,_)->fold~fr~init:(f~key:v~data:d(fold~fl~init:accu));;letrecfold_rightt~init:accu~f=matchtwith|Empty->accu|Leaf(v,d)->f~key:v~data:daccu|Node(l,v,d,r,_)->fold_right~fl~init:(f~key:v~data:d(fold_right~fr~init:accu));;letfilter_keyst~f~compare_key=fold~init:(Empty,0)t~f:(fun~key~data(accu,length)->iffkeythenset~length~key~dataaccu~compare_keyelseaccu,length);;letfiltert~f~compare_key=fold~init:(Empty,0)t~f:(fun~key~data(accu,length)->iffdatathenset~length~key~dataaccu~compare_keyelseaccu,length);;letfilterit~f~compare_key=fold~init:(Empty,0)t~f:(fun~key~data(accu,length)->iff~key~datathenset~length~key~dataaccu~compare_keyelseaccu,length);;letfilter_mapt~f~compare_key=fold~init:(Empty,0)t~f:(fun~key~data(accu,length)->matchfdatawith|None->accu,length|Someb->set~length~key~data:baccu~compare_key);;letfilter_mapit~f~compare_key=fold~init:(Empty,0)t~f:(fun~key~data(accu,length)->matchf~key~datawith|None->accu,length|Someb->set~length~key~data:baccu~compare_key);;letpartition_mapit~f~compare_key=foldt~init:((Empty,0),(Empty,0))~f:(fun~key~data(pair1,pair2)->match(f~key~data:_Either.t)with|Firstx->lett,length=pair1insett~key~data:x~compare_key~length,pair2|Secondy->lett,length=pair2inpair1,sett~key~data:y~compare_key~length);;letpartition_mapt~f~compare_key=partition_mapit~compare_key~f:(fun~key:_~data->fdata);;letpartitioni_tft~f~compare_key=partition_mapit~compare_key~f:(fun~key~data->iff~key~datathenFirstdataelseSeconddata);;letpartition_tft~f~compare_key=partition_mapit~compare_key~f:(fun~key:_~data->iffdatathenFirstdataelseSeconddata);;moduleEnum=structtypeincreasingtypedecreasingtype('k,'v,'direction)t=|End|Moreof'k*'v*('k,'v)tree*('k,'v,'direction)tletrecconst(e:(_,_,increasing)t):(_,_,increasing)t=matchtwith|Empty->e|Leaf(v,d)->More(v,d,Empty,e)|Node(l,v,d,r,_)->consl(More(v,d,r,e));;letreccons_rightt(e:(_,_,decreasing)t):(_,_,decreasing)t=matchtwith|Empty->e|Leaf(v,d)->More(v,d,Empty,e)|Node(l,v,d,r,_)->cons_rightr(More(v,d,l,e));;letof_treetree:(_,_,increasing)t=constreeEndletof_tree_righttree:(_,_,decreasing)t=cons_righttreeEndletstarting_at_increasingtkeycompare:(_,_,increasing)t=letrecloopte=matchtwith|Empty->e|Leaf(v,d)->loop(Node(Empty,v,d,Empty,1))e|Node(_,v,_,r,_)whencomparevkey<0->loopre|Node(l,v,d,r,_)->loopl(More(v,d,r,e))inlooptEnd;;letstarting_at_decreasingtkeycompare:(_,_,decreasing)t=letrecloopte=matchtwith|Empty->e|Leaf(v,d)->loop(Node(Empty,v,d,Empty,1))e|Node(l,v,_,_,_)whencomparevkey>0->loople|Node(l,v,d,r,_)->loopr(More(v,d,l,e))inlooptEnd;;letcomparecompare_keycompare_datat1t2=letrecloopt1t2=matcht1,t2with|End,End->0|End,_->-1|_,End->1|More(v1,d1,r1,e1),More(v2,d2,r2,e2)->letc=compare_keyv1v2inifc<>0thencelse(letc=compare_datad1d2inifc<>0thencelseifphys_equalr1r2thenloope1e2elseloop(consr1e1)(consr2e2))inloopt1t2;;letequalcompare_keydata_equalt1t2=letrecloopt1t2=matcht1,t2with|End,End->true|End,_|_,End->false|More(v1,d1,r1,e1),More(v2,d2,r2,e2)->compare_keyv1v2=0&&data_equald1d2&&ifphys_equalr1r2thenloope1e2elseloop(consr1e1)(consr2e2)inloopt1t2;;letrecfold~init~f=function|End->init|More(key,data,tree,enum)->letnext=f~key~datainitinfold(constreeenum)~init:next~f;;letfold2compare_keyt1t2~init~f=letrecloopt1t2curr=matcht1,t2with|End,End->curr|End,_->foldt2~init:curr~f:(fun~key~dataacc->f~key~data:(`Rightdata)acc)|_,End->foldt1~init:curr~f:(fun~key~dataacc->f~key~data:(`Leftdata)acc)|More(k1,v1,tree1,enum1),More(k2,v2,tree2,enum2)->letcompare_result=compare_keyk1k2inifcompare_result=0then(letnext=f~key:k1~data:(`Both(v1,v2))currinloop(constree1enum1)(constree2enum2)next)elseifcompare_result<0then(letnext=f~key:k1~data:(`Leftv1)currinloop(constree1enum1)t2next)else(letnext=f~key:k2~data:(`Rightv2)currinloopt1(constree2enum2)next)inloopt1t2init;;letsymmetric_difft1t2~compare_key~data_equal=letstepstate=matchstatewith|End,End->Sequence.Step.Done|End,More(key,data,tree,enum)->Sequence.Step.Yield((key,`Rightdata),(End,constreeenum))|More(key,data,tree,enum),End->Sequence.Step.Yield((key,`Leftdata),(constreeenum,End))|(More(k1,v1,tree1,enum1)asleft),(More(k2,v2,tree2,enum2)asright)->letcompare_result=compare_keyk1k2inifcompare_result=0then(letnext_state=ifphys_equaltree1tree2thenenum1,enum2elseconstree1enum1,constree2enum2inifdata_equalv1v2thenSequence.Step.Skipnext_stateelseSequence.Step.Yield((k1,`Unequal(v1,v2)),next_state))elseifcompare_result<0thenSequence.Step.Yield((k1,`Leftv1),(constree1enum1,right))elseSequence.Step.Yield((k2,`Rightv2),(left,constree2enum2))inSequence.unfold_step~init:(of_treet1,of_treet2)~f:step;;letfold_symmetric_difft1t2~compare_key~data_equal~init~f=letaddacckv=facc(k,`Rightv)inletremoveacckv=facc(k,`Leftv)inletrecloopleftrightacc=matchleft,rightwith|End,enum->foldenum~init:acc~f:(fun~key~dataacc->addacckeydata)|enum,End->foldenum~init:acc~f:(fun~key~dataacc->removeacckeydata)|(More(k1,v1,tree1,enum1)asleft),(More(k2,v2,tree2,enum2)asright)->letcompare_result=compare_keyk1k2inifcompare_result=0then(letacc=ifdata_equalv1v2thenaccelsefacc(k1,`Unequal(v1,v2))inifphys_equaltree1tree2thenloopenum1enum2accelseloop(constree1enum1)(constree2enum2)acc)elseifcompare_result<0then(letacc=removeacck1v1inloop(constree1enum1)rightacc)else(letacc=addacck2v2inloopleft(constree2enum2)acc)inloop(of_treet1)(of_treet2)init;;endletto_sequence_increasingcomparator~from_keyt=letnextenum=matchenumwith|Enum.End->Sequence.Step.Done|Enum.More(k,v,t,e)->Sequence.Step.Yield((k,v),Enum.conste)inletinit=matchfrom_keywith|None->Enum.of_treet|Somekey->Enum.starting_at_increasingtkeycomparator.Comparator.compareinSequence.unfold_step~init~f:next;;letto_sequence_decreasingcomparator~from_keyt=letnextenum=matchenumwith|Enum.End->Sequence.Step.Done|Enum.More(k,v,t,e)->Sequence.Step.Yield((k,v),Enum.cons_rightte)inletinit=matchfrom_keywith|None->Enum.of_tree_rightt|Somekey->Enum.starting_at_decreasingtkeycomparator.Comparator.compareinSequence.unfold_step~init~f:next;;letto_sequencecomparator?(order=`Increasing_key)?keys_greater_or_equal_to?keys_less_or_equal_tot=letinclusive_boundsidetbound=letcompare_key=comparator.Comparator.compareinletl,maybe,r=splittbound~compare_keyinlett=side(l,r)inmatchmaybewith|None->t|Some(key,data)->set'tkeydata~compare_keyinmatchorderwith|`Increasing_key->lett=Option.foldkeys_less_or_equal_to~init:t~f:(inclusive_boundfst)into_sequence_increasingcomparator~from_key:keys_greater_or_equal_tot|`Decreasing_key->lett=Option.foldkeys_greater_or_equal_to~init:t~f:(inclusive_boundsnd)into_sequence_decreasingcomparator~from_key:keys_less_or_equal_tot;;letcomparecompare_keycompare_datat1t2=Enum.comparecompare_keycompare_data(Enum.of_treet1)(Enum.of_treet2);;letequalcompare_keycompare_datat1t2=Enum.equalcompare_keycompare_data(Enum.of_treet1)(Enum.of_treet2);;letiter2t1t2~f~compare_key=Enum.fold2compare_key(Enum.of_treet1)(Enum.of_treet2)~init:()~f:(fun~key~data()->f~key~data);;letfold2t1t2~init~f~compare_key=Enum.fold2compare_key(Enum.of_treet1)(Enum.of_treet2)~f~init;;letsymmetric_diff=Enum.symmetric_diffletfold_symmetric_difft1t2~compare_key~data_equal~init~f=(* [Enum.fold_diffs] is a correct implementation of this function, but is considerably
slower, as we have to allocate quite a lot of state to track enumeration of a tree.
Avoid if we can.
*)letslowxy~init=Enum.fold_symmetric_diffxy~compare_key~data_equal~f~initinletaddacckv=facc(k,`Rightv)inletremoveacckv=facc(k,`Leftv)inletdeltaacckvv'=ifdata_equalvv'thenaccelsefacc(k,`Unequal(v,v'))in(* If two trees have the same structure at the root (and the same key, if they're
[Node]s) we can trivially diff each subpart in obvious ways. *)letreclooptt'acc=ifphys_equaltt'thenaccelse(matcht,t'with|Empty,new_vals->foldnew_vals~init:acc~f:(fun~key~dataacc->addacckeydata)|old_vals,Empty->foldold_vals~init:acc~f:(fun~key~dataacc->removeacckeydata)|Leaf(k,v),Leaf(k',v')->(matchcompare_keykk'with|xwhenx=0->deltaacckvv'|xwhenx<0->letacc=removeacckvinaddacck'v'|_(* when x > 0 *)->letacc=addacck'v'inremoveacckv)|Node(l,k,v,r,_),Node(l',k',v',r',_)whencompare_keykk'=0->letacc=loopll'accinletacc=deltaacckvv'inlooprr'acc(* Our roots aren't the same key. Fallback to the slow mode. Trees with small
diffs will only do this on very small parts of the tree (hopefully - if the
overall root is rebalanced, we'll eat the whole cost, unfortunately.) *)|Node_,Node_|Node_,Leaf_|Leaf_,Node_->slowtt'~init:acc)inloopt1t2init;;letreclength=function|Empty->0|Leaf_->1|Node(l,_,_,r,_)->lengthl+lengthr+1;;lethash_fold_t_ignoring_structurehash_fold_keyhash_fold_datastatet=foldt~init:(hash_fold_intstate(lengtht))~f:(fun~key~datastate->hash_fold_data(hash_fold_keystatekey)data);;letkeyst=fold_right~f:(fun~key~data:_list->key::list)t~init:[]letdatat=fold_right~f:(fun~key:_~datalist->data::list)t~init:[]moduletypeFoldable=sigvalname:stringtype'atvalfold:'at->init:'b->f:('b->'a->'b)->'bendmoduleOf_foldable(M:Foldable)=structletof_foldable_foldfoldable~init~f~compare_key=M.foldfoldable~init:(empty,0)~f:(fun(accum,length)(key,data)->letprev_data=matchfindaccumkey~compare_keywith|None->init|Someprev->previnletdata=fprev_datadatainsetaccum~length~key~data~compare_key);;letof_foldable_reducefoldable~f~compare_key=M.foldfoldable~init:(empty,0)~f:(fun(accum,length)(key,data)->letnew_data=matchfindaccumkey~compare_keywith|None->data|Someprev->fprevdatainsetaccum~length~key~data:new_data~compare_key);;letof_foldablefoldable~compare_key=with_return(funr->letmap=M.foldfoldable~init:(empty,0)~f:(fun(t,length)(key,data)->let((_,length')asacc)=set~length~key~datat~compare_keyiniflength=length'thenr.return(`Duplicate_keykey)elseacc)in`Okmap);;letof_foldable_or_errorfoldable~comparator=matchof_foldablefoldable~compare_key:comparator.Comparator.comparewith|`Okx->Result.Okx|`Duplicate_keykey->Or_error.error("Map.of_"^M.name^"_or_error: duplicate key")keycomparator.sexp_of_t;;letof_foldable_exnfoldable~comparator=matchof_foldablefoldable~compare_key:comparator.Comparator.comparewith|`Okx->x|`Duplicate_keykey->Error.create("Map.of_"^M.name^"_exn: duplicate key")keycomparator.sexp_of_t|>Error.raise;;endmoduleOf_alist=Of_foldable(structletname="alist"type'at='alistletfold=List.foldend)letof_alist_fold=Of_alist.of_foldable_foldletof_alist_reduce=Of_alist.of_foldable_reduceletof_alist=Of_alist.of_foldableletof_alist_or_error=Of_alist.of_foldable_or_errorletof_alist_exn=Of_alist.of_foldable_exn(* Reverse the input, then fold from left to right. The resulting map uses the first
instance of each key from the input list. The relative ordering of elements in each
output list is the same as in the input list. *)letof_foldable_multifoldable~fold~compare_key=letalist=foldfoldable~init:[]~f:(funlx->x::l)inof_alist_foldalist~init:[]~f:(funlx->x::l)~compare_key;;letof_alist_multialist~compare_key=of_foldable_multialist~fold:List.fold~compare_key;;moduleOf_sequence=Of_foldable(structletname="sequence"type'at='aSequence.tletfold=Sequence.foldend)letof_sequence_fold=Of_sequence.of_foldable_foldletof_sequence_reduce=Of_sequence.of_foldable_reduceletof_sequence=Of_sequence.of_foldableletof_sequence_or_error=Of_sequence.of_foldable_or_errorletof_sequence_exn=Of_sequence.of_foldable_exnletof_sequence_multisequence~compare_key=of_foldable_multisequence~fold:Sequence.fold~compare_key;;letfor_allt~f=with_return(funr->itert~f:(fundata->ifnot(fdata)thenr.returnfalse);true);;letfor_allit~f=with_return(funr->iterit~f:(fun~key~data->ifnot(f~key~data)thenr.returnfalse);true);;letexistst~f=with_return(funr->itert~f:(fundata->iffdatathenr.returntrue);false);;letexistsit~f=with_return(funr->iterit~f:(fun~key~data->iff~key~datathenr.returntrue);false);;letcountt~f=foldt~init:0~f:(fun~key:_~dataacc->iffdatathenacc+1elseacc);;letcountit~f=foldt~init:0~f:(fun~key~dataacc->iff~key~datathenacc+1elseacc);;letto_alist?(key_order=`Increasing)t=matchkey_orderwith|`Increasing->fold_rightt~init:[]~f:(fun~key~datax->(key,data)::x)|`Decreasing->foldt~init:[]~f:(fun~key~datax->(key,data)::x);;letmerget1t2~f~compare_key=letelts=Uniform_array.unsafe_create_uninitialized~len:(lengtht1+lengtht2)inleti=ref0initer2t1t2~compare_key~f:(fun~key~data:values->matchf~keyvalueswith|Somevalue->Uniform_array.setelts!i(key,value);incri|None->());letlen=!iinletgeti=Uniform_array.geteltsiinlettree=of_increasing_iterator_unchecked~len~f:getintree,len;;moduleClosest_key_impl=struct(* [marker] and [repackage] allow us to create "logical" options without actually
allocating any options. Passing [Found key value] to a function is equivalent to
passing [Some (key, value)]; passing [Missing () ()] is equivalent to passing
[None]. *)type('k,'v,'k_opt,'v_opt)marker=|Missing:('k,'v,unit,unit)marker|Found:('k,'v,'k,'v)markerletrepackage(typekvk_optv_opt)(marker:(k,v,k_opt,v_opt)marker)(k:k_opt)(v:v_opt):(k*v)option=matchmarkerwith|Missing->None|Found->Some(k,v);;(* The type signature is explicit here to allow polymorphic recursion. *)letrecloop:'k'v'k_opt'v_opt.('k,'v)tree->[`Greater_or_equal_to|`Greater_than|`Less_or_equal_to|`Less_than]->'k->compare_key:('k->'k->int)->('k,'v,'k_opt,'v_opt)marker->'k_opt->'v_opt->('k*'v)option=funtdirk~compare_keyfound_markerfound_keyfound_value->matchtwith|Empty->repackagefound_markerfound_keyfound_value|Leaf(k',v')->letc=compare_keyk'kinifmatchdirwith|`Greater_or_equal_to->c>=0|`Greater_than->c>0|`Less_or_equal_to->c<=0|`Less_than->c<0thenSome(k',v')elserepackagefound_markerfound_keyfound_value|Node(l,k',v',r,_)->letc=compare_keyk'kinifc=0then((* This is a base case (no recursive call). *)matchdirwith|`Greater_or_equal_to|`Less_or_equal_to->Some(k',v')|`Greater_than->ifis_emptyrthenrepackagefound_markerfound_keyfound_valueelsemin_eltr|`Less_than->ifis_emptylthenrepackagefound_markerfound_keyfound_valueelsemax_eltl)else((* We are guaranteed here that k' <> k. *)(* This is the only recursive case. *)matchdirwith|`Greater_or_equal_to|`Greater_than->ifc>0thenloopldirk~compare_keyFoundk'v'elselooprdirk~compare_keyfound_markerfound_keyfound_value|`Less_or_equal_to|`Less_than->ifc<0thenlooprdirk~compare_keyFoundk'v'elseloopldirk~compare_keyfound_markerfound_keyfound_value);;letclosest_keytdirk~compare_key=looptdirk~compare_keyMissing()()endletclosest_key=Closest_key_impl.closest_keyletrecranktk~compare_key=matchtwith|Empty->None|Leaf(k',_)->ifcompare_keyk'k=0thenSome0elseNone|Node(l,k',_,r,_)->letc=compare_keyk'kinifc=0thenSome(lengthl)elseifc>0thenranklk~compare_keyelseOption.map(rankrk~compare_key)~f:(funrank->rank+1+lengthl);;(* this could be implemented using [Sequence] interface but the following implementation
allocates only 2 words and doesn't require write-barrier *)letrecnth'num_to_search=function|Empty->None|Leaf(k,v)->if!num_to_search=0thenSome(k,v)else(decrnum_to_search;None)|Node(l,k,v,r,_)->(matchnth'num_to_searchlwith|Some_assome->some|None->if!num_to_search=0thenSome(k,v)else(decrnum_to_search;nth'num_to_searchr));;letnthtn=nth'(refn)tletrecfind_first_satisfyingt~f=matchtwith|Empty->None|Leaf(k,v)->iff~key:k~data:vthenSome(k,v)elseNone|Node(l,k,v,r,_)->iff~key:k~data:vthen(matchfind_first_satisfyingl~fwith|None->Some(k,v)|Some_asx->x)elsefind_first_satisfyingr~f;;letrecfind_last_satisfyingt~f=matchtwith|Empty->None|Leaf(k,v)->iff~key:k~data:vthenSome(k,v)elseNone|Node(l,k,v,r,_)->iff~key:k~data:vthen(matchfind_last_satisfyingr~fwith|None->Some(k,v)|Some_asx->x)elsefind_last_satisfyingl~f;;letbinary_searcht~comparehowv=matchhowwith|`Last_strictly_less_than->find_last_satisfyingt~f:(fun~key~data->compare~key~datav<0)|`Last_less_than_or_equal_to->find_last_satisfyingt~f:(fun~key~data->compare~key~datav<=0)|`First_equal_to->(matchfind_first_satisfyingt~f:(fun~key~data->compare~key~datav>=0)with|Some(key,data)aspairwhencompare~key~datav=0->pair|None|Some_->None)|`Last_equal_to->(matchfind_last_satisfyingt~f:(fun~key~data->compare~key~datav<=0)with|Some(key,data)aspairwhencompare~key~datav=0->pair|None|Some_->None)|`First_greater_than_or_equal_to->find_first_satisfyingt~f:(fun~key~data->compare~key~datav>=0)|`First_strictly_greater_than->find_first_satisfyingt~f:(fun~key~data->compare~key~datav>0);;letbinary_search_segmentedt~segment_ofhow=letis_left~key~data=matchsegment_of~key~datawith|`Left->true|`Right->falseinletis_right~key~data=not(is_left~key~data)inmatchhowwith|`Last_on_left->find_last_satisfyingt~f:is_left|`First_on_right->find_first_satisfyingt~f:is_right;;type('k,'v)acc={mutablebad_key:'koption;mutablemap_length:('k,'v)t*int}letof_iteri~iteri~compare_key=letacc={bad_key=None;map_length=empty,0}initeri~f:(fun~key~data->letmap,length=acc.map_lengthinlet((_,length')aspair)=set~length~key~datamap~compare_keyiniflength=length'&&Option.is_noneacc.bad_keythenacc.bad_key<-Somekeyelseacc.map_length<-pair);matchacc.bad_keywith|None->`Okacc.map_length|Somekey->`Duplicate_keykey;;lett_of_sexp_directkey_of_sexpvalue_of_sexpsexp~(comparator:_Comparator.t)=letalist=list_of_sexp(pair_of_sexpkey_of_sexpvalue_of_sexp)sexpinletcompare_key=comparator.compareinmatchof_alistalist~compare_keywith|`Okv->v|`Duplicate_keyk->(* find the sexp of a duplicate key, so the error is narrowed to a key and not
the whole map *)letalist_sexps=list_of_sexp(pair_of_sexpFn.idFn.id)sexpinletfound_first_k=reffalseinList.iter2_okalistalist_sexps~f:(fun(k2,_)(k2_sexp,_)->ifcompare_keykk2=0thenif!found_first_kthenof_sexp_error"Map.t_of_sexp_direct: duplicate key"k2_sexpelsefound_first_k:=true);assertfalse;;letsexp_of_tsexp_of_keysexp_of_valuet=letf~key~dataacc=Sexp.List[sexp_of_keykey;sexp_of_valuedata]::accinSexp.List(fold_right~ft~init:[]);;letcombine_errorst~compare_key~sexp_of_key=letoks,(error_tree,_)=partition_mapt~compare_key~f:Result.to_eitherinifis_emptyerror_treethenOkokselseOr_error.error_s(sexp_of_tsexp_of_keyError.sexp_of_terror_tree);;endtype('k,'v,'comparator)t={(* [comparator] is the first field so that polymorphic equality fails on a map due
to the functional value in the comparator.
Note that this does not affect polymorphic [compare]: that still produces
nonsense. *)comparator:('k,'comparator)Comparator.t;tree:('k,'v)Tree0.t;length:int}type('k,'v,'comparator)tree=('k,'v)Tree0.tletcompare_keyt=t.comparator.Comparator.compareletlike{tree=_;length=_;comparator}(tree,length)={tree;length;comparator};;letlike2x(y,z)=likexy,likexzletwith_same_length{tree=_;comparator;length}tree={tree;comparator;length}letof_tree~comparatortree={tree;comparator;length=Tree0.lengthtree}(* Exposing this function would make it very easy for the invariants
of this module to be broken. *)letof_tree_unsafe~comparator~lengthtree={tree;comparator;length}moduleAccessors=structletcomparatort=t.comparatorletto_treet=t.treeletinvariantst=Tree0.invariantst.tree~compare_key:(compare_keyt)letis_emptyt=Tree0.is_emptyt.treeletlengtht=t.lengthletsett~key~data=liket(Tree0.sett.tree~length:t.length~key~data~compare_key:(compare_keyt));;letadd_exnt~key~data=liket(Tree0.add_exnt.tree~length:t.length~key~data~compare_key:(compare_keyt)~sexp_of_key:t.comparator.sexp_of_t);;letadd_exn_internalt~key~data=liket(Tree0.add_exn_internalt.tree~length:t.length~key~data~compare_key:(compare_keyt)~sexp_of_key:t.comparator.sexp_of_t);;letaddt~key~data=matchadd_exn_internalt~key~datawith|result->`Okresult|exceptionDuplicate->`Duplicate;;letadd_multit~key~data=liket(Tree0.add_multit.tree~length:t.length~key~data~compare_key:(compare_keyt));;letremove_multitkey=liket(Tree0.remove_multit.tree~length:t.lengthkey~compare_key:(compare_keyt));;letfind_multitkey=Tree0.find_multit.treekey~compare_key:(compare_keyt)letchangetkey~f=liket(Tree0.changet.treekey~f~length:t.length~compare_key:(compare_keyt));;letupdatetkey~f=liket(Tree0.updatet.treekey~f~length:t.length~compare_key:(compare_keyt));;letfind_exntkey=Tree0.find_exnt.treekey~compare_key:(compare_keyt)~sexp_of_key:t.comparator.sexp_of_t;;letfindtkey=Tree0.findt.treekey~compare_key:(compare_keyt)letremovetkey=liket(Tree0.removet.treekey~length:t.length~compare_key:(compare_keyt));;letmemtkey=Tree0.memt.treekey~compare_key:(compare_keyt)letiter_keyst~f=Tree0.iter_keyst.tree~fletitert~f=Tree0.itert.tree~fletiterit~f=Tree0.iterit.tree~fletiteri_untilt~f=Tree0.iteri_untilt.tree~fletiter2t1t2~f=Tree0.iter2t1.treet2.tree~f~compare_key:(compare_keyt1)letmapt~f=with_same_lengtht(Tree0.mapt.tree~f)letmapit~f=with_same_lengtht(Tree0.mapit.tree~f)letfoldt~init~f=Tree0.foldt.tree~f~initletfold_rightt~init~f=Tree0.fold_rightt.tree~f~initletfold2t1t2~init~f=Tree0.fold2t1.treet2.tree~init~f~compare_key:(compare_keyt1);;letfilter_keyst~f=liket(Tree0.filter_keyst.tree~f~compare_key:(compare_keyt));;letfiltert~f=liket(Tree0.filtert.tree~f~compare_key:(compare_keyt))letfilterit~f=liket(Tree0.filterit.tree~f~compare_key:(compare_keyt))letfilter_mapt~f=liket(Tree0.filter_mapt.tree~f~compare_key:(compare_keyt))letfilter_mapit~f=liket(Tree0.filter_mapit.tree~f~compare_key:(compare_keyt));;letpartition_mapit~f=like2t(Tree0.partition_mapit.tree~f~compare_key:(compare_keyt));;letpartition_mapt~f=like2t(Tree0.partition_mapt.tree~f~compare_key:(compare_keyt));;letpartitioni_tft~f=like2t(Tree0.partitioni_tft.tree~f~compare_key:(compare_keyt));;letpartition_tft~f=like2t(Tree0.partition_tft.tree~f~compare_key:(compare_keyt));;letcombine_errorst=Or_error.map~f:(liket)(Tree0.combine_errorst.tree~compare_key:(compare_keyt)~sexp_of_key:t.comparator.sexp_of_t);;letcompare_directcompare_datat1t2=Tree0.compare(compare_keyt1)compare_datat1.treet2.tree;;letequalcompare_datat1t2=Tree0.equal(compare_keyt1)compare_datat1.treet2.tree;;letkeyst=Tree0.keyst.treeletdatat=Tree0.datat.treeletto_alist?key_ordert=Tree0.to_alist?key_ordert.treeletvalidate~nameft=Validate.alist~namef(to_alistt)letvalidatei~nameft=Validate.list~name:(Fn.composenamefst)f(to_alistt)letsymmetric_difft1t2~data_equal=Tree0.symmetric_difft1.treet2.tree~compare_key:(compare_keyt1)~data_equal;;letfold_symmetric_difft1t2~data_equal~init~f=Tree0.fold_symmetric_difft1.treet2.tree~compare_key:(compare_keyt1)~data_equal~init~f;;letmerget1t2~f=liket1(Tree0.merget1.treet2.tree~f~compare_key:(compare_keyt1));;letmin_eltt=Tree0.min_eltt.treeletmin_elt_exnt=Tree0.min_elt_exnt.treeletmax_eltt=Tree0.max_eltt.treeletmax_elt_exnt=Tree0.max_elt_exnt.treeletfor_allt~f=Tree0.for_allt.tree~fletfor_allit~f=Tree0.for_allit.tree~fletexistst~f=Tree0.existst.tree~fletexistsit~f=Tree0.existsit.tree~fletcountt~f=Tree0.countt.tree~fletcountit~f=Tree0.countit.tree~fletsplittk=letl,maybe,r=Tree0.splitt.treek~compare_key:(compare_keyt)inletcomparator=comparatortin(* Try to traverse the least amount possible to calculate the length,
using height as a heuristic. *)letboth_len=ifOption.is_somemaybethent.length-1elset.lengthinifTree0.heightl<Tree0.heightrthen(letl=of_treel~comparatorinl,maybe,of_tree_unsafer~comparator~length:(both_len-lengthl))else(letr=of_treer~comparatorinof_tree_unsafel~comparator~length:(both_len-lengthr),maybe,r);;letsubranget~lower_bound~upper_bound=letleft,mid,right=Tree0.split_ranget.tree~lower_bound~upper_bound~compare_key:(compare_keyt)in(* Try to traverse the least amount possible to calculate the length,
using height as a heuristic. *)letouter_joined_height=leth_l=Tree0.heightleftandh_r=Tree0.heightrightinifh_l=h_rthenh_l+1elsemaxh_lh_rinifouter_joined_height<Tree0.heightmidthen(letmid_length=t.length-(Tree0.lengthleft+Tree0.lengthright)inof_tree_unsafemid~comparator:(comparatort)~length:mid_length)elseof_treemid~comparator:(comparatort);;letappend~lower_part~upper_part=matchTree0.append~compare_key:(compare_keylower_part)~lower_part:lower_part.tree~upper_part:upper_part.treewith|`Oktree->`Ok(of_tree_unsafetree~comparator:(comparatorlower_part)~length:(lower_part.length+upper_part.length))|`Overlapping_key_ranges->`Overlapping_key_ranges;;letfold_range_inclusivet~min~max~init~f=Tree0.fold_range_inclusivet.tree~min~max~init~f~compare_key:(compare_keyt);;letrange_to_alistt~min~max=Tree0.range_to_alistt.tree~min~max~compare_key:(compare_keyt);;letclosest_keytdirkey=Tree0.closest_keyt.treedirkey~compare_key:(compare_keyt);;letnthtn=Tree0.ntht.treenletnth_exntn=Option.value_exn(nthtn)letranktkey=Tree0.rankt.treekey~compare_key:(compare_keyt)letsexp_of_tsexp_of_ksexp_of_v_t=Tree0.sexp_of_tsexp_of_ksexp_of_vt.treeletto_sequence?order?keys_greater_or_equal_to?keys_less_or_equal_tot=Tree0.to_sequencet.comparator?order?keys_greater_or_equal_to?keys_less_or_equal_tot.tree;;letbinary_searcht~comparehowv=Tree0.binary_searcht.tree~comparehowvletbinary_search_segmentedt~segment_ofhow=Tree0.binary_search_segmentedt.tree~segment_ofhow;;lethash_fold_directhash_fold_keyhash_fold_datastatet=Tree0.hash_fold_t_ignoring_structurehash_fold_keyhash_fold_datastatet.tree;;end(* [0] is used as the [length] argument everywhere in this module, since trees do not
have their lengths stored at the root, unlike maps. The values are discarded always. *)moduleTree=structtype('k,'v,'comparator)t=('k,'v,'comparator)treeletempty_without_value_restriction=Tree0.emptyletempty~comparator:_=empty_without_value_restrictionletof_tree~comparator:_tree=treeletsingleton~comparator:_kv=Tree0.singletonkvletof_sorted_array_unchecked~comparatorarray=fst(Tree0.of_sorted_array_uncheckedarray~compare_key:comparator.Comparator.compare);;letof_sorted_array~comparatorarray=Tree0.of_sorted_arrayarray~compare_key:comparator.Comparator.compare|>Or_error.map~f:fst;;letof_alist~comparatoralist=matchTree0.of_alistalist~compare_key:comparator.Comparator.comparewith|`Duplicate_key_asd->d|`Ok(tree,_size)->`Oktree;;letof_alist_or_error~comparatoralist=Tree0.of_alist_or_erroralist~comparator|>Or_error.map~f:fst;;letof_alist_exn~comparatoralist=fst(Tree0.of_alist_exnalist~comparator)letof_alist_multi~comparatoralist=fst(Tree0.of_alist_multialist~compare_key:comparator.Comparator.compare);;letof_alist_fold~comparatoralist~init~f=fst(Tree0.of_alist_foldalist~init~f~compare_key:comparator.Comparator.compare);;letof_alist_reduce~comparatoralist~f=fst(Tree0.of_alist_reducealist~f~compare_key:comparator.Comparator.compare);;letof_iteri~comparator~iteri=matchTree0.of_iteri~iteri~compare_key:comparator.Comparator.comparewith|`Ok(tree,_size)->`Oktree|`Duplicate_key_asd->d;;letof_increasing_iterator_unchecked~comparator:_required_by_intf~len~f=Tree0.of_increasing_iterator_unchecked~len~f;;letof_increasing_sequence~comparatorseq=Or_error.map~f:fst(Tree0.of_increasing_sequenceseq~compare_key:comparator.Comparator.compare);;letof_sequence~comparatorseq=matchTree0.of_sequenceseq~compare_key:comparator.Comparator.comparewith|`Duplicate_key_asd->d|`Ok(tree,_size)->`Oktree;;letof_sequence_or_error~comparatorseq=Tree0.of_sequence_or_errorseq~comparator|>Or_error.map~f:fst;;letof_sequence_exn~comparatorseq=fst(Tree0.of_sequence_exnseq~comparator)letof_sequence_multi~comparatorseq=fst(Tree0.of_sequence_multiseq~compare_key:comparator.Comparator.compare);;letof_sequence_fold~comparatorseq~init~f=fst(Tree0.of_sequence_foldseq~init~f~compare_key:comparator.Comparator.compare);;letof_sequence_reduce~comparatorseq~f=fst(Tree0.of_sequence_reduceseq~f~compare_key:comparator.Comparator.compare);;letto_treet=tletinvariants~comparatort=Tree0.invariantst~compare_key:comparator.Comparator.compare;;letis_emptyt=Tree0.is_emptytletlengtht=Tree0.lengthtletset~comparatort~key~data=fst(Tree0.sett~key~data~length:0~compare_key:comparator.Comparator.compare);;letadd_exn~comparatort~key~data=fst(Tree0.add_exnt~key~data~length:0~compare_key:comparator.Comparator.compare~sexp_of_key:comparator.sexp_of_t);;letadd~comparatort~key~data=try`Ok(add_exnt~comparator~key~data)with|_->`Duplicate;;letadd_multi~comparatort~key~data=Tree0.add_multit~key~data~length:0~compare_key:comparator.Comparator.compare|>fst;;letremove_multi~comparatortkey=Tree0.remove_multitkey~length:0~compare_key:comparator.Comparator.compare|>fst;;letfind_multi~comparatortkey=Tree0.find_multitkey~compare_key:comparator.Comparator.compare;;letchange~comparatortkey~f=fst(Tree0.changetkey~f~length:0~compare_key:comparator.Comparator.compare);;letupdate~comparatortkey~f=change~comparatortkey~f:(fundata->Some(fdata));;letfind_exn~comparatortkey=Tree0.find_exntkey~compare_key:comparator.Comparator.compare~sexp_of_key:comparator.Comparator.sexp_of_t;;letfind~comparatortkey=Tree0.findtkey~compare_key:comparator.Comparator.compare;;letremove~comparatortkey=fst(Tree0.removetkey~length:0~compare_key:comparator.Comparator.compare);;letmem~comparatortkey=Tree0.memtkey~compare_key:comparator.Comparator.compareletiter_keyst~f=Tree0.iter_keyst~fletitert~f=Tree0.itert~fletiterit~f=Tree0.iterit~fletiteri_untilt~f=Tree0.iteri_untilt~fletiter2~comparatort1t2~f=Tree0.iter2t1t2~f~compare_key:comparator.Comparator.compare;;letmapt~f=Tree0.mapt~fletmapit~f=Tree0.mapit~fletfoldt~init~f=Tree0.foldt~f~initletfold_rightt~init~f=Tree0.fold_rightt~f~initletfold2~comparatort1t2~init~f=Tree0.fold2t1t2~init~f~compare_key:comparator.Comparator.compare;;letfilter_keys~comparatort~f=fst(Tree0.filter_keyst~f~compare_key:comparator.Comparator.compare);;letfilter~comparatort~f=fst(Tree0.filtert~f~compare_key:comparator.Comparator.compare);;letfilteri~comparatort~f=fst(Tree0.filterit~f~compare_key:comparator.Comparator.compare);;letfilter_map~comparatort~f=fst(Tree0.filter_mapt~f~compare_key:comparator.Comparator.compare);;letfilter_mapi~comparatort~f=fst(Tree0.filter_mapit~f~compare_key:comparator.Comparator.compare);;letpartition_mapi~comparatort~f=let(a,_),(b,_)=Tree0.partition_mapit~f~compare_key:comparator.Comparator.compareina,b;;letpartition_map~comparatort~f=let(a,_),(b,_)=Tree0.partition_mapt~f~compare_key:comparator.Comparator.compareina,b;;letpartitioni_tf~comparatort~f=let(a,_),(b,_)=Tree0.partitioni_tft~f~compare_key:comparator.Comparator.compareina,b;;letpartition_tf~comparatort~f=let(a,_),(b,_)=Tree0.partition_tft~f~compare_key:comparator.Comparator.compareina,b;;letcombine_errors~comparatort=Or_error.map~f:fst(Tree0.combine_errorst~compare_key:comparator.Comparator.compare~sexp_of_key:comparator.Comparator.sexp_of_t);;letcompare_direct~comparatorcompare_datat1t2=Tree0.comparecomparator.Comparator.comparecompare_datat1t2;;letequal~comparatorcompare_datat1t2=Tree0.equalcomparator.Comparator.comparecompare_datat1t2;;letkeyst=Tree0.keystletdatat=Tree0.datatletto_alist?key_ordert=Tree0.to_alist?key_ordertletvalidate~nameft=Validate.alist~namef(to_alistt)letvalidatei~nameft=Validate.list~name:(Fn.composenamefst)f(to_alistt)letsymmetric_diff~comparatort1t2~data_equal=Tree0.symmetric_difft1t2~compare_key:comparator.Comparator.compare~data_equal;;letfold_symmetric_diff~comparatort1t2~data_equal~init~f=Tree0.fold_symmetric_difft1t2~compare_key:comparator.Comparator.compare~data_equal~init~f;;letmerge~comparatort1t2~f=fst(Tree0.merget1t2~f~compare_key:comparator.Comparator.compare);;letmin_eltt=Tree0.min_elttletmin_elt_exnt=Tree0.min_elt_exntletmax_eltt=Tree0.max_elttletmax_elt_exnt=Tree0.max_elt_exntletfor_allt~f=Tree0.for_allt~fletfor_allit~f=Tree0.for_allit~fletexistst~f=Tree0.existst~fletexistsit~f=Tree0.existsit~fletcountt~f=Tree0.countt~fletcountit~f=Tree0.countit~fletsplit~comparatortk=Tree0.splittk~compare_key:comparator.Comparator.compareletappend~comparator~lower_part~upper_part=Tree0.append~lower_part~upper_part~compare_key:comparator.Comparator.compare;;letsubrange~comparatort~lower_bound~upper_bound=let_,ret,_=Tree0.split_ranget~lower_bound~upper_bound~compare_key:comparator.Comparator.compareinret;;letfold_range_inclusive~comparatort~min~max~init~f=Tree0.fold_range_inclusivet~min~max~init~f~compare_key:comparator.Comparator.compare;;letrange_to_alist~comparatort~min~max=Tree0.range_to_alistt~min~max~compare_key:comparator.Comparator.compare;;letclosest_key~comparatortdirkey=Tree0.closest_keytdirkey~compare_key:comparator.Comparator.compare;;letnth~comparator:_tn=Tree0.nthtnletnth_exn~comparatortn=Option.value_exn(nth~comparatortn)letrank~comparatortkey=Tree0.ranktkey~compare_key:comparator.Comparator.compare;;letsexp_of_tsexp_of_ksexp_of_v_t=Tree0.sexp_of_tsexp_of_ksexp_of_vtlett_of_sexp_direct~comparatork_of_sexpv_of_sexpsexp=fst(Tree0.t_of_sexp_directk_of_sexpv_of_sexpsexp~comparator);;letto_sequence~comparator?order?keys_greater_or_equal_to?keys_less_or_equal_tot=Tree0.to_sequencecomparator?order?keys_greater_or_equal_to?keys_less_or_equal_tot;;letbinary_search~comparator:_t~comparehowv=Tree0.binary_searcht~comparehowvletbinary_search_segmented~comparator:_t~segment_ofhow=Tree0.binary_search_segmentedt~segment_ofhow;;endmoduleUsing_comparator=structtypenonrec('k,'v,'cmp)t=('k,'v,'cmp)tincludeAccessorsletempty~comparator={tree=Tree0.empty;comparator;length=0}letsingleton~comparatorkv={comparator;tree=Tree0.singletonkv;length=1}letof_tree0~comparator(tree,length)={comparator;tree;length}letof_tree~comparatortree=of_tree0~comparator(tree,Tree0.lengthtree)letto_tree=to_treeletof_sorted_array_unchecked~comparatorarray=of_tree0~comparator(Tree0.of_sorted_array_uncheckedarray~compare_key:comparator.Comparator.compare);;letof_sorted_array~comparatorarray=Or_error.map(Tree0.of_sorted_arrayarray~compare_key:comparator.Comparator.compare)~f:(funtree->of_tree0~comparatortree);;letof_alist~comparatoralist=matchTree0.of_alistalist~compare_key:comparator.Comparator.comparewith|`Ok(tree,length)->`Ok{comparator;tree;length}|`Duplicate_key_asz->z;;letof_alist_or_error~comparatoralist=Result.map(Tree0.of_alist_or_erroralist~comparator)~f:(funtree->of_tree0~comparatortree);;letof_alist_exn~comparatoralist=of_tree0~comparator(Tree0.of_alist_exnalist~comparator);;letof_alist_multi~comparatoralist=of_tree0~comparator(Tree0.of_alist_multialist~compare_key:comparator.Comparator.compare);;letof_alist_fold~comparatoralist~init~f=of_tree0~comparator(Tree0.of_alist_foldalist~init~f~compare_key:comparator.Comparator.compare);;letof_alist_reduce~comparatoralist~f=of_tree0~comparator(Tree0.of_alist_reducealist~f~compare_key:comparator.Comparator.compare);;letof_iteri~comparator~iteri=matchTree0.of_iteri~compare_key:comparator.Comparator.compare~iteriwith|`Oktree_length->`Ok(of_tree0~comparatortree_length)|`Duplicate_key_asz->z;;letof_increasing_iterator_unchecked~comparator~len~f=of_tree0~comparator(Tree0.of_increasing_iterator_unchecked~len~f,len);;letof_increasing_sequence~comparatorseq=Or_error.map~f:(of_tree0~comparator)(Tree0.of_increasing_sequenceseq~compare_key:comparator.Comparator.compare);;letof_sequence~comparatorseq=matchTree0.of_sequenceseq~compare_key:comparator.Comparator.comparewith|`Ok(tree,length)->`Ok{comparator;tree;length}|`Duplicate_key_asz->z;;letof_sequence_or_error~comparatorseq=Result.map(Tree0.of_sequence_or_errorseq~comparator)~f:(funtree->of_tree0~comparatortree);;letof_sequence_exn~comparatorseq=of_tree0~comparator(Tree0.of_sequence_exnseq~comparator);;letof_sequence_multi~comparatorseq=of_tree0~comparator(Tree0.of_sequence_multiseq~compare_key:comparator.Comparator.compare);;letof_sequence_fold~comparatorseq~init~f=of_tree0~comparator(Tree0.of_sequence_foldseq~init~f~compare_key:comparator.Comparator.compare);;letof_sequence_reduce~comparatorseq~f=of_tree0~comparator(Tree0.of_sequence_reduceseq~f~compare_key:comparator.Comparator.compare);;lett_of_sexp_direct~comparatork_of_sexpv_of_sexpsexp=of_tree0~comparator(Tree0.t_of_sexp_directk_of_sexpv_of_sexpsexp~comparator);;moduleEmpty_without_value_restriction(K:Comparator.S1)=structletempty={tree=Tree0.empty;comparator=K.comparator;length=0}endmoduleTree=TreeendincludeAccessorstype('k,'cmp)comparator=(moduleComparator.Swithtypet='kandtypecomparator_witness='cmp)letcomparator_s(typekcmp)t:(k,cmp)comparator=(modulestructtypet=ktypecomparator_witness=cmpletcomparator=t.comparatorend);;letto_comparator(typekcmp)((moduleM):(k,cmp)comparator)=M.comparatorletemptym=Using_comparator.empty~comparator:(to_comparatorm)letsingletonma=Using_comparator.singleton~comparator:(to_comparatorm)aletof_alistma=Using_comparator.of_alist~comparator:(to_comparatorm)aletof_alist_or_errorma=Using_comparator.of_alist_or_error~comparator:(to_comparatorm)a;;letof_alist_exnma=Using_comparator.of_alist_exn~comparator:(to_comparatorm)aletof_alist_multima=Using_comparator.of_alist_multi~comparator:(to_comparatorm)aletof_alist_foldma~init~f=Using_comparator.of_alist_fold~comparator:(to_comparatorm)a~init~f;;letof_alist_reducema~f=Using_comparator.of_alist_reduce~comparator:(to_comparatorm)a~f;;letof_sorted_array_uncheckedma=Using_comparator.of_sorted_array_unchecked~comparator:(to_comparatorm)a;;letof_sorted_arrayma=Using_comparator.of_sorted_array~comparator:(to_comparatorm)a;;letof_iterim~iteri=Using_comparator.of_iteri~iteri~comparator:(to_comparatorm)letof_increasing_iterator_uncheckedm~len~f=Using_comparator.of_increasing_iterator_unchecked~len~f~comparator:(to_comparatorm);;letof_increasing_sequencemseq=Using_comparator.of_increasing_sequence~comparator:(to_comparatorm)seq;;letof_sequencems=Using_comparator.of_sequence~comparator:(to_comparatorm)sletof_sequence_or_errorms=Using_comparator.of_sequence_or_error~comparator:(to_comparatorm)s;;letof_sequence_exnms=Using_comparator.of_sequence_exn~comparator:(to_comparatorm)s;;letof_sequence_multims=Using_comparator.of_sequence_multi~comparator:(to_comparatorm)s;;letof_sequence_foldms~init~f=Using_comparator.of_sequence_fold~comparator:(to_comparatorm)s~init~f;;letof_sequence_reducems~f=Using_comparator.of_sequence_reduce~comparator:(to_comparatorm)s~f;;moduleM(K:sigtypettypecomparator_witnessend)=structtypenonrec'vt=(K.t,'v,K.comparator_witness)tendmoduletypeSexp_of_m=sigtypet[@@deriving_inlinesexp_of]valsexp_of_t:t->Ppx_sexp_conv_lib.Sexp.t[@@@end]endmoduletypeM_of_sexp=sigtypet[@@deriving_inlineof_sexp]valt_of_sexp:Ppx_sexp_conv_lib.Sexp.t->t[@@@end]includeComparator.Swithtypet:=tendmoduletypeCompare_m=sigendmoduletypeEqual_m=sigendmoduletypeHash_fold_m=Hasher.Sletsexp_of_m__t(typek)(moduleK:Sexp_of_mwithtypet=k)sexp_of_vt=sexp_of_tK.sexp_of_tsexp_of_v(fun_->Sexp.Atom"_")t;;letm__t_of_sexp(typekcmp)(moduleK:M_of_sexpwithtypet=kandtypecomparator_witness=cmp)v_of_sexpsexp=Using_comparator.t_of_sexp_direct~comparator:K.comparatorK.t_of_sexpv_of_sexpsexp;;letm__t_sexp_grammar:Ppx_sexp_conv_lib.Sexp.Private.Raw_grammar.t=Inline(Explicit_bind(["'k";"'v"],Apply(Grammarlist_sexp_grammar,[Apply(GrammarPpx_sexp_conv_lib.Sexp.Private.Raw_grammar.tuple2_sexp_grammar,[Explicit_var0;Explicit_var1])])));;letcompare_m__t(moduleK:Compare_m)compare_vt1t2=compare_directcompare_vt1t2letequal_m__t(moduleK:Equal_m)equal_vt1t2=equalequal_vt1t2lethash_fold_m__t(typek)(moduleK:Hash_fold_mwithtypet=k)hash_fold_vstate=hash_fold_directK.hash_fold_thash_fold_vstate;;letmerge_skewedt1t2~combine=lett1,t2,combine=iflengtht2<=lengtht1thent1,t2,combineelset2,t1,fun~keyv1v2->combine~keyv2v1infoldt2~init:t1~f:(fun~key~data:v2t1->changet1key~f:(function|None->Somev2|Somev1->Some(combine~keyv1v2)));;modulePoly=structtypenonrec('k,'v)t=('k,'v,Comparator.Poly.comparator_witness)ttypenonrec('k,'v)tree=('k,'v)Tree0.ttypecomparator_witness=Comparator.Poly.comparator_witnessincludeAccessorsletcomparator=Comparator.Poly.comparatorletof_treetree={tree;comparator;length=Tree0.lengthtree}includeUsing_comparator.Empty_without_value_restriction(Comparator.Poly)letsingletona=Using_comparator.singleton~comparatoraletof_alista=Using_comparator.of_alist~comparatoraletof_alist_or_errora=Using_comparator.of_alist_or_error~comparatoraletof_alist_exna=Using_comparator.of_alist_exn~comparatoraletof_alist_multia=Using_comparator.of_alist_multi~comparatoraletof_alist_folda~init~f=Using_comparator.of_alist_fold~comparatora~init~fletof_alist_reducea~f=Using_comparator.of_alist_reduce~comparatora~fletof_sorted_array_uncheckeda=Using_comparator.of_sorted_array_unchecked~comparatora;;letof_sorted_arraya=Using_comparator.of_sorted_array~comparatoraletof_iteri~iteri=Using_comparator.of_iteri~iteri~comparatorletof_increasing_iterator_unchecked~len~f=Using_comparator.of_increasing_iterator_unchecked~len~f~comparator;;letof_increasing_sequenceseq=Using_comparator.of_increasing_sequence~comparatorseq;;letof_sequences=Using_comparator.of_sequence~comparatorsletof_sequence_or_errors=Using_comparator.of_sequence_or_error~comparatorsletof_sequence_exns=Using_comparator.of_sequence_exn~comparatorsletof_sequence_multis=Using_comparator.of_sequence_multi~comparatorsletof_sequence_folds~init~f=Using_comparator.of_sequence_fold~comparators~init~f;;letof_sequence_reduces~f=Using_comparator.of_sequence_reduce~comparators~fend