12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976# 1 "W.cppo.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)openSignatures# 1 "ConcreteView.macros"(* In the concrete view, to deconstruct a tree [t], one matches the tree [t]
directly against the patterns [TLeaf] and [TNode _]. This requires the
concrete definition of the type [tree] to be visible. *)(* In the map variant, a pair must be constructed. This is rather painful,
as it cannot be done in a pattern, on the left-hand side of the arrow;
it must be done in an expression, on the right-hand side of the arrow.
This forces the macro [NODE] to include the arrow itself. *)# 1 "Derived.macros"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Derived macros. *)(* [EMPTY(t)] determines whether the tree [t] is empty, that is, a leaf. *)# 19 "Derived.macros"(* [BOTH_EMPTY(l,r)] determines whether the trees [l] and [r] are both empty. *)# 19 "W.cppo.ml"moduleSet=structmoduletypeOrderedType=OrderedTypemoduletypeS=SETmodule[@inline]Make(E:OrderedType)=structincludeWeightSet# 1 "UpperLayer.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Types. *)(* A key is a value of the ordered type [E.t]. *)(* In the set variant, a set element and a key are the same thing.
In the map variant, a map element is a binding, that is, a key-data pair.
Therefore, a key is just the first component of a map element. *)(* The following types exist in both variants:
+ [key] is the type of a key;
+ [DATA] is the type of a datum;
+ [ELT] is the type of an element;
+ [TREE] is the type of a tree.
[DATA], [ELT], and [TREE] may contain a wildcard, so they can be used only
in type annotations (as opposed to type definitions, signatures, etc.).
The following macros exist in both variants:
+ [EXTRA(x)] expands to nothing in the set variant
and to [x] in the map variant;
+ [GET_KEY(v)] extracts the key component of the element [v];
+ [GET_DATA(v)] extracts the data component of the element [v];
*)typekey=E.t# 48 "UpperLayer.frag.ml"typeelt=keytypeset=elttreetypet=set# 74 "UpperLayer.frag.ml"(* The total order on elements. *)let[@inline]compare_elts(x:# 76 "UpperLayer.frag.ml"elt# 76 "UpperLayer.frag.ml")(y:# 76 "UpperLayer.frag.ml"elt# 76 "UpperLayer.frag.ml"):int=E.compare(# 77 "UpperLayer.frag.ml"(x)# 77 "UpperLayer.frag.ml")(# 77 "UpperLayer.frag.ml"(y)# 77 "UpperLayer.frag.ml")(* The following macro is used by [union] and [inter] on maps.
We could also make it a function and mark it [@inline]. *)# 85 "UpperLayer.frag.ml"(* The following macros abstract away the distinction between
[if] on a Boolean value and [match] on an option. *)# 96 "UpperLayer.frag.ml"(* The following macro applies the function [f] directly to [v] in the set
variant and separately to the two components of the pair [v] in the map
variant. *)# 108 "UpperLayer.frag.ml"(* -------------------------------------------------------------------------- *)(* Operations. *)# 1 "Empty.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letempty:# 13 "Empty.frag.ml"elttree# 13 "Empty.frag.ml"=leafletis_empty(t:# 16 "Empty.frag.ml"elttree# 16 "Empty.frag.ml"):bool=match# 17 "Empty.frag.ml"(t)# 17 "Empty.frag.ml"with|# 18 "Empty.frag.ml"TLeaf# 18 "Empty.frag.ml"->true|# 20 "Empty.frag.ml"TNode{l=_;v=_;r=_;_}-># 21 "Empty.frag.ml"false# 1 "MinMax.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letrecmin_elt_1(default:# 13 "MinMax.frag.ml"elt# 13 "MinMax.frag.ml")(t:# 13 "MinMax.frag.ml"elttree# 13 "MinMax.frag.ml"):# 13 "MinMax.frag.ml"elt# 13 "MinMax.frag.ml"=match# 14 "MinMax.frag.ml"(t)# 14 "MinMax.frag.ml"with|# 15 "MinMax.frag.ml"TLeaf# 15 "MinMax.frag.ml"->default|# 17 "MinMax.frag.ml"TNode{l=l;v=v;r=_;_}-># 18 "MinMax.frag.ml"min_elt_1vlletmin_elt(t:# 20 "MinMax.frag.ml"elttree# 20 "MinMax.frag.ml"):# 20 "MinMax.frag.ml"elt# 20 "MinMax.frag.ml"=match# 21 "MinMax.frag.ml"(t)# 21 "MinMax.frag.ml"with|# 22 "MinMax.frag.ml"TLeaf# 22 "MinMax.frag.ml"->raiseNot_found|# 24 "MinMax.frag.ml"TNode{l=l;v=v;r=_;_}-># 25 "MinMax.frag.ml"min_elt_1vlletrecmin_elt_opt_1(default:# 27 "MinMax.frag.ml"elt# 27 "MinMax.frag.ml")(t:# 27 "MinMax.frag.ml"elttree# 27 "MinMax.frag.ml"):# 27 "MinMax.frag.ml"elt# 27 "MinMax.frag.ml"option=match# 28 "MinMax.frag.ml"(t)# 28 "MinMax.frag.ml"with|# 29 "MinMax.frag.ml"TLeaf# 29 "MinMax.frag.ml"->Somedefault|# 31 "MinMax.frag.ml"TNode{l=l;v=v;r=_;_}-># 32 "MinMax.frag.ml"min_elt_opt_1vlletmin_elt_opt(t:# 34 "MinMax.frag.ml"elttree# 34 "MinMax.frag.ml"):# 34 "MinMax.frag.ml"elt# 34 "MinMax.frag.ml"option=match# 35 "MinMax.frag.ml"(t)# 35 "MinMax.frag.ml"with|# 36 "MinMax.frag.ml"TLeaf# 36 "MinMax.frag.ml"->None|# 38 "MinMax.frag.ml"TNode{l=l;v=v;r=_;_}-># 39 "MinMax.frag.ml"min_elt_opt_1vlletrecmax_elt_1(default:# 41 "MinMax.frag.ml"elt# 41 "MinMax.frag.ml")(t:# 41 "MinMax.frag.ml"elttree# 41 "MinMax.frag.ml"):# 41 "MinMax.frag.ml"elt# 41 "MinMax.frag.ml"=match# 42 "MinMax.frag.ml"(t)# 42 "MinMax.frag.ml"with|# 43 "MinMax.frag.ml"TLeaf# 43 "MinMax.frag.ml"->default|# 45 "MinMax.frag.ml"TNode{l=_;v=v;r=r;_}-># 46 "MinMax.frag.ml"max_elt_1vrletmax_elt(t:# 48 "MinMax.frag.ml"elttree# 48 "MinMax.frag.ml"):# 48 "MinMax.frag.ml"elt# 48 "MinMax.frag.ml"=match# 49 "MinMax.frag.ml"(t)# 49 "MinMax.frag.ml"with|# 50 "MinMax.frag.ml"TLeaf# 50 "MinMax.frag.ml"->raiseNot_found|# 52 "MinMax.frag.ml"TNode{l=_;v=v;r=r;_}-># 53 "MinMax.frag.ml"max_elt_1vrletrecmax_elt_opt_1(default:# 55 "MinMax.frag.ml"elt# 55 "MinMax.frag.ml")(t:# 55 "MinMax.frag.ml"elttree# 55 "MinMax.frag.ml"):# 55 "MinMax.frag.ml"elt# 55 "MinMax.frag.ml"option=match# 56 "MinMax.frag.ml"(t)# 56 "MinMax.frag.ml"with|# 57 "MinMax.frag.ml"TLeaf# 57 "MinMax.frag.ml"->Somedefault|# 59 "MinMax.frag.ml"TNode{l=_;v=v;r=r;_}-># 60 "MinMax.frag.ml"max_elt_opt_1vrletmax_elt_opt(t:# 62 "MinMax.frag.ml"elttree# 62 "MinMax.frag.ml"):# 62 "MinMax.frag.ml"elt# 62 "MinMax.frag.ml"option=match# 63 "MinMax.frag.ml"(t)# 63 "MinMax.frag.ml"with|# 64 "MinMax.frag.ml"TLeaf# 64 "MinMax.frag.ml"->None|# 66 "MinMax.frag.ml"TNode{l=_;v=v;r=r;_}-># 67 "MinMax.frag.ml"max_elt_opt_1vr(* In the map variant, the above operations have different names. *)# 78 "MinMax.frag.ml"(* As in OCaml's Set library, [choose] and [choose_opt] choose the minimum
element of the set. This is slow (logarithmic time), but guarantees that
[choose] respects equality: that is, if the sets [s1] and [s2] are equal
then [choose s1] and [choose s2] are equal. *)letchoose=min_eltletchoose_opt=min_elt_opt# 1 "Mem.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* The value [v] that is extracted out of the tree has type [ELT]. In the set
variant, it is an element of the set. In the map variant, it is a pair of
a key and a value. In either case, [GET_KEY(v)] is a key. *)letrecmem(x:key)(t:# 17 "Mem.frag.ml"elttree# 17 "Mem.frag.ml"):bool=match# 18 "Mem.frag.ml"(t)# 18 "Mem.frag.ml"with|# 19 "Mem.frag.ml"TLeaf# 19 "Mem.frag.ml"->false|# 21 "Mem.frag.ml"TNode{l=l;v=v;r=r;_}-># 22 "Mem.frag.ml"letc=E.comparex(# 22 "Mem.frag.ml"(v)# 22 "Mem.frag.ml")inc=0||memx(ifc<0thenlelser)# 1 "Find.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letrecfind(x:key)(t:# 13 "Find.frag.ml"elttree# 13 "Find.frag.ml"):# 13 "Find.frag.ml"elt# 13 "Find.frag.ml"=match# 14 "Find.frag.ml"(t)# 14 "Find.frag.ml"with|# 15 "Find.frag.ml"TLeaf# 15 "Find.frag.ml"->raiseNot_found|# 17 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 18 "Find.frag.ml"letc=E.comparex(# 18 "Find.frag.ml"(v)# 18 "Find.frag.ml")inifc=0then# 20 "Find.frag.ml"(v)# 21 "Find.frag.ml"elseifc<0thenfindxlelsefindxrletrecfind_opt(x:key)(t:# 26 "Find.frag.ml"elttree# 26 "Find.frag.ml"):# 26 "Find.frag.ml"elt# 26 "Find.frag.ml"option=match# 27 "Find.frag.ml"(t)# 27 "Find.frag.ml"with|# 28 "Find.frag.ml"TLeaf# 28 "Find.frag.ml"->None|# 30 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 31 "Find.frag.ml"letc=E.comparex(# 31 "Find.frag.ml"(v)# 31 "Find.frag.ml")inifc=0thenSome(# 33 "Find.frag.ml"(v)# 33 "Find.frag.ml")elseifc<0thenfind_optxlelsefind_optxr(* -------------------------------------------------------------------------- *)(* [find_first] and its variants are as in OCaml's Set library. *)(* A lot of repetitive code. *)(* It is worth noting that [find_first] is not a naive linear search.
Instead, it assumes that [f] is a monotonically increasing function
of elements to Booleans. This implies that there is at most one
position in the increasing sequence of the set elements where the
value of [f] changes, and it changes from [false] to [true]. This
position can be found in logarithmic time. *)letrecfind_first_aux(v0:# 52 "Find.frag.ml"elt# 52 "Find.frag.ml")(f:key->bool)(t:# 52 "Find.frag.ml"elttree# 52 "Find.frag.ml"):# 52 "Find.frag.ml"elt# 52 "Find.frag.ml"=match# 53 "Find.frag.ml"(t)# 53 "Find.frag.ml"with|# 54 "Find.frag.ml"TLeaf# 54 "Find.frag.ml"->v0|# 56 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 57 "Find.frag.ml"iff(# 57 "Find.frag.ml"(v)# 57 "Find.frag.ml")thenfind_first_auxvflelsefind_first_auxv0frletrecfind_first(f:key->bool)(t:# 62 "Find.frag.ml"elttree# 62 "Find.frag.ml"):# 62 "Find.frag.ml"elt# 62 "Find.frag.ml"=match# 63 "Find.frag.ml"(t)# 63 "Find.frag.ml"with|# 64 "Find.frag.ml"TLeaf# 64 "Find.frag.ml"->raiseNot_found|# 66 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 67 "Find.frag.ml"iff(# 67 "Find.frag.ml"(v)# 67 "Find.frag.ml")thenfind_first_auxvflelsefind_firstfrletrecfind_first_opt_aux(v0:# 72 "Find.frag.ml"elt# 72 "Find.frag.ml")(f:key->bool)(t:# 72 "Find.frag.ml"elttree# 72 "Find.frag.ml"):# 72 "Find.frag.ml"elt# 72 "Find.frag.ml"option=match# 73 "Find.frag.ml"(t)# 73 "Find.frag.ml"with|# 74 "Find.frag.ml"TLeaf# 74 "Find.frag.ml"->Somev0|# 76 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 77 "Find.frag.ml"iff(# 77 "Find.frag.ml"(v)# 77 "Find.frag.ml")thenfind_first_opt_auxvflelsefind_first_opt_auxv0frletrecfind_first_opt(f:key->bool)(t:# 82 "Find.frag.ml"elttree# 82 "Find.frag.ml"):# 82 "Find.frag.ml"elt# 82 "Find.frag.ml"option=match# 83 "Find.frag.ml"(t)# 83 "Find.frag.ml"with|# 84 "Find.frag.ml"TLeaf# 84 "Find.frag.ml"->None|# 86 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 87 "Find.frag.ml"iff(# 87 "Find.frag.ml"(v)# 87 "Find.frag.ml")thenfind_first_opt_auxvflelsefind_first_optfrletrecfind_last_aux(v0:# 92 "Find.frag.ml"elt# 92 "Find.frag.ml")(f:key->bool)(t:# 92 "Find.frag.ml"elttree# 92 "Find.frag.ml"):# 92 "Find.frag.ml"elt# 92 "Find.frag.ml"=match# 93 "Find.frag.ml"(t)# 93 "Find.frag.ml"with|# 94 "Find.frag.ml"TLeaf# 94 "Find.frag.ml"->v0|# 96 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 97 "Find.frag.ml"iff(# 97 "Find.frag.ml"(v)# 97 "Find.frag.ml")thenfind_last_auxvfrelsefind_last_auxv0flletrecfind_last(f:key->bool)(t:# 102 "Find.frag.ml"elttree# 102 "Find.frag.ml"):# 102 "Find.frag.ml"elt# 102 "Find.frag.ml"=match# 103 "Find.frag.ml"(t)# 103 "Find.frag.ml"with|# 104 "Find.frag.ml"TLeaf# 104 "Find.frag.ml"->raiseNot_found|# 106 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 107 "Find.frag.ml"iff(# 107 "Find.frag.ml"(v)# 107 "Find.frag.ml")thenfind_last_auxvfrelsefind_lastflletrecfind_last_opt_aux(v0:# 112 "Find.frag.ml"elt# 112 "Find.frag.ml")(f:key->bool)(t:# 112 "Find.frag.ml"elttree# 112 "Find.frag.ml"):# 112 "Find.frag.ml"elt# 112 "Find.frag.ml"option=match# 113 "Find.frag.ml"(t)# 113 "Find.frag.ml"with|# 114 "Find.frag.ml"TLeaf# 114 "Find.frag.ml"->Somev0|# 116 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 117 "Find.frag.ml"iff(# 117 "Find.frag.ml"(v)# 117 "Find.frag.ml")thenfind_last_opt_auxvfrelsefind_last_opt_auxv0flletrecfind_last_opt(f:key->bool)(t:# 122 "Find.frag.ml"elttree# 122 "Find.frag.ml"):# 122 "Find.frag.ml"elt# 122 "Find.frag.ml"option=match# 123 "Find.frag.ml"(t)# 123 "Find.frag.ml"with|# 124 "Find.frag.ml"TLeaf# 124 "Find.frag.ml"->None|# 126 "Find.frag.ml"TNode{l=l;v=v;r=r;_}-># 127 "Find.frag.ml"iff(# 127 "Find.frag.ml"(v)# 127 "Find.frag.ml")thenfind_last_opt_auxvfrelsefind_last_optfl# 1 "Add.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* This is insertion in the style of BFS. *)(* (Disabled.) (Set variant only.)
let add (k : key) (t : TREE) : TREE =
let l, _, r = split k t in
join l k r
*)# 25 "Add.frag.ml"(* This is a less elegant but more efficient version of insertion. *)(* This implementation is adapted from OCaml's Set library. *)(* If an equivalent element is already present in the set, then the
existing element is retained, so the set is unchanged. *)letrecadd(x:key)(t:# 32 "Add.frag.ml"elttree# 32 "Add.frag.ml"):# 32 "Add.frag.ml"elttree# 32 "Add.frag.ml"=match# 33 "Add.frag.ml"(t)# 33 "Add.frag.ml"with|# 34 "Add.frag.ml"TLeaf# 34 "Add.frag.ml"->singletonx|# 36 "Add.frag.ml"TNode{l=l;v=v;r=r;_}-># 37 "Add.frag.ml"letc=E.comparexvinifc=0then(* Retain the existing element: *)telseifc<0thenletl'=addxlinifl==l'thentelsejoin_quasi_siblingsl'vrelseletr'=addxrinifr==r'thentelsejoin_quasi_siblingslvr'(* [add_absent] is currently used by [xor]. We could optimize it,
a little, by removing one test. *)letadd_absent=add# 1 "Remove.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [remove_min_elt_1 l v r] removes the minimum element of the tree
[NODE(l, v, r)]. *)letrecremove_min_elt_1(l:# 16 "Remove.frag.ml"elttree# 16 "Remove.frag.ml")(v:# 16 "Remove.frag.ml"elt# 16 "Remove.frag.ml")(r:# 16 "Remove.frag.ml"elttree# 16 "Remove.frag.ml"):# 16 "Remove.frag.ml"elttree# 16 "Remove.frag.ml"=match# 17 "Remove.frag.ml"(l)# 17 "Remove.frag.ml"with|# 18 "Remove.frag.ml"TLeaf# 18 "Remove.frag.ml"->r|# 20 "Remove.frag.ml"TNode{l=ll;v=lv;r=lr;_}-># 21 "Remove.frag.ml"letl=remove_min_elt_1lllvlrinjoin_quasi_siblingslvr(* [remove_min_elt t] removes the minimum element of the tree [t]. *)letremove_min_elt(t:# 26 "Remove.frag.ml"elttree# 26 "Remove.frag.ml"):# 26 "Remove.frag.ml"elttree# 26 "Remove.frag.ml"=match# 27 "Remove.frag.ml"(t)# 27 "Remove.frag.ml"with|# 28 "Remove.frag.ml"TLeaf# 28 "Remove.frag.ml"->raiseNot_found|# 30 "Remove.frag.ml"TNode{l=l;v=v;r=r;_}-># 31 "Remove.frag.ml"remove_min_elt_1lvr(* [remove_max_elt_1 l v r] removes the maximum element of the tree
[NODE(l, v, r)]. *)letrecremove_max_elt_1(l:# 36 "Remove.frag.ml"elttree# 36 "Remove.frag.ml")(v:# 36 "Remove.frag.ml"elt# 36 "Remove.frag.ml")(r:# 36 "Remove.frag.ml"elttree# 36 "Remove.frag.ml"):# 36 "Remove.frag.ml"elttree# 36 "Remove.frag.ml"=match# 37 "Remove.frag.ml"(r)# 37 "Remove.frag.ml"with|# 38 "Remove.frag.ml"TLeaf# 38 "Remove.frag.ml"->l|# 40 "Remove.frag.ml"TNode{l=rl;v=rv;r=rr;_}-># 41 "Remove.frag.ml"letr=remove_max_elt_1rlrvrrinjoin_quasi_siblingslvr(* [remove_max_elt t] removes the maximum element of the tree [t]. *)letremove_max_elt(t:# 46 "Remove.frag.ml"elttree# 46 "Remove.frag.ml"):# 46 "Remove.frag.ml"elttree# 46 "Remove.frag.ml"=match# 47 "Remove.frag.ml"(t)# 47 "Remove.frag.ml"with|# 48 "Remove.frag.ml"TLeaf# 48 "Remove.frag.ml"->raiseNot_found|# 50 "Remove.frag.ml"TNode{l=l;v=v;r=r;_}-># 51 "Remove.frag.ml"remove_max_elt_1lvr(* In the map variant, the above operations have different names. *)# 60 "Remove.frag.ml"(* [join2_siblings l r] is analogous to [join2 l r], but requires the
subtrees [l] and [r] to be siblings. *)(* [join2_siblings] is named [merge] in OCaml's Set library. *)(* This implementation arbitrarily chooses to place the minimum element of the
tree [r] at the root. One could also choose to place the maximum element of
the tree [l] at the root. One could imagine choosing between these
alternatives, based on the weights or heights of the trees [l] and [r], if
such a notion exists. That would remove the need for rebalancing. However,
this seems to make essentially no difference in practice. *)letjoin2_siblings(l:# 72 "Remove.frag.ml"elttree# 72 "Remove.frag.ml")(r:# 72 "Remove.frag.ml"elttree# 72 "Remove.frag.ml"):# 72 "Remove.frag.ml"elttree# 72 "Remove.frag.ml"=assert(siblingslr);match# 74 "Remove.frag.ml"(l)# 74 "Remove.frag.ml",# 74 "Remove.frag.ml"(r)# 74 "Remove.frag.ml"with|_,# 75 "Remove.frag.ml"TLeaf# 75 "Remove.frag.ml"->l|# 77 "Remove.frag.ml"TLeaf# 77 "Remove.frag.ml",_->r|_,# 79 "Remove.frag.ml"TNode{l=rl;v=rv;r=rr;_}-># 80 "Remove.frag.ml"join_quasi_siblingsl(min_elt_1rvrl)(* same as [min_elt r] *)(remove_min_elt_1rlrvrr)(* same as [remove_min_elt r] *)(* This is removal in the style of BFS. *)(* (Disabled.) (Set variant only.)
let remove (k : key) (t : TREE) : TREE =
let l, _, r = split k t in
join2 l r
*)(* This is a less elegant but more efficient version of removal. *)(* This implementation is taken from OCaml's Set library. *)letrecremove(x:key)(t:# 99 "Remove.frag.ml"elttree# 99 "Remove.frag.ml"):# 99 "Remove.frag.ml"elttree# 99 "Remove.frag.ml"=match# 100 "Remove.frag.ml"(t)# 100 "Remove.frag.ml"with|# 101 "Remove.frag.ml"TLeaf# 101 "Remove.frag.ml"->empty|# 103 "Remove.frag.ml"TNode{l=l;v=v;r=r;_}-># 104 "Remove.frag.ml"letc=E.comparex(# 104 "Remove.frag.ml"(v)# 104 "Remove.frag.ml")inifc=0thenjoin2_siblingslrelseifc<0thenletl'=removexlinifl==l'thentelsejoin_quasi_siblingsl'vrelseletr'=removexrinifr==r'thentelsejoin_quasi_siblingslvr'# 1 "Split.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [split] is implemented in the same way in OCaml's Set library and by BFS. *)(* We use the same code, but add a physical equality test that allows us to
preserve sharing (and avoid memory allocation) in some cases. *)(* In the set variant, the second component of the result has type [bool].
In the map variant, it has type [DATA option]. *)# 33 "Split.frag.ml"letrecsplit(k:key)(t:# 33 "Split.frag.ml"elttree# 33 "Split.frag.ml"):# 33 "Split.frag.ml"elttree# 33 "Split.frag.ml"*# 33 "Split.frag.ml"bool# 33 "Split.frag.ml"*# 33 "Split.frag.ml"elttree# 33 "Split.frag.ml"=match# 34 "Split.frag.ml"(t)# 34 "Split.frag.ml"with|# 35 "Split.frag.ml"TLeaf# 35 "Split.frag.ml"->leaf,# 36 "Split.frag.ml"false# 36 "Split.frag.ml",leaf|# 37 "Split.frag.ml"TNode{l=l;v=v;r=r;_}-># 38 "Split.frag.ml"letc=E.comparek(# 38 "Split.frag.ml"(v)# 38 "Split.frag.ml")inifc=0thenl,# 40 "Split.frag.ml"true# 40 "Split.frag.ml",relseifc<0thenletll,b,lr=splitklinll,b,(iflr==lthentelsejoinlrvr)elseletrl,b,rr=splitkrin(ifrl==rthentelsejoinlvrl),b,rr# 52 "Split.frag.ml"(* A specialized version of [split] that returns just the Boolean component
of the result is [mem]. *)(* [split13] is a variant of [split] that returns only the first and third
components of the result. *)letrecsplit13(k:key)(t:'atree):'atree*'atree=match# 59 "Split.frag.ml"(t)# 59 "Split.frag.ml"with|# 60 "Split.frag.ml"TLeaf# 60 "Split.frag.ml"->leaf,leaf|# 62 "Split.frag.ml"TNode{l=l;v=v;r=r;_}-># 63 "Split.frag.ml"letc=E.comparekvinifc=0thenl,relseifc<0thenletll,lr=split13klinll,(iflr==lthentelsejoinlrvr)elseletrl,rr=split13krin(ifrl==rthentelsejoinlvrl),rr# 1 "Join.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [join2 l r] requires [l < r]. It joins the trees [l] and [r]
into a single tree. *)(* [join2] is known as [concat] in OCaml's Set library. *)(* This is the code proposed by BFS. Their [split_last] function
corresponds to our functions [min_elt] and [remove_min_elt_1].
(Set variant only.)
let rec split_last (l : TREE) (k : key) (r : TREE) : TREE * key =
match VIEW(r) with
| LEAF ->
l, k
| NODE(l', k', r')
let r, m = split_last l' k' r' in
join l k r, m
let join2 (l : TREE) (r : TREE) : TREE =
match VIEW(l) with
| LEAF ->
r
| NODE(ll, m, lr)
let l', k = split_last ll m lr in
join l' k r
*)(* [join2 l r] is implemented by extracting the maximum element of [l]
or the minimum element of [r] and letting [join] do the rest of the
work. *)(* In order to maintain a better balance, one might wish to extract an
element from the tree that seems larger. However, this seems to
bring no improvement in practice, so we avoid this complication. *)letjoin2(l:# 48 "Join.frag.ml"elttree# 48 "Join.frag.ml")(r:# 48 "Join.frag.ml"elttree# 48 "Join.frag.ml"):# 48 "Join.frag.ml"elttree# 48 "Join.frag.ml"=match# 49 "Join.frag.ml"(l)# 49 "Join.frag.ml",# 49 "Join.frag.ml"(r)# 49 "Join.frag.ml"with|# 50 "Join.frag.ml"TLeaf# 50 "Join.frag.ml",_->r|_,# 52 "Join.frag.ml"TLeaf# 52 "Join.frag.ml"->l|_,# 54 "Join.frag.ml"TNode{l=rl;v=rv;r=rr;_}-># 55 "Join.frag.ml"joinl(min_elt_1rvrl)(* same as [min_elt r] *)(remove_min_elt_1rlrvrr)(* same as [remove_min_elt r] *)(* -------------------------------------------------------------------------- *)# 1 "Enum.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Enumerations. *)moduleEnum=struct(* An enumeration can be viewed as a list of pairs of an element and
a (sub)tree. It is sorted in increasing order of keys. *)(* There is no structural difference between the set variant and the
map variant. In the map variant, we do not flatten the key-data
pair into the constructor [More], as this seems unlikely to lead
to a gain in performance. *)(* In both variants, the type [ienum] is parameterized with ['v].
This type is internal (not public). *)type'vienum=|End|Moreof'v*'vtree*'vienum(* The public type [enum] is unparameterized in the set variant and
parameterized with ['a] in the map variant. *)# 36 "Enum.frag.ml"typeenum=eltienumtypet=enum# 43 "Enum.frag.ml"letempty:'vienum=Endlet[@inline]is_empty(e:'vienum):bool=matchewith|End->true|More_->false(* [cat_tree_enum t e] concatenates the tree [t] in front of the
enumeration [e]. *)(* This function is named [cons_enum] in OCaml's Set library. *)letreccat_tree_enum(t:'vtree)(e:'vienum):'vienum=match# 57 "Enum.frag.ml"(t)# 57 "Enum.frag.ml"with|# 58 "Enum.frag.ml"TLeaf# 58 "Enum.frag.ml"->e|# 60 "Enum.frag.ml"TNode{l=l;v=v;r=r;_}-># 61 "Enum.frag.ml"cat_tree_enuml(More(v,r,e))(* [enum] converts a tree to an enumeration. *)let[@inline]enum(t:'vtree):'vienum=cat_tree_enumtempty(* [filter_tree low t e] constructs an enumeration whose elements are: 1-
the elements [x] of the tree [t] such that [low <= x] holds, followed
with 2- all elements of the enumeration [e]. *)(* In [filter_tree low t e], only the tree [t] is filtered by the constraint
[low <= x]. The enumeration [e] is not filtered (typically because it is
already known that all of its elements satisfy this constraint). This is
in contrast with [filter_tree_enum low t e] (below), where both [t] and
[e] are filtered. *)letrecfilter_tree(low:key)(t:'vtree)(e:'vienum):'vienum=match# 79 "Enum.frag.ml"(t)# 79 "Enum.frag.ml"with|# 80 "Enum.frag.ml"TLeaf# 80 "Enum.frag.ml"->e|# 82 "Enum.frag.ml"TNode{l=l;v=v;r=r;_}-># 83 "Enum.frag.ml"letc=E.compare(# 83 "Enum.frag.ml"(v)# 83 "Enum.frag.ml")lowinifc=0thenMore(v,r,e)elseifc<0thenfilter_treelowreelsefilter_treelowl(More(v,r,e))let[@inline]from_enum(low:key)(t:'vtree):'vienum=filter_treelowtempty(* [filter_tree_enum low r e] extracts the elements [x] that satisfy the
constraint [low <= x] out of the sequence of the elements of the tree [r]
and of the enumeration [e]. *)(* Thus, it is equivalent to [from low (cat_tree_enum r e)],
but the function [from] has not been defined yet.
[filter_tree_enum] is in fact used to define [from]. *)(* Both the tree [r] and the enumeration [e] are filtered. *)letrecfilter_tree_enum(low:key)(r:'vtree)(e:'vienum):'vienum=(* Peek past [r] at the first element [v'] of [e], if there is one. *)matchewith|More(v',r',e')->letc=E.comparelow(# 108 "Enum.frag.ml"(v')# 108 "Enum.frag.ml")inifc>0then(* [v'] is below the threshold.
The subtree [r] and the value [v'] must be discarded.
Continue with [r'] and [e']. *)filter_tree_enumlowr'e'elseifc=0then(* [v'] is at the threshold.
The subtree [r] must be discarded. [e] must be kept. *)eelse(* c < 0 *)(* [v'] is above the threshold. *)(* No part of [e] must be discarded. *)(* Keep part of [r], followed with [e]. *)filter_treelowre|End->(* [e] is empty. Keep part of [r]. *)filter_treelowre(* [from low e] extracts from the enumeration [e]
the elements that lie at or above the threshold [low] . *)(* One could define [from low e] as [filter_tree_enum low leaf e].
However, the following code is slightly more efficient. *)letfrom(low:key)(e:'vienum):'vienum=matchewith|More(v,r,e')->ifE.comparelow(# 136 "Enum.frag.ml"(v)# 136 "Enum.frag.ml")<=0then(* [v] is at or above the threshold. Keep all elements. *)eelse(* [v] is below the threshold. [v] must be discarded. *)filter_tree_enumlowre'|End->Endlethead(e:'vienum):# 145 "Enum.frag.ml"elt# 145 "Enum.frag.ml"=matchewith|End->raiseNot_found|More(v,_,_)->vlettail(e:'vienum):'vienum=matchewith|End->raiseNot_found|More(_,r,e)->cat_tree_enumrelethead_opt(e:'vienum):# 155 "Enum.frag.ml"elt# 155 "Enum.frag.ml"option=matchewith|End->None|More(v,_,_)->Somevlettail_opt(e:'vienum):'vienumoption=matchewith|End->None|More(_,r,e)->Some(cat_tree_enumre)(* [equal e1 e2] compares the enumerations [e1] and [e2]. *)(* In the map variant, [equal] takes an extra argument, [eq], which is used
to compare the data components of two values. In the set variant, this
argument is absent; there are no data components, and one can think of
[eq] as the constant function [true]. *)letrecequal# 172 "Enum.frag.ml"# 172 "Enum.frag.ml"(e1:_ienum)(e2:_ienum):bool=matche1,e2with|End,End->true|End,More_|More_,End->false|More(v1,r1,e1),More(v2,r2,e2)->compare_eltsv1v2=0&&# 184 "Enum.frag.ml"equal# 184 "Enum.frag.ml"# 184 "Enum.frag.ml"(cat_tree_enumr1e1)(cat_tree_enumr2e2)(* [compare e1 e2] compares the enumerations [e1] and [e2] according to a
lexicographic ordering. *)(* In the map variant, [compare] takes an extra argument, [cmp], which is
used to compare the data components of two values. In the set variant,
this argument is absent; there are no data components, and one can think
of [cmp] as the constant function [0]. *)letreccompare# 194 "Enum.frag.ml"# 194 "Enum.frag.ml"(e1:_ienum)(e2:_ienum):int=matche1,e2with|End,End->0|End,More_->-1|More_,End->1|More(v1,r1,e1),More(v2,r2,e2)->letc=compare_eltsv1v2inifc<>0thencelse# 209 "Enum.frag.ml"compare# 209 "Enum.frag.ml"# 209 "Enum.frag.ml"(cat_tree_enumr1e1)(cat_tree_enumr2e2)(* [to_seq] converts an enumeration to an OCaml sequence. *)letrecto_seq_node(e:'vienum):# 213 "Enum.frag.ml"elt# 213 "Enum.frag.ml"Seq.node=matchewith|End->Seq.Nil|More(v,r,e)->Seq.Cons(v,fun()->to_seq_node(cat_tree_enumre))letto_seq(e:'vienum):# 220 "Enum.frag.ml"elt# 220 "Enum.frag.ml"Seq.t=fun()->to_seq_nodee(* [elements] converts an enumeration back to a tree. *)(* It is the only function in this file that constructs a tree.
It exploits the construction function [join].
It performs no key comparisons. *)(* I believe, but have not proved, that, thanks to the remarkable
properties of [join], the time complexity of [elements] is only
O(log n). *)letrecelements(v:# 233 "Enum.frag.ml"elt# 233 "Enum.frag.ml")(r:'vtree)(e:'vienum):'vtree=matchewith|End->joinleafvr|More(v',r',e)->elementsv(joinrv'r')eletelements(e:'vienum):'vtree=matchewith|End->leaf|More(v,r,e)->elementsvre(* Disjointness. *)exceptionNotDisjoint(* [filter_tree_disjoint low t e] returns the same result as
[filter_tree low t e], except that it raises [NotDisjoint]
if the key [low] appears in its result. *)letrecfilter_tree_disjoint(low:key)(t:'vtree)(e:'vienum):'vienum=match# 256 "Enum.frag.ml"(t)# 256 "Enum.frag.ml"with|# 257 "Enum.frag.ml"TLeaf# 257 "Enum.frag.ml"->e|# 259 "Enum.frag.ml"TNode{l=l;v=v;r=r;_}-># 260 "Enum.frag.ml"letc=E.compare(# 260 "Enum.frag.ml"(v)# 260 "Enum.frag.ml")lowinifc=0thenraiseNotDisjointelseifc<0thenfilter_tree_disjointlowreelsefilter_tree_disjointlowl(More(v,r,e))(* [filter_tree_enum_disjoint low r e] returns the same result as
[filter_tree_enum low r e], except that it raises [NotDisjoint]
if the key [low] appears in its result. *)letrecfilter_tree_enum_disjoint(low:key)(r:'vtree)(e:'vienum):'vienum=matchewith|More(v',r',e')->letc=E.comparelow(# 275 "Enum.frag.ml"(v')# 275 "Enum.frag.ml")inifc>0thenfilter_tree_enum_disjointlowr'e'elseifc=0thenraiseNotDisjointelsefilter_tree_disjointlowre|End->filter_tree_disjointlowre(* [disjoint_more_more v1 r1 e1 v2 r2 e2] requires [v1 < v2]. It determines
whether the enumerations [More (v1, r1, e1)] and [More (v2, r2, e2)] are
disjoint. It either returns [true] or raises [NotDisjoint]. *)(* This is Veldhuizen's leapfrog join algorithm. *)(* In the map variant, a type annotation is required, because this function
is polymorphic recursive. Indeed, the final recursive call exchanges the
two sides. *)letrecdisjoint_more_more# 302 "Enum.frag.ml"=funv1r1e1v2r2e2->assert(compare_eltsv1v2<0);(* Skip past [v2] in the enumeration [e1]. *)(* If [v2] appears in [e1], fail. *)lete1=filter_tree_enum_disjoint(# 306 "Enum.frag.ml"(v2)# 306 "Enum.frag.ml")r1e1inmatche1with|End->(* If [e1] is now empty, we are done. *)true|More(v1,r1,e1)->(* If [e1] is nonempty, then its front value [v1] must be greater than
[v2]. Exchange the roles of the two enumerations and continue. *)assert(compare_eltsv2v1<0);disjoint_more_morev2r2e2v1r1e1(* [disjoint e1 e2] determines whether the enumerations [e1] and [e2] are
disjoint. *)letdisjoint(e1:_ienum)(e2:_ienum):bool=matche1,e2with|End,_|_,End->true|More(v1,r1,e1),More(v2,r2,e2)->letc=compare_eltsv1v2inifc=0thenfalseelsetryifc<0thendisjoint_more_morev1r1e1v2r2e2elsedisjoint_more_morev2r2e2v1r1e1withNotDisjoint->false(* [length e] computes the length of the enumeration [e]. If we have
a constant-time [cardinal] function on sets, then its complexity
is logarithmic. Otherwise, its complexity is linear. *)letreclength_auxaccu(e:'vienum):int=matchewith|End->accu|More(_,r,e)->length_aux(accu+cardinalr+1)elet[@inline]length(e:'vienum):int=length_aux0eend(* Enum *)(* -------------------------------------------------------------------------- *)(* Enumerations in reverse (decreasing order). *)(* I would rather avoid this code duplication, but we must provide at least
[to_rev_seq], for compatibility with OCaml's Set library. *)moduleRevEnum=struct(* In the enumeration [More (e, l, v)], we have [e < l < v], but the
enumeration is consumed (by the user) from the right to the left,
so [v] is produced first, followed with the elements of the tree
[l], followed with the elements of the enumeration [e]. *)type'vienum=|End|Moreof'vienum*'vtree*'vletempty:'vienum=End(* [cat_enum_tree e t] concatenates the enumeration [e] in front of
the tree [t]. It requires [e < t]. *)(* This function corresponds to [snoc_enum] in OCaml's Set library. *)letreccat_enum_tree(e:'vienum)(t:'vtree):'vienum=match# 381 "Enum.frag.ml"(t)# 381 "Enum.frag.ml"with|# 382 "Enum.frag.ml"TLeaf# 382 "Enum.frag.ml"->e|# 384 "Enum.frag.ml"TNode{l=l;v=v;r=r;_}-># 385 "Enum.frag.ml"cat_enum_tree(More(e,l,v))r(* [enum] converts a tree to an enumeration. *)let[@inline]enum(t:'vtree):'vienum=cat_enum_treeemptyt(* [to_seq] converts an enumeration to an OCaml sequence. *)letrecto_seq_node(e:'vienum):# 394 "Enum.frag.ml"elt# 394 "Enum.frag.ml"Seq.node=matchewith|End->Seq.Nil|More(e,l,v)->Seq.Cons(v,fun()->to_seq_node(cat_enum_treeel))(* let to_seq (e : enum) : key Seq.t = *)(* fun () -> to_seq_node e *)end# 1 "Compare.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Comparison. *)(* Instead of using enumerations of the trees [t1] and [t2], one could perform
a recursive traversal of [t1], while consuming an enumeration of [t2]. I
have benchmarked this variant: it allocates less memory, and can be faster,
but can also be about twice slower. *)letcompare# 22 "Compare.frag.ml"# 22 "Compare.frag.ml"(t1:# 22 "Compare.frag.ml"elttree# 22 "Compare.frag.ml")(t2:# 22 "Compare.frag.ml"elttree# 22 "Compare.frag.ml"):int=# 24 "Compare.frag.ml"ift1==t2then0else(* fast path *)# 26 "Compare.frag.ml"Enum.(compare# 26 "Compare.frag.ml"# 26 "Compare.frag.ml"(enumt1)(enumt2))# 1 "Equal.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Equality. *)(* Equality of sets can be implemented in several ways. E.g., [equal t1 t2]
could be implemented in one line by [subset t1 t2 && subset t2 t1] or also
in one line by [is_empty (xor t1 t2)]. (The latter idea could be optimized,
so as to avoid actually constructing the tree [xor t1 t2] in memory.) Some
experiments suggest that either of these approaches is more expensive than
the following approach, which compares two enumerations. Furthermore, this
approach works for both sets and maps. *)(* In weight-balanced trees, the weight of a tree can be determined in
constant time. This yields a fast path: if the weights and [t1] and [t2]
differ, then they cannot possibly be equal. In height-balanced trees, the
[weight] function returns a constant value, so this fast path is
disabled. *)letequal# 31 "Equal.frag.ml"# 31 "Equal.frag.ml"t1t2=# 33 "Equal.frag.ml"t1==t2||(* fast path *)# 35 "Equal.frag.ml"weightt1=weightt2&&(* fast path *)Enum.(equal# 36 "Equal.frag.ml"# 36 "Equal.frag.ml"(enumt1)(enumt2))# 1 "Union.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Union. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 21 "Union.frag.ml"(* This is the simple, elegant version of [union] given by BFS.
let rec union (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _
| _, LEAF ->
leaf
| NODENODE(_, _, _, l2, v2, r2)
let l1, r1 = split13 v2 t1 in
let l = union l1 l2
and r = union r1 r2 in
join l v2 r
*)(* Our implementation of [union] is in the same style as [inter].
It inherits two features of OCaml's Set library:
- the tree that seems smaller is split;
- if a subtree is a singleton then [union] degenerates to [add].
Furthermore, compared with OCaml's Set library, it is able to exploit
physical equality when present, and it offers a stronger guarantee
regarding the preservation of physical equality. *)(* The recursive function [union] ensures that if the result is
equal to [t2] then the result is physically equal to [t2]. *)(* In the case where [t2] is a singleton, we have already checked that
[t1] is neither empty nor a singleton, so the result of the union
cannot possibly be equal to [t2]. Thus, the obligation to preserve
sharing disappears in this case: using [add v2 t1] is safe. *)(* We are able to use [split13] because, as soon as we know that [v2] is
present on the right-hand side, we do not care whether it is absent or
present on the left-hand side. In the map variant, however, we must use
[split] instead. *)letrecunion(t1:'vtree)(t2:'vtree):'vtree=match# 58 "Union.frag.ml"(t1)# 58 "Union.frag.ml",# 58 "Union.frag.ml"(t2)# 58 "Union.frag.ml"with|# 59 "Union.frag.ml"TLeaf# 59 "Union.frag.ml",_->t2|_,# 61 "Union.frag.ml"TLeaf# 61 "Union.frag.ml"->t1|# 63 "Union.frag.ml"TNode{l=l1;v=v1;r=r1;_},TNode{l=l2;v=v2;r=r2;_}-># 64 "Union.frag.ml"if# 64 "Union.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 64 "Union.frag.ml"thenaddv1t2elseif# 65 "Union.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 65 "Union.frag.ml"thenaddv2t1elseletl1,r1=split13v2t1inletl=unionl1l2andr=unionr1r2inletv=v2inifl==l2&&r==r2thent2else(* preserve sharing *)joinlvr(* This toplevel wrapper tests which of the two arguments seems larger. (With
weight-balanced trees, this is an exact test. With height-balanced trees,
it is a heuristic test.) This argument, one may hope, might also be the
result. Therefore, the recursive function [union] (above) is invoked with
this argument as its second argument. Compared with [inter], this is the
other way around. *)(* The fast path, based on the test [t1 == t2], is sound because [union s s]
is [s]. *)letuniont1t2=ift1==t2thent1else(* fast path *)ifseems_smallert1t2thenuniont1t2elseuniont2t1(* In the set variant, [override] is [union]. It is commutative. *)letoverride=union# 1 "Inter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Intersection. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 21 "Inter.frag.ml"(* This is the simple, elegant version of [inter] given by BFS.
let rec inter (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _
| _, LEAF ->
leaf
| NODENODE(_, _, _, l2, k2, r2)
let l1, b, r1 = split k2 t1 in
let l = inter l1 l2
and r = inter r1 r2 in
if b then join l k2 r else join2 l r
*)(* The recursive function [inter] ensures that if the result is
equal to [t2] then the result is physically equal to [t2]. *)(* Compared with the simple version (above),
+ there is a fast path for the case where [t1 == t2] holds;
+ there is specialized code for the case where [t2] is a
singleton; in that case there is no need to use [split];
+ the code guarantees that if the result is equal to [t2]
then [t2] itself is returned. *)(* Adding specialized code for the case where [t1] is a singleton can lead
to small gains or losses in speed; the effect seems unclear. *)(* Adding specialized code for the cases where one of [l2] or [r2] is empty
saves a few percent in time, and is not worth the extra complexity. *)letrecinter(t1:# 53 "Inter.frag.ml"elttree# 53 "Inter.frag.ml")(t2:# 53 "Inter.frag.ml"elttree# 53 "Inter.frag.ml"):# 53 "Inter.frag.ml"elttree# 53 "Inter.frag.ml"=match# 54 "Inter.frag.ml"(t1)# 54 "Inter.frag.ml",# 54 "Inter.frag.ml"(t2)# 54 "Inter.frag.ml"with|# 55 "Inter.frag.ml"TLeaf# 55 "Inter.frag.ml",_|_,# 56 "Inter.frag.ml"TLeaf# 56 "Inter.frag.ml"->leaf|# 58 "Inter.frag.ml"TNode{l=_;v=_;r=_;_},TNode{l=l2;v=k2;r=r2;_}-># 59 "Inter.frag.ml"ift1==t2thent2else(* fast path *)if# 60 "Inter.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 60 "Inter.frag.ml"then(* The tree [t2] is [singleton k2]. *)ifmemk2t1thent2elseleafelseletl1,b,r1=splitk2t1inletl=interl1l2andr=interr1r2inifbthenifl==l2&&r==r2thent2else(* preserve sharing *)joinlk2relsejoin2lr(* This toplevel wrapper serves two purposes. First, it contains a fast path
for the case where [t1 == t2] holds. Second, it tests which of the two
arguments seems smaller. (With weight-balanced trees, this is an exact
test. With height-balanced trees, it is a heuristic test.) This argument,
one may hope, might also be the result. Therefore, the recursive function
[inter] (above) is invoked with this argument as its second argument. *)letintert1t2=ift1==t2thent1else(* fast path *)ifseems_smallert1t2thenintert2t1elseintert1t2# 1 "Diff.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Difference. *)(* This is a simple, elegant version of [diff]. This version splits the
tree [t1]. (Set variant only.)
let rec diff (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _ ->
leaf
| _, LEAF ->
t1
| NODENODE(_, _, _, l2, k2, r2)
let l1, r1 = split13 k2 t1 in
let l = diff l1 l2
and r = diff r1 r2 in
join2 l r
*)(* This version of [diff] guarantees that if the result is equal to [t1]
then [t1] itself is returned. It splits the tree [t2]. *)letrecdiff(t1:# 37 "Diff.frag.ml"elttree# 37 "Diff.frag.ml")(t2:# 37 "Diff.frag.ml"elttree# 37 "Diff.frag.ml"):# 37 "Diff.frag.ml"elttree# 37 "Diff.frag.ml"=match# 38 "Diff.frag.ml"(t1)# 38 "Diff.frag.ml",# 38 "Diff.frag.ml"(t2)# 38 "Diff.frag.ml"with|# 39 "Diff.frag.ml"TLeaf# 39 "Diff.frag.ml",_->leaf|_,# 41 "Diff.frag.ml"TLeaf# 41 "Diff.frag.ml"->t1|# 43 "Diff.frag.ml"TNode{l=l1;v=v1;r=r1;_},TNode{l=l2;v=v2;r=r2;_}-># 44 "Diff.frag.ml"letk1=# 44 "Diff.frag.ml"(v1)# 44 "Diff.frag.ml"in# 46 "Diff.frag.ml"ift1==t2thenleafelse(* fast path *)# 48 "Diff.frag.ml"if# 48 "Diff.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 48 "Diff.frag.ml"then(* [t1] is [singleton v1]. *)ifmemk1t2thenleafelset1elseif# 51 "Diff.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 51 "Diff.frag.ml"then(* [t2] is [singleton v2]. *)letk2=# 53 "Diff.frag.ml"(v2)# 53 "Diff.frag.ml"inremovek2t1elseletl2,b,r2=splitk1t2inletl=diffl1l2andr=diffr1r2in# 59 "Diff.frag.ml"ifbthen# 60 "Diff.frag.ml"join2lr# 61 "Diff.frag.ml"else# 62 "Diff.frag.ml"ifl==l1&&r==r1thent1else(* preserve sharing *)joinlv1r# 1 "Xor.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Symmetric difference. *)(* This is a simple, elegant version of [xor]. (Set variant only.)
let rec xor (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _ ->
t2
| _, LEAF ->
t1
| NODENODE(_, _, _, l2, k2, r2)
let l1, b, r1 = split k2 t1 in
let l = xor l1 l2
and r = xor r1 r2 in
if b then join2 l r else join l k2 r
*)(* Except in the case where [t1] or [t2] is empty, [xor t1 t2] cannot be
equal to [t1] or [t2]. So there is no need to attempt to preserve
sharing when constructing new nodes. *)letrecxor(t1:# 37 "Xor.frag.ml"elttree# 37 "Xor.frag.ml")(t2:# 37 "Xor.frag.ml"elttree# 37 "Xor.frag.ml"):# 37 "Xor.frag.ml"elttree# 37 "Xor.frag.ml"=match# 38 "Xor.frag.ml"(t1)# 38 "Xor.frag.ml",# 38 "Xor.frag.ml"(t2)# 38 "Xor.frag.ml"with|# 39 "Xor.frag.ml"TLeaf# 39 "Xor.frag.ml",_->t2|_,# 41 "Xor.frag.ml"TLeaf# 41 "Xor.frag.ml"->t1|# 43 "Xor.frag.ml"TNode{l=_;v=_;r=_;_},TNode{l=l2;v=v2;r=r2;_}-># 44 "Xor.frag.ml"ift1==t2thenleafelse(* fast path *)letk2=# 45 "Xor.frag.ml"(v2)# 45 "Xor.frag.ml"inif# 46 "Xor.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 46 "Xor.frag.ml"then(* [t2] is [singleton v2]. *)ifmemk2t1thenremovek2t1elseadd_absentv2t1elseletl1,b,r1=splitk2t1inletl=xorl1l2andr=xorr1r2in# 56 "Xor.frag.ml"ifbthen# 57 "Xor.frag.ml"join2lr# 58 "Xor.frag.ml"else# 59 "Xor.frag.ml"joinlv2r# 1 "Disjoint.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Disjointness. *)(* This simple version of [disjoint] has the same structure as [inter]. *)(* (Disabled.) (Set variant only.)
let rec disjoint (t1 : tree) (t2 : tree) : bool =
match VIEW(t1), VIEW(t2) with
| LEAF, _
| _, LEAF ->
true
| NODE(_, _, _), NODE(l2, k2, r2) ->
let l1, b, r1 = split k2 t1 in
not b && disjoint l1 l2 && disjoint r1 r2
*)(* The above code can be improved by adding a fast path (based on physical
equality), by adding special cases for singletons, and by using a copy of
[split] that does not construct the subtrees [l] and [r] if the Boolean
result [b] is true. *)(* I have played with these variations, but I find them to be consistently
slower than the following approach, which is based on [Enum.disjoint]. *)letdisjointt1t2=match# 41 "Disjoint.frag.ml"(t1)# 41 "Disjoint.frag.ml",# 41 "Disjoint.frag.ml"(t2)# 41 "Disjoint.frag.ml"with|# 42 "Disjoint.frag.ml"TLeaf# 42 "Disjoint.frag.ml",_|_,# 43 "Disjoint.frag.ml"TLeaf# 43 "Disjoint.frag.ml"->true(* fast path *)|_,_-># 47 "Disjoint.frag.ml"t1!=t2&&(* fast path *)# 49 "Disjoint.frag.ml"Enum.(disjoint(enumt1)(enumt2))(* I have also played with a version of [disjoint] that does not use [split],
therefore does not construct new trees; it does not allocate memory or
perform rebalancing work. It can be fast, but I believe that its worst-case
time complexity is not optimal. *)# 1 "Subset.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Inclusion. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 21 "Subset.frag.ml"(* This simple version of [subset] has canonical structure. *)(* (Disabled.)
let rec subset (t1 : set) (t2 : set) : bool =
match VIEW(t1), VIEW(t2) with
| LEAF, _ ->
true
| _, LEAF ->
false
| NODENODE(_, _, _, l2, v2, r2)
let l1, r1 = split13 v2 t1 in
subset l1 l2 && subset r1 r2
*)(* This version adds a positive fast path (based on physical equality), a
negative fast path (based on weights), and a special treatment of the case
where [t1] is a singleton. (There is no need to add special treatment of
the case where [t2] is a singleton. Indeed, the subcases where [t1] is
empty or a singleton are taken care of already, and the subcase where [t1]
has more than one element is caught by the weight test.) *)(* In weight-balanced trees, the weight of a tree can be determined in time
O(1). This yields a negative fast path: if [weight t1 <= weight t2] does
not hold, then [subset t1 t2] returns false. In height-balanced trees, the
[weight] function returns a constant value, so this fast path is
disabled. *)letrecsubset(t1:set)(t2:set):bool=match# 51 "Subset.frag.ml"(t1)# 51 "Subset.frag.ml",# 51 "Subset.frag.ml"(t2)# 51 "Subset.frag.ml"with|# 52 "Subset.frag.ml"TLeaf# 52 "Subset.frag.ml",_->true|_,# 54 "Subset.frag.ml"TLeaf# 54 "Subset.frag.ml"->false|# 56 "Subset.frag.ml"TNode{l=l1;v=v1;r=r1;_},TNode{l=l2;v=v2;r=r2;_}-># 57 "Subset.frag.ml"t1==t2||(* fast path *)if# 58 "Subset.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 58 "Subset.frag.ml"then(* The tree [t1] is [singleton v1]. *)memv1t2elseweightt1<=weightt2&&(* fast path *)letl1,r1=split13v2t1insubsetl1l2&&subsetr1r2# 1 "Map.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [map] and [filter_map]. *)(* The set variant is more complex because the function [f] is not
necessarily monotone. The map variant is simpler because its API is
less expressive; by construction, the key component is preserved
and the function [f] transforms only the data component, so the
transformation that is applied to the key-data pair is monotone. *)# 23 "Map.frag.ml"(* -------------------------------------------------------------------------- *)(* The set variant. *)(* [map] is defined in the same way as in OCaml's Set library. *)(* [tree_below_key] and [key_below_tree] invoke [min_elt] or [max_elt],
whose cost is the height of the subtree. The cumulative cost of
these calls, during the execution of [map], is of the form
1 * n/2 + 2 * n/4 + 3 * n/8 + ..., that is, O(n). *)(* If the function [f] is monotone, then the tests in [lax_join]
always succeed, so [join] is invoked at every node, and every
such call runs in constant time, since no rebalancing is
required. Thus, in this case, [map] runs in linear time. *)(* Otherwise, I believe (but have not carefully checked) that the
complexity of [map] is O(n.log n). *)let[@inline]tree_below_key(t:# 42 "Map.frag.ml"elttree# 42 "Map.frag.ml")(x:key):bool=match# 43 "Map.frag.ml"(t)# 43 "Map.frag.ml"with|# 44 "Map.frag.ml"TLeaf# 44 "Map.frag.ml"->true|# 46 "Map.frag.ml"TNode{l=_;v=v;r=r;_}-># 47 "Map.frag.ml"E.compare(max_elt_1vr)x<0let[@inline]key_below_tree(x:key)(t:# 49 "Map.frag.ml"elttree# 49 "Map.frag.ml"):bool=match# 50 "Map.frag.ml"(t)# 50 "Map.frag.ml"with|# 51 "Map.frag.ml"TLeaf# 51 "Map.frag.ml"->true|# 53 "Map.frag.ml"TNode{l=l;v=v;r=_;_}-># 54 "Map.frag.ml"E.comparex(min_elt_1vl)<0(* [lax_join l v r] is analogous to [join l v r], but does not
require [l < v < r]. *)let[@inline]lax_joinlvr=iftree_below_keylv&&key_below_treevrthenjoinlvrelseunionl(addvr)letrecmapf(t:# 65 "Map.frag.ml"elttree# 65 "Map.frag.ml")=match# 66 "Map.frag.ml"(t)# 66 "Map.frag.ml"with|# 67 "Map.frag.ml"TLeaf# 67 "Map.frag.ml"->leaf|# 69 "Map.frag.ml"TNode{l=l;v=v;r=r;_}-># 70 "Map.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=mapflinletv'=fvinletr'=mapfrinifl==l'&&v==v'&&r==r'thent(* preserve sharing *)elselax_joinl'v'r'(* -------------------------------------------------------------------------- *)(* [lax_join2] plays the role of [try_concat] in OCaml's Set library,
but is implemented in a slightly better way. *)letlax_join2t1t2=match# 83 "Map.frag.ml"(t1)# 83 "Map.frag.ml",# 83 "Map.frag.ml"(t2)# 83 "Map.frag.ml"with|# 84 "Map.frag.ml"TLeaf# 84 "Map.frag.ml",_->t2|_,# 86 "Map.frag.ml"TLeaf# 86 "Map.frag.ml"->t1|_,_->ifE.compare(max_eltt1)(min_eltt2)<0thenjoin2t1t2elseuniont1t2(* [filter_map] is defined in the same way as in OCaml's Set library. *)letrecfilter_mapf(t:# 96 "Map.frag.ml"elttree# 96 "Map.frag.ml")=match# 97 "Map.frag.ml"(t)# 97 "Map.frag.ml"with|# 98 "Map.frag.ml"TLeaf# 98 "Map.frag.ml"->leaf|# 100 "Map.frag.ml"TNode{l=l;v=v;r=r;_}-># 101 "Map.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=filter_mapflinletv'=fvinletr'=filter_mapfrinmatchv'with|Somev'->ifl==l'&&v==v'&&r==r'thent(* preserve sharing *)elselax_joinl'v'r'|None->lax_join2l'r'# 1 "Filter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [filter] is the same as in OCaml's Set library. *)(* Because [join] and [join2] have logarithmic cost, this implementation
of [filter] has linear time complexity. *)(* One could imagine a completely different implementation of [filter],
also with linear time complexity, as follows: copy the data to an
array, filter the array, reconstruct a tree. However, this approach
would require linear auxiliary storage, may be slower in practice, and
would be less effective at preserving sharing in scenarios where many
elements are retained. *)letrecfilterp(t:# 25 "Filter.frag.ml"elttree# 25 "Filter.frag.ml"):# 25 "Filter.frag.ml"elttree# 25 "Filter.frag.ml"=match# 26 "Filter.frag.ml"(t)# 26 "Filter.frag.ml"with|# 27 "Filter.frag.ml"TLeaf# 27 "Filter.frag.ml"->leaf|# 29 "Filter.frag.ml"TNode{l=l;v=v;r=r;_}-># 30 "Filter.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=filterplinletkeep=# 32 "Filter.frag.ml"((p)(v))# 32 "Filter.frag.ml"inletr'=filterprinifkeepthenifl==l'&&r==r'thentelsejoinl'vr'elsejoin2l'r'(* [partition] is the same as in OCaml's Set library, with one extra
optimization: as in [filter], we attempt to preserve sharing where
possible. *)letrecpartitionp(t:# 43 "Filter.frag.ml"elttree# 43 "Filter.frag.ml"):# 43 "Filter.frag.ml"elttree# 43 "Filter.frag.ml"*# 43 "Filter.frag.ml"elttree# 43 "Filter.frag.ml"=match# 44 "Filter.frag.ml"(t)# 44 "Filter.frag.ml"with|# 45 "Filter.frag.ml"TLeaf# 45 "Filter.frag.ml"->leaf,leaf|# 47 "Filter.frag.ml"TNode{l=l;v=v;r=r;_}-># 48 "Filter.frag.ml"(* Enforce left-to-right evaluation order. *)letlt,lf=partitionplinletkeep=# 50 "Filter.frag.ml"((p)(v))# 50 "Filter.frag.ml"inletrt,rf=partitionprinifkeepthen(iflt==l&&rt==rthentelsejoinltvrt),join2lfrfelsejoin2ltrt,(iflf==l&&rf==rthentelsejoinlfvrf)# 1 "Conversions.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* [elements] converts a set, in linear time, to a sorted list. *)letrecto_list(t:# 17 "Conversions.frag.ml"elttree# 17 "Conversions.frag.ml")(k:# 17 "Conversions.frag.ml"elt# 17 "Conversions.frag.ml"list):# 17 "Conversions.frag.ml"elt# 17 "Conversions.frag.ml"list=match# 18 "Conversions.frag.ml"(t)# 18 "Conversions.frag.ml"with|# 19 "Conversions.frag.ml"TLeaf# 19 "Conversions.frag.ml"->k|# 21 "Conversions.frag.ml"TNode{l=l;v=v;r=r;_}-># 22 "Conversions.frag.ml"to_listl(v::to_listrk)let[@inline]to_list(t:# 24 "Conversions.frag.ml"elttree# 24 "Conversions.frag.ml"):# 24 "Conversions.frag.ml"elt# 24 "Conversions.frag.ml"list=to_listt[](* -------------------------------------------------------------------------- *)(* [to_seq] constructs the increasing sequence of the elements of the
tree [t]. *)letto_seq(t:# 32 "Conversions.frag.ml"elttree# 32 "Conversions.frag.ml"):# 32 "Conversions.frag.ml"elt# 32 "Conversions.frag.ml"Seq.t=fun()->Enum.(to_seq_node(enumt))(* [to_seq_from low t] constructs the increasing sequence of the
elements [x] of the tree [t] such that [low <= x] holds. *)letto_seq_from(low:key)(t:# 38 "Conversions.frag.ml"elttree# 38 "Conversions.frag.ml"):# 38 "Conversions.frag.ml"elt# 38 "Conversions.frag.ml"Seq.t=fun()->Enum.(to_seq_node(from_enumlowt))(* [to_rev_seq] constructs the decreasing sequence of the elements of
the tree [t]. *)letto_rev_seq(t:# 44 "Conversions.frag.ml"elttree# 44 "Conversions.frag.ml"):# 44 "Conversions.frag.ml"elt# 44 "Conversions.frag.ml"Seq.t=fun()->RevEnum.(to_seq_node(enumt))(* -------------------------------------------------------------------------- *)(* [to_array_slice t a i] writes the elements of the tree [t] to the
array slice determined by the array [a] and the start index [i].
It returns the end index of this slice. *)letrecto_array_slice(t:# 53 "Conversions.frag.ml"elttree# 53 "Conversions.frag.ml")ai:int=assert(0<=i&&i+cardinalt<=Array.lengtha);match# 55 "Conversions.frag.ml"(t)# 55 "Conversions.frag.ml"with|# 56 "Conversions.frag.ml"TLeaf# 56 "Conversions.frag.ml"->i|# 58 "Conversions.frag.ml"TNode{l=l;v=v;r=r;_}-># 59 "Conversions.frag.ml"leti=to_array_slicelaiina.(i)<-v;leti=i+1into_array_slicerai(* -------------------------------------------------------------------------- *)(* [to_array] converts a set, in linear time, to a sorted array. *)letto_array(t:# 68 "Conversions.frag.ml"elttree# 68 "Conversions.frag.ml"):# 68 "Conversions.frag.ml"elt# 68 "Conversions.frag.ml"array=match# 69 "Conversions.frag.ml"(t)# 69 "Conversions.frag.ml"with|# 70 "Conversions.frag.ml"TLeaf# 70 "Conversions.frag.ml"->[||]|# 72 "Conversions.frag.ml"TNode{l=_;v=dummy;r=_;_}-># 73 "Conversions.frag.ml"letn=cardinaltinleta=Array.makendummyinletj=to_array_sliceta0inassert(n=j);a(* -------------------------------------------------------------------------- *)(* [of_sorted_unique_array_slice] is available as part of the [BASE_SET]
or [BASE_MAP] signature. *)(* -------------------------------------------------------------------------- *)(* [of_sorted_unique_array a] requires the array [a] to be sorted and to
contain no duplicate elements. It converts this array, in linear time,
to a set. *)(* Because this function is unsafe (the user can provide an array that
is not sorted and/or that has duplicate elements), it is disabled.
[to_array] (below) is safe and is almost just as fast.
let[@inline] of_sorted_unique_array a =
of_sorted_unique_array_slice a 0 (Array.length a)
*)(* -------------------------------------------------------------------------- *)(* [of_array] converts an array to a set. This algorithm is adaptive. If the
array is sorted, then its time complexity is O(n). If the array is not
sorted, then its time complexity gradually degenerates to O(n.log n). *)(* Each run of consecutive increasing elements is converted to a set, in
linear time in the length of this run. Then, the union of these sets
is computed. *)(* [override] is [union] with priority to the right-hand argument. So,
in the map variant, if a key appears twice in the list, the rightmost
binding takes over. *)letof_arraya=letyieldaccuij=overrideaccu(of_sorted_unique_array_sliceaij)inArrayExtra.foreach_increasing_runcompare_eltsyieldemptya(* -------------------------------------------------------------------------- *)(* [of_list] converts a list to a set. It is adaptive. *)(* OCaml's Set library constructs a sorted list (using [List.sort_uniq]) and
converts it directly to a tree. Instead, we convert the list to an array
and use [of_array]. On random data, our approach seems slower by about 50%.
On sorted data, our approach can be 2x or 3x faster. One drawback of our
approach is that it requires linear auxiliary storage. *)letof_listxs=xs|>Array.of_list|>of_array(* -------------------------------------------------------------------------- *)(* [of_seq] converts a sequence to a set. It is adaptive. *)(* [of_seq] in OCaml's Set library is implemented using [add_seq], which
itself is naively implemented by iterated insertions, so its complexity
is O(n.log n), whereas it could be O(n). *)letof_seqxs=xs|>Array.of_seq|>of_array(* [add_seq] inserts a sequence into a set. *)letadd_seqxst=overridet(of_seqxs)# 1 "RandomAccess.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* The functions in this file assume that we have a constant-time [cardinal]
function. *)(* -------------------------------------------------------------------------- *)(* Access to an element, based on its index. *)(* [get] has logarithmic complexity. *)(* If [cardinal] requires linear time then this implementation of [get] has
quadratic time complexity, which is unacceptable. In that case, it is
preferable to just use [to_array], which has linear time complexity,
followed with [Array.get]. *)letrecget(t:# 27 "RandomAccess.frag.ml"elttree# 27 "RandomAccess.frag.ml")(i:int):# 27 "RandomAccess.frag.ml"elt# 27 "RandomAccess.frag.ml"=assert(0<=i&&i<cardinalt);match# 29 "RandomAccess.frag.ml"(t)# 29 "RandomAccess.frag.ml"with|# 30 "RandomAccess.frag.ml"TLeaf# 30 "RandomAccess.frag.ml"->assertfalse|# 32 "RandomAccess.frag.ml"TNode{l=l;v=v;r=r;_}-># 33 "RandomAccess.frag.ml"letcl=cardinallinifi=clthenvelseifi<clthengetlielsegetr(i-(cl+1))letget(t:# 41 "RandomAccess.frag.ml"elttree# 41 "RandomAccess.frag.ml")(i:int):# 41 "RandomAccess.frag.ml"elt# 41 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<cardinaltthengettielsePrintf.sprintf"get: index %d is out of expected range [0, %d)"i(cardinalt)|>invalid_argelsefailwith"get: operation is not available"(* -------------------------------------------------------------------------- *)(* Discovering the index of an element, based on its value. *)(* [index] has logarithmic complexity. *)(* [index] is roughly analogous to [List.find_index], but has a different
type; [index] expects an element [x], whereas [List.find_index] expects
a predicate of type [elt -> bool]. *)(* We could offer [find_index] on sets, with linear time complexity, but
this seems pointless. The user can implement this function using an
enumeration, if she so wishes. *)letrecindex(i:int)(x:key)(t:# 66 "RandomAccess.frag.ml"elttree# 66 "RandomAccess.frag.ml"):int=match# 67 "RandomAccess.frag.ml"(t)# 67 "RandomAccess.frag.ml"with|# 68 "RandomAccess.frag.ml"TLeaf# 68 "RandomAccess.frag.ml"->raiseNot_found|# 70 "RandomAccess.frag.ml"TNode{l=l;v=v;r=r;_}-># 71 "RandomAccess.frag.ml"letc=E.comparex(# 71 "RandomAccess.frag.ml"(v)# 71 "RandomAccess.frag.ml")inifc<0thenindexixlelseleti=i+cardinallinifc=0thenielseindex(i+1)xrlet[@inline]indexxt=index0xtletindexxt=ifconstant_time_cardinalthenindexxtelsefailwith"index: operation is not available"(* -------------------------------------------------------------------------- *)(* Splitting by index -- in two parts. *)letreccut(t:# 94 "RandomAccess.frag.ml"elttree# 94 "RandomAccess.frag.ml")(i:int):# 94 "RandomAccess.frag.ml"elttree# 94 "RandomAccess.frag.ml"*# 94 "RandomAccess.frag.ml"elttree# 94 "RandomAccess.frag.ml"=assert(0<=i&&i<=cardinalt);ifi=0thenleaf,telseifi=cardinaltthent,leafelsematch# 101 "RandomAccess.frag.ml"(t)# 101 "RandomAccess.frag.ml"with|# 102 "RandomAccess.frag.ml"TLeaf# 102 "RandomAccess.frag.ml"->assertfalse|# 104 "RandomAccess.frag.ml"TNode{l=l;v=v;r=r;_}-># 105 "RandomAccess.frag.ml"letcl=cardinallinifi<=clthenletll,lr=cutliinassert(lr!=l);ll,joinlrvrelse(* [cl < i] *)letrl,rr=cutr(i-(cl+1))inassert(rl!=r);joinlvrl,rrletcut(t:# 115 "RandomAccess.frag.ml"elttree# 115 "RandomAccess.frag.ml")(i:int):# 115 "RandomAccess.frag.ml"elttree# 115 "RandomAccess.frag.ml"*# 115 "RandomAccess.frag.ml"elttree# 115 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<=cardinaltthencuttielsePrintf.sprintf"cut: index %d is out of expected range [0, %d]"i(cardinalt)|>invalid_argelsefailwith"cut: operation is not available"(* -------------------------------------------------------------------------- *)(* Splitting by index -- in three parts. *)letreccut_and_get(t:# 130 "RandomAccess.frag.ml"elttree# 130 "RandomAccess.frag.ml")(i:int):# 130 "RandomAccess.frag.ml"elttree# 130 "RandomAccess.frag.ml"*# 130 "RandomAccess.frag.ml"elt# 130 "RandomAccess.frag.ml"*# 130 "RandomAccess.frag.ml"elttree# 130 "RandomAccess.frag.ml"=assert(0<=i&&i<cardinalt);match# 132 "RandomAccess.frag.ml"(t)# 132 "RandomAccess.frag.ml"with|# 133 "RandomAccess.frag.ml"TLeaf# 133 "RandomAccess.frag.ml"->assertfalse|# 135 "RandomAccess.frag.ml"TNode{l=l;v=v;r=r;_}-># 136 "RandomAccess.frag.ml"letcl=cardinallinifi=clthenl,v,relseifi<clthenletll,lv,lr=cut_and_getliinll,lv,joinlrvrelseletrl,rv,rr=cut_and_getr(i-(cl+1))injoinlvrl,rv,rrletcut_and_get(t:# 146 "RandomAccess.frag.ml"elttree# 146 "RandomAccess.frag.ml")(i:int):# 146 "RandomAccess.frag.ml"elttree# 146 "RandomAccess.frag.ml"*# 146 "RandomAccess.frag.ml"elt# 146 "RandomAccess.frag.ml"*# 146 "RandomAccess.frag.ml"elttree# 146 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<cardinaltthencut_and_gettielsePrintf.sprintf"cut_and_get: index %d is out of expected range [0, %d)"i(cardinalt)|>invalid_argelsefailwith"cut_and_get: operation is not available"# 1 "Iter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letreciterf(t:# 13 "Iter.frag.ml"elttree# 13 "Iter.frag.ml")=match# 14 "Iter.frag.ml"(t)# 14 "Iter.frag.ml"with|# 15 "Iter.frag.ml"TLeaf# 15 "Iter.frag.ml"->()|# 17 "Iter.frag.ml"TNode{l=l;v=v;r=r;_}-># 18 "Iter.frag.ml"iterfl;# 18 "Iter.frag.ml"((f)(v))# 18 "Iter.frag.ml";iterfrletrecfoldf(t:# 20 "Iter.frag.ml"elttree# 20 "Iter.frag.ml")accu=match# 21 "Iter.frag.ml"(t)# 21 "Iter.frag.ml"with|# 22 "Iter.frag.ml"TLeaf# 22 "Iter.frag.ml"->accu|# 24 "Iter.frag.ml"TNode{l=l;v=v;r=r;_}-># 25 "Iter.frag.ml"foldfr(# 25 "Iter.frag.ml"((f)(v)(foldflaccu))# 25 "Iter.frag.ml")letrecfor_allp(t:# 27 "Iter.frag.ml"elttree# 27 "Iter.frag.ml")=match# 28 "Iter.frag.ml"(t)# 28 "Iter.frag.ml"with|# 29 "Iter.frag.ml"TLeaf# 29 "Iter.frag.ml"->true|# 31 "Iter.frag.ml"TNode{l=l;v=v;r=r;_}-># 32 "Iter.frag.ml"((p)(v))# 32 "Iter.frag.ml"&&for_allpl&&for_allprletrecexistsp(t:# 34 "Iter.frag.ml"elttree# 34 "Iter.frag.ml")=match# 35 "Iter.frag.ml"(t)# 35 "Iter.frag.ml"with|# 36 "Iter.frag.ml"TLeaf# 36 "Iter.frag.ml"->false|# 38 "Iter.frag.ml"TNode{l=l;v=v;r=r;_}-># 39 "Iter.frag.ml"((p)(v))# 39 "Iter.frag.ml"||existspl||existspr# 137 "UpperLayer.frag.ml"(* In the set API, [to_list] is published under the name [elements]. *)letelements=to_list# 155 "UpperLayer.frag.ml"(* -------------------------------------------------------------------------- *)# 25 "W.cppo.ml"endend# 1 "ConcreteView.macros"(* In the concrete view, to deconstruct a tree [t], one matches the tree [t]
directly against the patterns [TLeaf] and [TNode _]. This requires the
concrete definition of the type [tree] to be visible. *)(* In the map variant, a pair must be constructed. This is rather painful,
as it cannot be done in a pattern, on the left-hand side of the arrow;
it must be done in an expression, on the right-hand side of the arrow.
This forces the macro [NODE] to include the arrow itself. *)# 1 "Derived.macros"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Derived macros. *)(* [EMPTY(t)] determines whether the tree [t] is empty, that is, a leaf. *)# 19 "Derived.macros"(* [BOTH_EMPTY(l,r)] determines whether the trees [l] and [r] are both empty. *)# 35 "W.cppo.ml"moduleMap=structmoduletypeOrderedType=OrderedTypemoduletypeS=MAPmodule[@inline]Make(E:OrderedType)=structincludeWeightMap# 1 "UpperLayer.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Types. *)(* A key is a value of the ordered type [E.t]. *)(* In the set variant, a set element and a key are the same thing.
In the map variant, a map element is a binding, that is, a key-data pair.
Therefore, a key is just the first component of a map element. *)(* The following types exist in both variants:
+ [key] is the type of a key;
+ [DATA] is the type of a datum;
+ [ELT] is the type of an element;
+ [TREE] is the type of a tree.
[DATA], [ELT], and [TREE] may contain a wildcard, so they can be used only
in type annotations (as opposed to type definitions, signatures, etc.).
The following macros exist in both variants:
+ [EXTRA(x)] expands to nothing in the set variant
and to [x] in the map variant;
+ [GET_KEY(v)] extracts the key component of the element [v];
+ [GET_DATA(v)] extracts the data component of the element [v];
*)typekey=E.t# 60 "UpperLayer.frag.ml"type'abinding=key*'atype'amap='abindingtreetype'at='amap# 74 "UpperLayer.frag.ml"(* The total order on elements. *)let[@inline]compare_elts(x:# 76 "UpperLayer.frag.ml"(key*_)# 76 "UpperLayer.frag.ml")(y:# 76 "UpperLayer.frag.ml"(key*_)# 76 "UpperLayer.frag.ml"):int=E.compare(# 77 "UpperLayer.frag.ml"(let(_k,_)=xin_k)# 77 "UpperLayer.frag.ml")(# 77 "UpperLayer.frag.ml"(let(_k,_)=yin_k)# 77 "UpperLayer.frag.ml")(* The following macro is used by [union] and [inter] on maps.
We could also make it a function and mark it [@inline]. *)# 85 "UpperLayer.frag.ml"(* The following macros abstract away the distinction between
[if] on a Boolean value and [match] on an option. *)# 96 "UpperLayer.frag.ml"(* The following macro applies the function [f] directly to [v] in the set
variant and separately to the two components of the pair [v] in the map
variant. *)# 108 "UpperLayer.frag.ml"(* -------------------------------------------------------------------------- *)(* Operations. *)# 1 "Empty.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letempty:# 13 "Empty.frag.ml"(key*_)tree# 13 "Empty.frag.ml"=leafletis_empty(t:# 16 "Empty.frag.ml"(key*_)tree# 16 "Empty.frag.ml"):bool=match# 17 "Empty.frag.ml"(t)# 17 "Empty.frag.ml"with|# 18 "Empty.frag.ml"TLeaf# 18 "Empty.frag.ml"->true|# 20 "Empty.frag.ml"TNode{l=_;k=_k;d=_d;r=_;_}->let_=(_k,_d)in# 21 "Empty.frag.ml"false# 1 "MinMax.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letrecmin_elt_1(default:# 13 "MinMax.frag.ml"(key*_)# 13 "MinMax.frag.ml")(t:# 13 "MinMax.frag.ml"(key*_)tree# 13 "MinMax.frag.ml"):# 13 "MinMax.frag.ml"(key*_)# 13 "MinMax.frag.ml"=match# 14 "MinMax.frag.ml"(t)# 14 "MinMax.frag.ml"with|# 15 "MinMax.frag.ml"TLeaf# 15 "MinMax.frag.ml"->default|# 17 "MinMax.frag.ml"TNode{l=l;k=_k;d=_d;r=_;_}->letv=(_k,_d)in# 18 "MinMax.frag.ml"min_elt_1vlletmin_elt(t:# 20 "MinMax.frag.ml"(key*_)tree# 20 "MinMax.frag.ml"):# 20 "MinMax.frag.ml"(key*_)# 20 "MinMax.frag.ml"=match# 21 "MinMax.frag.ml"(t)# 21 "MinMax.frag.ml"with|# 22 "MinMax.frag.ml"TLeaf# 22 "MinMax.frag.ml"->raiseNot_found|# 24 "MinMax.frag.ml"TNode{l=l;k=_k;d=_d;r=_;_}->letv=(_k,_d)in# 25 "MinMax.frag.ml"min_elt_1vlletrecmin_elt_opt_1(default:# 27 "MinMax.frag.ml"(key*_)# 27 "MinMax.frag.ml")(t:# 27 "MinMax.frag.ml"(key*_)tree# 27 "MinMax.frag.ml"):# 27 "MinMax.frag.ml"(key*_)# 27 "MinMax.frag.ml"option=match# 28 "MinMax.frag.ml"(t)# 28 "MinMax.frag.ml"with|# 29 "MinMax.frag.ml"TLeaf# 29 "MinMax.frag.ml"->Somedefault|# 31 "MinMax.frag.ml"TNode{l=l;k=_k;d=_d;r=_;_}->letv=(_k,_d)in# 32 "MinMax.frag.ml"min_elt_opt_1vlletmin_elt_opt(t:# 34 "MinMax.frag.ml"(key*_)tree# 34 "MinMax.frag.ml"):# 34 "MinMax.frag.ml"(key*_)# 34 "MinMax.frag.ml"option=match# 35 "MinMax.frag.ml"(t)# 35 "MinMax.frag.ml"with|# 36 "MinMax.frag.ml"TLeaf# 36 "MinMax.frag.ml"->None|# 38 "MinMax.frag.ml"TNode{l=l;k=_k;d=_d;r=_;_}->letv=(_k,_d)in# 39 "MinMax.frag.ml"min_elt_opt_1vlletrecmax_elt_1(default:# 41 "MinMax.frag.ml"(key*_)# 41 "MinMax.frag.ml")(t:# 41 "MinMax.frag.ml"(key*_)tree# 41 "MinMax.frag.ml"):# 41 "MinMax.frag.ml"(key*_)# 41 "MinMax.frag.ml"=match# 42 "MinMax.frag.ml"(t)# 42 "MinMax.frag.ml"with|# 43 "MinMax.frag.ml"TLeaf# 43 "MinMax.frag.ml"->default|# 45 "MinMax.frag.ml"TNode{l=_;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 46 "MinMax.frag.ml"max_elt_1vrletmax_elt(t:# 48 "MinMax.frag.ml"(key*_)tree# 48 "MinMax.frag.ml"):# 48 "MinMax.frag.ml"(key*_)# 48 "MinMax.frag.ml"=match# 49 "MinMax.frag.ml"(t)# 49 "MinMax.frag.ml"with|# 50 "MinMax.frag.ml"TLeaf# 50 "MinMax.frag.ml"->raiseNot_found|# 52 "MinMax.frag.ml"TNode{l=_;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 53 "MinMax.frag.ml"max_elt_1vrletrecmax_elt_opt_1(default:# 55 "MinMax.frag.ml"(key*_)# 55 "MinMax.frag.ml")(t:# 55 "MinMax.frag.ml"(key*_)tree# 55 "MinMax.frag.ml"):# 55 "MinMax.frag.ml"(key*_)# 55 "MinMax.frag.ml"option=match# 56 "MinMax.frag.ml"(t)# 56 "MinMax.frag.ml"with|# 57 "MinMax.frag.ml"TLeaf# 57 "MinMax.frag.ml"->Somedefault|# 59 "MinMax.frag.ml"TNode{l=_;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 60 "MinMax.frag.ml"max_elt_opt_1vrletmax_elt_opt(t:# 62 "MinMax.frag.ml"(key*_)tree# 62 "MinMax.frag.ml"):# 62 "MinMax.frag.ml"(key*_)# 62 "MinMax.frag.ml"option=match# 63 "MinMax.frag.ml"(t)# 63 "MinMax.frag.ml"with|# 64 "MinMax.frag.ml"TLeaf# 64 "MinMax.frag.ml"->None|# 66 "MinMax.frag.ml"TNode{l=_;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 67 "MinMax.frag.ml"max_elt_opt_1vr(* In the map variant, the above operations have different names. *)# 72 "MinMax.frag.ml"letmin_binding=min_eltletmin_binding_opt=min_elt_optletmax_binding=max_eltletmax_binding_opt=max_elt_opt# 78 "MinMax.frag.ml"(* As in OCaml's Set library, [choose] and [choose_opt] choose the minimum
element of the set. This is slow (logarithmic time), but guarantees that
[choose] respects equality: that is, if the sets [s1] and [s2] are equal
then [choose s1] and [choose s2] are equal. *)letchoose=min_eltletchoose_opt=min_elt_opt# 1 "Mem.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* The value [v] that is extracted out of the tree has type [ELT]. In the set
variant, it is an element of the set. In the map variant, it is a pair of
a key and a value. In either case, [GET_KEY(v)] is a key. *)letrecmem(x:key)(t:# 17 "Mem.frag.ml"(key*_)tree# 17 "Mem.frag.ml"):bool=match# 18 "Mem.frag.ml"(t)# 18 "Mem.frag.ml"with|# 19 "Mem.frag.ml"TLeaf# 19 "Mem.frag.ml"->false|# 21 "Mem.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 22 "Mem.frag.ml"letc=E.comparex(# 22 "Mem.frag.ml"(let(_k,_)=vin_k)# 22 "Mem.frag.ml")inc=0||memx(ifc<0thenlelser)# 1 "Find.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letrecfind(x:key)(t:# 13 "Find.frag.ml"(key*_)tree# 13 "Find.frag.ml"):# 13 "Find.frag.ml"_# 13 "Find.frag.ml"=match# 14 "Find.frag.ml"(t)# 14 "Find.frag.ml"with|# 15 "Find.frag.ml"TLeaf# 15 "Find.frag.ml"->raiseNot_found|# 17 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 18 "Find.frag.ml"letc=E.comparex(# 18 "Find.frag.ml"(let(_k,_)=vin_k)# 18 "Find.frag.ml")inifc=0then# 20 "Find.frag.ml"(let(_,_d)=vin_d)# 21 "Find.frag.ml"elseifc<0thenfindxlelsefindxrletrecfind_opt(x:key)(t:# 26 "Find.frag.ml"(key*_)tree# 26 "Find.frag.ml"):# 26 "Find.frag.ml"_# 26 "Find.frag.ml"option=match# 27 "Find.frag.ml"(t)# 27 "Find.frag.ml"with|# 28 "Find.frag.ml"TLeaf# 28 "Find.frag.ml"->None|# 30 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 31 "Find.frag.ml"letc=E.comparex(# 31 "Find.frag.ml"(let(_k,_)=vin_k)# 31 "Find.frag.ml")inifc=0thenSome(# 33 "Find.frag.ml"(let(_,_d)=vin_d)# 33 "Find.frag.ml")elseifc<0thenfind_optxlelsefind_optxr(* -------------------------------------------------------------------------- *)(* [find_first] and its variants are as in OCaml's Set library. *)(* A lot of repetitive code. *)(* It is worth noting that [find_first] is not a naive linear search.
Instead, it assumes that [f] is a monotonically increasing function
of elements to Booleans. This implies that there is at most one
position in the increasing sequence of the set elements where the
value of [f] changes, and it changes from [false] to [true]. This
position can be found in logarithmic time. *)letrecfind_first_aux(v0:# 52 "Find.frag.ml"(key*_)# 52 "Find.frag.ml")(f:key->bool)(t:# 52 "Find.frag.ml"(key*_)tree# 52 "Find.frag.ml"):# 52 "Find.frag.ml"(key*_)# 52 "Find.frag.ml"=match# 53 "Find.frag.ml"(t)# 53 "Find.frag.ml"with|# 54 "Find.frag.ml"TLeaf# 54 "Find.frag.ml"->v0|# 56 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 57 "Find.frag.ml"iff(# 57 "Find.frag.ml"(let(_k,_)=vin_k)# 57 "Find.frag.ml")thenfind_first_auxvflelsefind_first_auxv0frletrecfind_first(f:key->bool)(t:# 62 "Find.frag.ml"(key*_)tree# 62 "Find.frag.ml"):# 62 "Find.frag.ml"(key*_)# 62 "Find.frag.ml"=match# 63 "Find.frag.ml"(t)# 63 "Find.frag.ml"with|# 64 "Find.frag.ml"TLeaf# 64 "Find.frag.ml"->raiseNot_found|# 66 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 67 "Find.frag.ml"iff(# 67 "Find.frag.ml"(let(_k,_)=vin_k)# 67 "Find.frag.ml")thenfind_first_auxvflelsefind_firstfrletrecfind_first_opt_aux(v0:# 72 "Find.frag.ml"(key*_)# 72 "Find.frag.ml")(f:key->bool)(t:# 72 "Find.frag.ml"(key*_)tree# 72 "Find.frag.ml"):# 72 "Find.frag.ml"(key*_)# 72 "Find.frag.ml"option=match# 73 "Find.frag.ml"(t)# 73 "Find.frag.ml"with|# 74 "Find.frag.ml"TLeaf# 74 "Find.frag.ml"->Somev0|# 76 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 77 "Find.frag.ml"iff(# 77 "Find.frag.ml"(let(_k,_)=vin_k)# 77 "Find.frag.ml")thenfind_first_opt_auxvflelsefind_first_opt_auxv0frletrecfind_first_opt(f:key->bool)(t:# 82 "Find.frag.ml"(key*_)tree# 82 "Find.frag.ml"):# 82 "Find.frag.ml"(key*_)# 82 "Find.frag.ml"option=match# 83 "Find.frag.ml"(t)# 83 "Find.frag.ml"with|# 84 "Find.frag.ml"TLeaf# 84 "Find.frag.ml"->None|# 86 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 87 "Find.frag.ml"iff(# 87 "Find.frag.ml"(let(_k,_)=vin_k)# 87 "Find.frag.ml")thenfind_first_opt_auxvflelsefind_first_optfrletrecfind_last_aux(v0:# 92 "Find.frag.ml"(key*_)# 92 "Find.frag.ml")(f:key->bool)(t:# 92 "Find.frag.ml"(key*_)tree# 92 "Find.frag.ml"):# 92 "Find.frag.ml"(key*_)# 92 "Find.frag.ml"=match# 93 "Find.frag.ml"(t)# 93 "Find.frag.ml"with|# 94 "Find.frag.ml"TLeaf# 94 "Find.frag.ml"->v0|# 96 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 97 "Find.frag.ml"iff(# 97 "Find.frag.ml"(let(_k,_)=vin_k)# 97 "Find.frag.ml")thenfind_last_auxvfrelsefind_last_auxv0flletrecfind_last(f:key->bool)(t:# 102 "Find.frag.ml"(key*_)tree# 102 "Find.frag.ml"):# 102 "Find.frag.ml"(key*_)# 102 "Find.frag.ml"=match# 103 "Find.frag.ml"(t)# 103 "Find.frag.ml"with|# 104 "Find.frag.ml"TLeaf# 104 "Find.frag.ml"->raiseNot_found|# 106 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 107 "Find.frag.ml"iff(# 107 "Find.frag.ml"(let(_k,_)=vin_k)# 107 "Find.frag.ml")thenfind_last_auxvfrelsefind_lastflletrecfind_last_opt_aux(v0:# 112 "Find.frag.ml"(key*_)# 112 "Find.frag.ml")(f:key->bool)(t:# 112 "Find.frag.ml"(key*_)tree# 112 "Find.frag.ml"):# 112 "Find.frag.ml"(key*_)# 112 "Find.frag.ml"option=match# 113 "Find.frag.ml"(t)# 113 "Find.frag.ml"with|# 114 "Find.frag.ml"TLeaf# 114 "Find.frag.ml"->Somev0|# 116 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 117 "Find.frag.ml"iff(# 117 "Find.frag.ml"(let(_k,_)=vin_k)# 117 "Find.frag.ml")thenfind_last_opt_auxvfrelsefind_last_opt_auxv0flletrecfind_last_opt(f:key->bool)(t:# 122 "Find.frag.ml"(key*_)tree# 122 "Find.frag.ml"):# 122 "Find.frag.ml"(key*_)# 122 "Find.frag.ml"option=match# 123 "Find.frag.ml"(t)# 123 "Find.frag.ml"with|# 124 "Find.frag.ml"TLeaf# 124 "Find.frag.ml"->None|# 126 "Find.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 127 "Find.frag.ml"iff(# 127 "Find.frag.ml"(let(_k,_)=vin_k)# 127 "Find.frag.ml")thenfind_last_opt_auxvfrelsefind_last_optfl# 1 "Add.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* This is insertion in the style of BFS. *)(* (Disabled.) (Set variant only.)
let add (k : key) (t : TREE) : TREE =
let l, _, r = split k t in
join l k r
*)# 55 "Add.frag.ml"(* If a binding for this key is already present in the map, then this
existing binding is replaced with a new binding. *)(* This implementation is adapted from OCaml's Map library. *)letrecreplace(x:key)(d:# 60 "Add.frag.ml"_# 60 "Add.frag.ml")(t:# 60 "Add.frag.ml"(key*_)tree# 60 "Add.frag.ml"):# 60 "Add.frag.ml"(key*_)tree# 60 "Add.frag.ml"=match# 61 "Add.frag.ml"(t)# 61 "Add.frag.ml"with|# 62 "Add.frag.ml"TLeaf# 62 "Add.frag.ml"->letv=(x,d)insingletonv|# 65 "Add.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 66 "Add.frag.ml"letc=E.comparex(# 66 "Add.frag.ml"(let(_k,_)=vin_k)# 66 "Add.frag.ml")inifc=0then(* Overwrite the existing element: *)if# 69 "Add.frag.ml"(let(_,_d)=vin_d)# 69 "Add.frag.ml"==dthentelseletv=(x,d)injoin_siblingslvrelseifc<0thenletl'=replacexdlinifl==l'thentelsejoin_quasi_siblingsl'vrelseletr'=replacexdrinifr==r'thentelsejoin_quasi_siblingslvr'(* [replace] is published under the name [add], but one should be
aware that [add] and [replace] are really two distinct functions,
as they differ in the way they choose between the existing element
and the new element. *)letadd=replace(* See also [update] and [union1]. *)(* [add_absent] is currently used by [xor]. It takes a key-data pair. *)letadd_absent(x,d)t=addxdt# 1 "Remove.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [remove_min_elt_1 l v r] removes the minimum element of the tree
[NODE(l, v, r)]. *)letrecremove_min_elt_1(l:# 16 "Remove.frag.ml"(key*_)tree# 16 "Remove.frag.ml")(v:# 16 "Remove.frag.ml"(key*_)# 16 "Remove.frag.ml")(r:# 16 "Remove.frag.ml"(key*_)tree# 16 "Remove.frag.ml"):# 16 "Remove.frag.ml"(key*_)tree# 16 "Remove.frag.ml"=match# 17 "Remove.frag.ml"(l)# 17 "Remove.frag.ml"with|# 18 "Remove.frag.ml"TLeaf# 18 "Remove.frag.ml"->r|# 20 "Remove.frag.ml"TNode{l=ll;k=_k;d=_d;r=lr;_}->letlv=(_k,_d)in# 21 "Remove.frag.ml"letl=remove_min_elt_1lllvlrinjoin_quasi_siblingslvr(* [remove_min_elt t] removes the minimum element of the tree [t]. *)letremove_min_elt(t:# 26 "Remove.frag.ml"(key*_)tree# 26 "Remove.frag.ml"):# 26 "Remove.frag.ml"(key*_)tree# 26 "Remove.frag.ml"=match# 27 "Remove.frag.ml"(t)# 27 "Remove.frag.ml"with|# 28 "Remove.frag.ml"TLeaf# 28 "Remove.frag.ml"->raiseNot_found|# 30 "Remove.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 31 "Remove.frag.ml"remove_min_elt_1lvr(* [remove_max_elt_1 l v r] removes the maximum element of the tree
[NODE(l, v, r)]. *)letrecremove_max_elt_1(l:# 36 "Remove.frag.ml"(key*_)tree# 36 "Remove.frag.ml")(v:# 36 "Remove.frag.ml"(key*_)# 36 "Remove.frag.ml")(r:# 36 "Remove.frag.ml"(key*_)tree# 36 "Remove.frag.ml"):# 36 "Remove.frag.ml"(key*_)tree# 36 "Remove.frag.ml"=match# 37 "Remove.frag.ml"(r)# 37 "Remove.frag.ml"with|# 38 "Remove.frag.ml"TLeaf# 38 "Remove.frag.ml"->l|# 40 "Remove.frag.ml"TNode{l=rl;k=_k;d=_d;r=rr;_}->letrv=(_k,_d)in# 41 "Remove.frag.ml"letr=remove_max_elt_1rlrvrrinjoin_quasi_siblingslvr(* [remove_max_elt t] removes the maximum element of the tree [t]. *)letremove_max_elt(t:# 46 "Remove.frag.ml"(key*_)tree# 46 "Remove.frag.ml"):# 46 "Remove.frag.ml"(key*_)tree# 46 "Remove.frag.ml"=match# 47 "Remove.frag.ml"(t)# 47 "Remove.frag.ml"with|# 48 "Remove.frag.ml"TLeaf# 48 "Remove.frag.ml"->raiseNot_found|# 50 "Remove.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 51 "Remove.frag.ml"remove_max_elt_1lvr(* In the map variant, the above operations have different names. *)# 56 "Remove.frag.ml"letremove_min_binding=remove_min_eltletremove_max_binding=remove_max_elt# 60 "Remove.frag.ml"(* [join2_siblings l r] is analogous to [join2 l r], but requires the
subtrees [l] and [r] to be siblings. *)(* [join2_siblings] is named [merge] in OCaml's Set library. *)(* This implementation arbitrarily chooses to place the minimum element of the
tree [r] at the root. One could also choose to place the maximum element of
the tree [l] at the root. One could imagine choosing between these
alternatives, based on the weights or heights of the trees [l] and [r], if
such a notion exists. That would remove the need for rebalancing. However,
this seems to make essentially no difference in practice. *)letjoin2_siblings(l:# 72 "Remove.frag.ml"(key*_)tree# 72 "Remove.frag.ml")(r:# 72 "Remove.frag.ml"(key*_)tree# 72 "Remove.frag.ml"):# 72 "Remove.frag.ml"(key*_)tree# 72 "Remove.frag.ml"=assert(siblingslr);match# 74 "Remove.frag.ml"(l)# 74 "Remove.frag.ml",# 74 "Remove.frag.ml"(r)# 74 "Remove.frag.ml"with|_,# 75 "Remove.frag.ml"TLeaf# 75 "Remove.frag.ml"->l|# 77 "Remove.frag.ml"TLeaf# 77 "Remove.frag.ml",_->r|_,# 79 "Remove.frag.ml"TNode{l=rl;k=_k;d=_d;r=rr;_}->letrv=(_k,_d)in# 80 "Remove.frag.ml"join_quasi_siblingsl(min_elt_1rvrl)(* same as [min_elt r] *)(remove_min_elt_1rlrvrr)(* same as [remove_min_elt r] *)(* This is removal in the style of BFS. *)(* (Disabled.) (Set variant only.)
let remove (k : key) (t : TREE) : TREE =
let l, _, r = split k t in
join2 l r
*)(* This is a less elegant but more efficient version of removal. *)(* This implementation is taken from OCaml's Set library. *)letrecremove(x:key)(t:# 99 "Remove.frag.ml"(key*_)tree# 99 "Remove.frag.ml"):# 99 "Remove.frag.ml"(key*_)tree# 99 "Remove.frag.ml"=match# 100 "Remove.frag.ml"(t)# 100 "Remove.frag.ml"with|# 101 "Remove.frag.ml"TLeaf# 101 "Remove.frag.ml"->empty|# 103 "Remove.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 104 "Remove.frag.ml"letc=E.comparex(# 104 "Remove.frag.ml"(let(_k,_)=vin_k)# 104 "Remove.frag.ml")inifc=0thenjoin2_siblingslrelseifc<0thenletl'=removexlinifl==l'thentelsejoin_quasi_siblingsl'vrelseletr'=removexrinifr==r'thentelsejoin_quasi_siblingslvr'# 116 "Remove.frag.ml"(* [update] generalizes [add], [replace], and [remove] by letting the user
choose how to transform the information associated with a specific key. *)(* This code is essentially the same as in OCaml's Map library. *)letrecupdate(x:key)(f:'aoption->'aoption)(t:'abindingtree):'abindingtree=match# 124 "Remove.frag.ml"(t)# 124 "Remove.frag.ml"with|# 125 "Remove.frag.ml"TLeaf# 125 "Remove.frag.ml"->beginmatchfNonewith|None->t|Somed->letv=(x,d)insingletonvend|# 133 "Remove.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 134 "Remove.frag.ml"let(k,d)=vinletc=E.comparexkinifc=0thenbeginmatchf(Somed)with|None->join2_siblingslr|Somed'->ifd==d'thentelseletv=(k,d')injoin_siblingslvrendelseifc<0thenletl'=updatexflinifl==l'thentelsejoin_quasi_siblingsl'vrelseletr'=updatexfrinifr==r'thentelsejoin_quasi_siblingslvr'(* [add_to_list] is taken from OCaml's Map library (and reformulated). *)let[@inline]flatten(ods:'alistoption):'alist=matchodswithNone->[]|Someds->dsletadd_to_listxdm=letaddods=Some(d::flattenods)inupdatexaddm# 1 "Split.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [split] is implemented in the same way in OCaml's Set library and by BFS. *)(* We use the same code, but add a physical equality test that allows us to
preserve sharing (and avoid memory allocation) in some cases. *)(* In the set variant, the second component of the result has type [bool].
In the map variant, it has type [DATA option]. *)# 33 "Split.frag.ml"letrecsplit(k:key)(t:# 33 "Split.frag.ml"(key*_)tree# 33 "Split.frag.ml"):# 33 "Split.frag.ml"(key*_)tree# 33 "Split.frag.ml"*# 33 "Split.frag.ml"_option# 33 "Split.frag.ml"*# 33 "Split.frag.ml"(key*_)tree# 33 "Split.frag.ml"=match# 34 "Split.frag.ml"(t)# 34 "Split.frag.ml"with|# 35 "Split.frag.ml"TLeaf# 35 "Split.frag.ml"->leaf,# 36 "Split.frag.ml"None# 36 "Split.frag.ml",leaf|# 37 "Split.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 38 "Split.frag.ml"letc=E.comparek(# 38 "Split.frag.ml"(let(_k,_)=vin_k)# 38 "Split.frag.ml")inifc=0thenl,# 40 "Split.frag.ml"Some((let(_,_d)=vin_d))# 40 "Split.frag.ml",relseifc<0thenletll,b,lr=splitklinll,b,(iflr==lthentelsejoinlrvr)elseletrl,b,rr=splitkrin(ifrl==rthentelsejoinlvrl),b,rr# 1 "Join.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [join2 l r] requires [l < r]. It joins the trees [l] and [r]
into a single tree. *)(* [join2] is known as [concat] in OCaml's Set library. *)(* This is the code proposed by BFS. Their [split_last] function
corresponds to our functions [min_elt] and [remove_min_elt_1].
(Set variant only.)
let rec split_last (l : TREE) (k : key) (r : TREE) : TREE * key =
match VIEW(r) with
| LEAF ->
l, k
| NODE(l', k', r')
let r, m = split_last l' k' r' in
join l k r, m
let join2 (l : TREE) (r : TREE) : TREE =
match VIEW(l) with
| LEAF ->
r
| NODE(ll, m, lr)
let l', k = split_last ll m lr in
join l' k r
*)(* [join2 l r] is implemented by extracting the maximum element of [l]
or the minimum element of [r] and letting [join] do the rest of the
work. *)(* In order to maintain a better balance, one might wish to extract an
element from the tree that seems larger. However, this seems to
bring no improvement in practice, so we avoid this complication. *)letjoin2(l:# 48 "Join.frag.ml"(key*_)tree# 48 "Join.frag.ml")(r:# 48 "Join.frag.ml"(key*_)tree# 48 "Join.frag.ml"):# 48 "Join.frag.ml"(key*_)tree# 48 "Join.frag.ml"=match# 49 "Join.frag.ml"(l)# 49 "Join.frag.ml",# 49 "Join.frag.ml"(r)# 49 "Join.frag.ml"with|# 50 "Join.frag.ml"TLeaf# 50 "Join.frag.ml",_->r|_,# 52 "Join.frag.ml"TLeaf# 52 "Join.frag.ml"->l|_,# 54 "Join.frag.ml"TNode{l=rl;k=_k;d=_d;r=rr;_}->letrv=(_k,_d)in# 55 "Join.frag.ml"joinl(min_elt_1rvrl)(* same as [min_elt r] *)(remove_min_elt_1rlrvrr)(* same as [remove_min_elt r] *)(* -------------------------------------------------------------------------- *)# 64 "Join.frag.ml"(* [ojoin] is known as [concat_or_join] in OCaml's Map library. *)(* [ojoin] is defined only in the map variant. *)letojoint1kodt2=matchodwith|None->join2t1t2|Somed->joint1(k,d)t2# 1 "Enum.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Enumerations. *)moduleEnum=struct(* An enumeration can be viewed as a list of pairs of an element and
a (sub)tree. It is sorted in increasing order of keys. *)(* There is no structural difference between the set variant and the
map variant. In the map variant, we do not flatten the key-data
pair into the constructor [More], as this seems unlikely to lead
to a gain in performance. *)(* In both variants, the type [ienum] is parameterized with ['v].
This type is internal (not public). *)type'vienum=|End|Moreof'v*'vtree*'vienum(* The public type [enum] is unparameterized in the set variant and
parameterized with ['a] in the map variant. *)# 39 "Enum.frag.ml"type'aenum='abindingienumtype'at='aenum# 43 "Enum.frag.ml"letempty:'vienum=Endlet[@inline]is_empty(e:'vienum):bool=matchewith|End->true|More_->false(* [cat_tree_enum t e] concatenates the tree [t] in front of the
enumeration [e]. *)(* This function is named [cons_enum] in OCaml's Set library. *)letreccat_tree_enum(t:'vtree)(e:'vienum):'vienum=match# 57 "Enum.frag.ml"(t)# 57 "Enum.frag.ml"with|# 58 "Enum.frag.ml"TLeaf# 58 "Enum.frag.ml"->e|# 60 "Enum.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 61 "Enum.frag.ml"cat_tree_enuml(More(v,r,e))(* [enum] converts a tree to an enumeration. *)let[@inline]enum(t:'vtree):'vienum=cat_tree_enumtempty(* [filter_tree low t e] constructs an enumeration whose elements are: 1-
the elements [x] of the tree [t] such that [low <= x] holds, followed
with 2- all elements of the enumeration [e]. *)(* In [filter_tree low t e], only the tree [t] is filtered by the constraint
[low <= x]. The enumeration [e] is not filtered (typically because it is
already known that all of its elements satisfy this constraint). This is
in contrast with [filter_tree_enum low t e] (below), where both [t] and
[e] are filtered. *)letrecfilter_tree(low:key)(t:'vtree)(e:'vienum):'vienum=match# 79 "Enum.frag.ml"(t)# 79 "Enum.frag.ml"with|# 80 "Enum.frag.ml"TLeaf# 80 "Enum.frag.ml"->e|# 82 "Enum.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 83 "Enum.frag.ml"letc=E.compare(# 83 "Enum.frag.ml"(let(_k,_)=vin_k)# 83 "Enum.frag.ml")lowinifc=0thenMore(v,r,e)elseifc<0thenfilter_treelowreelsefilter_treelowl(More(v,r,e))let[@inline]from_enum(low:key)(t:'vtree):'vienum=filter_treelowtempty(* [filter_tree_enum low r e] extracts the elements [x] that satisfy the
constraint [low <= x] out of the sequence of the elements of the tree [r]
and of the enumeration [e]. *)(* Thus, it is equivalent to [from low (cat_tree_enum r e)],
but the function [from] has not been defined yet.
[filter_tree_enum] is in fact used to define [from]. *)(* Both the tree [r] and the enumeration [e] are filtered. *)letrecfilter_tree_enum(low:key)(r:'vtree)(e:'vienum):'vienum=(* Peek past [r] at the first element [v'] of [e], if there is one. *)matchewith|More(v',r',e')->letc=E.comparelow(# 108 "Enum.frag.ml"(let(_k,_)=v'in_k)# 108 "Enum.frag.ml")inifc>0then(* [v'] is below the threshold.
The subtree [r] and the value [v'] must be discarded.
Continue with [r'] and [e']. *)filter_tree_enumlowr'e'elseifc=0then(* [v'] is at the threshold.
The subtree [r] must be discarded. [e] must be kept. *)eelse(* c < 0 *)(* [v'] is above the threshold. *)(* No part of [e] must be discarded. *)(* Keep part of [r], followed with [e]. *)filter_treelowre|End->(* [e] is empty. Keep part of [r]. *)filter_treelowre(* [from low e] extracts from the enumeration [e]
the elements that lie at or above the threshold [low] . *)(* One could define [from low e] as [filter_tree_enum low leaf e].
However, the following code is slightly more efficient. *)letfrom(low:key)(e:'vienum):'vienum=matchewith|More(v,r,e')->ifE.comparelow(# 136 "Enum.frag.ml"(let(_k,_)=vin_k)# 136 "Enum.frag.ml")<=0then(* [v] is at or above the threshold. Keep all elements. *)eelse(* [v] is below the threshold. [v] must be discarded. *)filter_tree_enumlowre'|End->Endlethead(e:'vienum):# 145 "Enum.frag.ml"(key*_)# 145 "Enum.frag.ml"=matchewith|End->raiseNot_found|More(v,_,_)->vlettail(e:'vienum):'vienum=matchewith|End->raiseNot_found|More(_,r,e)->cat_tree_enumrelethead_opt(e:'vienum):# 155 "Enum.frag.ml"(key*_)# 155 "Enum.frag.ml"option=matchewith|End->None|More(v,_,_)->Somevlettail_opt(e:'vienum):'vienumoption=matchewith|End->None|More(_,r,e)->Some(cat_tree_enumre)(* [equal e1 e2] compares the enumerations [e1] and [e2]. *)(* In the map variant, [equal] takes an extra argument, [eq], which is used
to compare the data components of two values. In the set variant, this
argument is absent; there are no data components, and one can think of
[eq] as the constant function [true]. *)letrecequal# 172 "Enum.frag.ml"(eq)# 172 "Enum.frag.ml"(e1:_ienum)(e2:_ienum):bool=matche1,e2with|End,End->true|End,More_|More_,End->false|More(v1,r1,e1),More(v2,r2,e2)->compare_eltsv1v2=0&&# 182 "Enum.frag.ml"eq(# 182 "Enum.frag.ml"(let(_,_d)=v1in_d)# 182 "Enum.frag.ml")(# 182 "Enum.frag.ml"(let(_,_d)=v2in_d)# 182 "Enum.frag.ml")&&# 184 "Enum.frag.ml"equal# 184 "Enum.frag.ml"(eq)# 184 "Enum.frag.ml"(cat_tree_enumr1e1)(cat_tree_enumr2e2)(* [compare e1 e2] compares the enumerations [e1] and [e2] according to a
lexicographic ordering. *)(* In the map variant, [compare] takes an extra argument, [cmp], which is
used to compare the data components of two values. In the set variant,
this argument is absent; there are no data components, and one can think
of [cmp] as the constant function [0]. *)letreccompare# 194 "Enum.frag.ml"(cmp)# 194 "Enum.frag.ml"(e1:_ienum)(e2:_ienum):int=matche1,e2with|End,End->0|End,More_->-1|More_,End->1|More(v1,r1,e1),More(v2,r2,e2)->letc=compare_eltsv1v2inifc<>0thencelse# 206 "Enum.frag.ml"letc=cmp(# 206 "Enum.frag.ml"(let(_,_d)=v1in_d)# 206 "Enum.frag.ml")(# 206 "Enum.frag.ml"(let(_,_d)=v2in_d)# 206 "Enum.frag.ml")inifc<>0thencelse# 209 "Enum.frag.ml"compare# 209 "Enum.frag.ml"(cmp)# 209 "Enum.frag.ml"(cat_tree_enumr1e1)(cat_tree_enumr2e2)(* [to_seq] converts an enumeration to an OCaml sequence. *)letrecto_seq_node(e:'vienum):# 213 "Enum.frag.ml"(key*_)# 213 "Enum.frag.ml"Seq.node=matchewith|End->Seq.Nil|More(v,r,e)->Seq.Cons(v,fun()->to_seq_node(cat_tree_enumre))letto_seq(e:'vienum):# 220 "Enum.frag.ml"(key*_)# 220 "Enum.frag.ml"Seq.t=fun()->to_seq_nodee(* [elements] converts an enumeration back to a tree. *)(* It is the only function in this file that constructs a tree.
It exploits the construction function [join].
It performs no key comparisons. *)(* I believe, but have not proved, that, thanks to the remarkable
properties of [join], the time complexity of [elements] is only
O(log n). *)letrecelements(v:# 233 "Enum.frag.ml"(key*_)# 233 "Enum.frag.ml")(r:'vtree)(e:'vienum):'vtree=matchewith|End->joinleafvr|More(v',r',e)->elementsv(joinrv'r')eletelements(e:'vienum):'vtree=matchewith|End->leaf|More(v,r,e)->elementsvre(* Disjointness. *)exceptionNotDisjoint(* [filter_tree_disjoint low t e] returns the same result as
[filter_tree low t e], except that it raises [NotDisjoint]
if the key [low] appears in its result. *)letrecfilter_tree_disjoint(low:key)(t:'vtree)(e:'vienum):'vienum=match# 256 "Enum.frag.ml"(t)# 256 "Enum.frag.ml"with|# 257 "Enum.frag.ml"TLeaf# 257 "Enum.frag.ml"->e|# 259 "Enum.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 260 "Enum.frag.ml"letc=E.compare(# 260 "Enum.frag.ml"(let(_k,_)=vin_k)# 260 "Enum.frag.ml")lowinifc=0thenraiseNotDisjointelseifc<0thenfilter_tree_disjointlowreelsefilter_tree_disjointlowl(More(v,r,e))(* [filter_tree_enum_disjoint low r e] returns the same result as
[filter_tree_enum low r e], except that it raises [NotDisjoint]
if the key [low] appears in its result. *)letrecfilter_tree_enum_disjoint(low:key)(r:'vtree)(e:'vienum):'vienum=matchewith|More(v',r',e')->letc=E.comparelow(# 275 "Enum.frag.ml"(let(_k,_)=v'in_k)# 275 "Enum.frag.ml")inifc>0thenfilter_tree_enum_disjointlowr'e'elseifc=0thenraiseNotDisjointelsefilter_tree_disjointlowre|End->filter_tree_disjointlowre(* [disjoint_more_more v1 r1 e1 v2 r2 e2] requires [v1 < v2]. It determines
whether the enumerations [More (v1, r1, e1)] and [More (v2, r2, e2)] are
disjoint. It either returns [true] or raises [NotDisjoint]. *)(* This is Veldhuizen's leapfrog join algorithm. *)(* In the map variant, a type annotation is required, because this function
is polymorphic recursive. Indeed, the final recursive call exchanges the
two sides. *)letrecdisjoint_more_more# 297 "Enum.frag.ml":'a1'a2.'a1binding->'a1bindingtree->'a1bindingienum->'a2binding->'a2bindingtree->'a2bindingienum->bool# 302 "Enum.frag.ml"=funv1r1e1v2r2e2->assert(compare_eltsv1v2<0);(* Skip past [v2] in the enumeration [e1]. *)(* If [v2] appears in [e1], fail. *)lete1=filter_tree_enum_disjoint(# 306 "Enum.frag.ml"(let(_k,_)=v2in_k)# 306 "Enum.frag.ml")r1e1inmatche1with|End->(* If [e1] is now empty, we are done. *)true|More(v1,r1,e1)->(* If [e1] is nonempty, then its front value [v1] must be greater than
[v2]. Exchange the roles of the two enumerations and continue. *)assert(compare_eltsv2v1<0);disjoint_more_morev2r2e2v1r1e1(* [disjoint e1 e2] determines whether the enumerations [e1] and [e2] are
disjoint. *)letdisjoint(e1:_ienum)(e2:_ienum):bool=matche1,e2with|End,_|_,End->true|More(v1,r1,e1),More(v2,r2,e2)->letc=compare_eltsv1v2inifc=0thenfalseelsetryifc<0thendisjoint_more_morev1r1e1v2r2e2elsedisjoint_more_morev2r2e2v1r1e1withNotDisjoint->false(* [length e] computes the length of the enumeration [e]. If we have
a constant-time [cardinal] function on sets, then its complexity
is logarithmic. Otherwise, its complexity is linear. *)letreclength_auxaccu(e:'vienum):int=matchewith|End->accu|More(_,r,e)->length_aux(accu+cardinalr+1)elet[@inline]length(e:'vienum):int=length_aux0eend(* Enum *)(* -------------------------------------------------------------------------- *)(* Enumerations in reverse (decreasing order). *)(* I would rather avoid this code duplication, but we must provide at least
[to_rev_seq], for compatibility with OCaml's Set library. *)moduleRevEnum=struct(* In the enumeration [More (e, l, v)], we have [e < l < v], but the
enumeration is consumed (by the user) from the right to the left,
so [v] is produced first, followed with the elements of the tree
[l], followed with the elements of the enumeration [e]. *)type'vienum=|End|Moreof'vienum*'vtree*'vletempty:'vienum=End(* [cat_enum_tree e t] concatenates the enumeration [e] in front of
the tree [t]. It requires [e < t]. *)(* This function corresponds to [snoc_enum] in OCaml's Set library. *)letreccat_enum_tree(e:'vienum)(t:'vtree):'vienum=match# 381 "Enum.frag.ml"(t)# 381 "Enum.frag.ml"with|# 382 "Enum.frag.ml"TLeaf# 382 "Enum.frag.ml"->e|# 384 "Enum.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 385 "Enum.frag.ml"cat_enum_tree(More(e,l,v))r(* [enum] converts a tree to an enumeration. *)let[@inline]enum(t:'vtree):'vienum=cat_enum_treeemptyt(* [to_seq] converts an enumeration to an OCaml sequence. *)letrecto_seq_node(e:'vienum):# 394 "Enum.frag.ml"(key*_)# 394 "Enum.frag.ml"Seq.node=matchewith|End->Seq.Nil|More(e,l,v)->Seq.Cons(v,fun()->to_seq_node(cat_enum_treeel))(* let to_seq (e : enum) : key Seq.t = *)(* fun () -> to_seq_node e *)end# 1 "Compare.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Comparison. *)(* Instead of using enumerations of the trees [t1] and [t2], one could perform
a recursive traversal of [t1], while consuming an enumeration of [t2]. I
have benchmarked this variant: it allocates less memory, and can be faster,
but can also be about twice slower. *)letcompare# 22 "Compare.frag.ml"(cmp)# 22 "Compare.frag.ml"(t1:# 22 "Compare.frag.ml"(key*_)tree# 22 "Compare.frag.ml")(t2:# 22 "Compare.frag.ml"(key*_)tree# 22 "Compare.frag.ml"):int=# 26 "Compare.frag.ml"Enum.(compare# 26 "Compare.frag.ml"(cmp)# 26 "Compare.frag.ml"(enumt1)(enumt2))# 1 "Equal.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Equality. *)(* Equality of sets can be implemented in several ways. E.g., [equal t1 t2]
could be implemented in one line by [subset t1 t2 && subset t2 t1] or also
in one line by [is_empty (xor t1 t2)]. (The latter idea could be optimized,
so as to avoid actually constructing the tree [xor t1 t2] in memory.) Some
experiments suggest that either of these approaches is more expensive than
the following approach, which compares two enumerations. Furthermore, this
approach works for both sets and maps. *)(* In weight-balanced trees, the weight of a tree can be determined in
constant time. This yields a fast path: if the weights and [t1] and [t2]
differ, then they cannot possibly be equal. In height-balanced trees, the
[weight] function returns a constant value, so this fast path is
disabled. *)letequal# 31 "Equal.frag.ml"(eq)# 31 "Equal.frag.ml"t1t2=# 35 "Equal.frag.ml"weightt1=weightt2&&(* fast path *)Enum.(equal# 36 "Equal.frag.ml"(eq)# 36 "Equal.frag.ml"(enumt1)(enumt2))# 1 "Union.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Union. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 96 "Union.frag.ml"(* -------------------------------------------------------------------------- *)(* The map variant. *)(* In accordance with the API of OCaml's Map library, [union] expects a
function [f], which specifies how two values must be combined.
Furthermore, the internal functions [union1] and [union] expect a
Boolean flag [flip], which indicates whether the arguments of [f]
should be exchanged. *)(* [union1] can be viewed as a generalization of [add] and [replace]
where the manner in which the existing element and the new element
must be combined is determined by the parameters [flip] and [f].
It can also be viewed as a special case of [union] where the first
map is a singleton. *)(* [union1] assumes that [t1] is [singleton (k1, d1)]. Carrying this
extra parameter lets us save one allocation in the base case
where the key [k1] does not appear in the tree [t2]. *)letrecunion1(flip:bool)(f:key->'a->'a->'aoption)(k1:key)(d1:'a)(t1:'abindingtree)(t2:'abindingtree):'abindingtree=match# 121 "Union.frag.ml"(t2)# 121 "Union.frag.ml"with|# 122 "Union.frag.ml"TLeaf# 122 "Union.frag.ml"->(* This is equivalent to [singleton (k1, d1)]. *)t1|# 125 "Union.frag.ml"TNode{l=l2;k=_k;d=_d;r=r2;_}->letv2=(_k,_d)in# 126 "Union.frag.ml"let(k2,d2)=v2inletc=E.comparek1k2inifc=0thenletk=k2inmatch# 130 "Union.frag.ml"(ifflipthenfkd2d1elsefkd1d2)# 130 "Union.frag.ml"with|None->join2_siblingsl2r2|Somed->ifd==d2thent2elseletv2=(k,d)injoin_siblingsl2v2r2elseifc<0thenletl'2=union1flipfk1d1t1l2inifl2==l'2thent2elsejoin_quasi_siblingsl'2v2r2elseletr'2=union1flipfk1d1t1r2inifr2==r'2thent2elsejoin_quasi_siblingsl2v2r'2(* Re-package [union1] to take [(k1, d1)] as a pair. *)let[@inline]union1flipf(k1,d1)t1t2=union1flipfk1d1t1t2(* [union] does not offer a physical equality guarantee about its result.
(This does not seem to be possible. One would need to require [f] to
preserve physical equality, but it is impossible to predict which
argument of [f] should be favored.) *)(* As in the set variant, we try to preserve physical equality with the
second argument, which is likely to be the larger tree. *)letrecunion(flip:bool)(f:key->'a->'a->'aoption)(t1:'abindingtree)(t2:'abindingtree):'abindingtree=match# 160 "Union.frag.ml"(t1)# 160 "Union.frag.ml",# 160 "Union.frag.ml"(t2)# 160 "Union.frag.ml"with|# 161 "Union.frag.ml"TLeaf# 161 "Union.frag.ml",_->t2|_,# 163 "Union.frag.ml"TLeaf# 163 "Union.frag.ml"->t1|# 165 "Union.frag.ml"TNode{l=l1;k=_k1;d=_d1;r=r1;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->letv1=(_k1,_d1)andv2=(_k2,_d2)in# 166 "Union.frag.ml"if# 166 "Union.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 166 "Union.frag.ml"thenunion1flipfv1t1t2elseif# 167 "Union.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 167 "Union.frag.ml"thenunion1(notflip)fv2t2t1elselet(k2,d2)=v2inletl1,od1,r1=splitk2t1inletl=unionflipfl1l2andr=unionflipfr1r2inmatchod1with|None->letv=v2inifl==l2&&r==r2thent2elsejoinlvr|Somed1->letk=k2inmatch# 179 "Union.frag.ml"(ifflipthenfkd2d1elsefkd1d2)# 179 "Union.frag.ml"with|None->join2lr|Somed->ifl==l2&&d==d2&&r==r2thent2elseletv=(k,d)injoinlvr(* The toplevel wrapper tests which of the two arguments seems larger. This
guarantees that we split the smaller tree. (As in the set variant, this
test is performed just once at the top level, not at every level.) *)(* The fast path, based on the test [t1 == t2], disappears in the map
variant. It would be sound if we could require [f x x = Some x]
for all [x]. *)letunionft1t2=ifseems_smallert1t2thenletflip=falseinunionflipft1t2elseletflip=trueinunionflipft2t1(* In the [merge] functions, we assume that [f None None] is [None], and
never actually evaluate [f None None]. *)(* [merge_no_left] is the special case of [merge] where the left-hand tree
[t1] is empty. *)letrecmerge_no_leftft2=match# 210 "Union.frag.ml"(t2)# 210 "Union.frag.ml"with|# 211 "Union.frag.ml"TLeaf# 211 "Union.frag.ml"->leaf|# 213 "Union.frag.ml"TNode{l=l2;k=_k;d=_d;r=r2;_}->letv2=(_k,_d)in# 214 "Union.frag.ml"let(k2,d2)=v2inletk=k2andod1=Noneandod2=Somed2inojoin(merge_no_leftfl2)k(fkod1od2)(merge_no_leftfr2)(* [merge_no_right] is the special case of [merge] where the right-hand
tree [t2] is empty. *)letrecmerge_no_rightft1=match# 224 "Union.frag.ml"(t1)# 224 "Union.frag.ml"with|# 225 "Union.frag.ml"TLeaf# 225 "Union.frag.ml"->leaf|# 227 "Union.frag.ml"TNode{l=l1;k=_k;d=_d;r=r1;_}->letv1=(_k,_d)in# 228 "Union.frag.ml"let(k1,d1)=v1inletk=k1andod1=Somed1andod2=Noneinojoin(merge_no_rightfl1)k(fkod1od2)(merge_no_rightfr1)(* [merge] does not attempt to preserve physical equality. *)(* As soon as we discover that one of the two arguments is an empty tree,
we switch to [merge_no_left] or [merge_no_right]. This should be more
efficient, and makes the code simpler. *)letrecmergeft1t2=match# 241 "Union.frag.ml"(t1)# 241 "Union.frag.ml",# 241 "Union.frag.ml"(t2)# 241 "Union.frag.ml"with|# 242 "Union.frag.ml"TLeaf# 242 "Union.frag.ml",# 242 "Union.frag.ml"TLeaf# 242 "Union.frag.ml"->leaf|# 244 "Union.frag.ml"TLeaf# 244 "Union.frag.ml",_->merge_no_leftft2|_,# 246 "Union.frag.ml"TLeaf# 246 "Union.frag.ml"->merge_no_rightft1|# 248 "Union.frag.ml"TNode{l=l1;k=_k1;d=_d1;r=r1;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->letv1=(_k1,_d1)andv2=(_k2,_d2)in# 249 "Union.frag.ml"ifseems_smallert1t2then(* Split the smaller tree, namely [t1]. *)let(k2,d2)=v2inletk=k2inletl1,od1,r1=splitk2t1inletod2=Somed2inojoin(mergefl1l2)k(fkod1od2)(mergefr1r2)else(* Split the smaller tree, namely [t2]. *)let(k1,d1)=v1inletk=k1inletod1=Somed1inletl2,od2,r2=splitk1t2inojoin(mergefl1l2)k(fkod1od2)(mergefr1r2)(* In the map variant, [override] is [union] with priority to the right-hand
argument. It is not commutative. It is used internally; for example, the
functions [of_array] and [add_seq] rely on it. *)letoverridet1t2=union(fun_k_v1v2->Somev2)t1t2# 1 "Inter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Intersection. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 89 "Inter.frag.ml"(* -------------------------------------------------------------------------- *)(* The map variant. *)(* Like [union], [inter] expects a function [f], which specifies how two
values must be combined. In contrast with [union], [inter] admits a more
general type, where the two input maps and the output map can have three
distinct types of values. *)(* The physical equality tests, whose purpose was to preserve sharing, are
abandoned, because they impose undesirable type equality constraints. *)(* [inter1l] represents the special case where the left-hand tree is a
singleton [singleton (k1, d1)]. *)letinter1lf(k1,d1)t2=matchfind_optk1t2with|None->empty|Somed2->letk=k1inmatchfkd1d2with|None->empty|Somed->singleton(k,d)letrecinterft1t2=match# 117 "Inter.frag.ml"(t1)# 117 "Inter.frag.ml",# 117 "Inter.frag.ml"(t2)# 117 "Inter.frag.ml"with|# 118 "Inter.frag.ml"TLeaf# 118 "Inter.frag.ml",_|_,# 119 "Inter.frag.ml"TLeaf# 119 "Inter.frag.ml"->leaf|# 121 "Inter.frag.ml"TNode{l=l1;k=_k1;d=_d1;r=r1;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->letv1=(_k1,_d1)andv2=(_k2,_d2)in# 122 "Inter.frag.ml"if# 122 "Inter.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 122 "Inter.frag.ml"theninter1lfv1t2elselet(k2,d2)=v2inletl1,od1,r1=splitk2t1inletl=interfl1l2andr=interfr1r2inmatchod1with|None->join2lr|Somed1->letk=k2inletod=fkd1d2inojoinlkodr(* The toplevel wrapper tests which of the two arguments seems larger. This
guarantees that we split the smaller tree. (As in the set variant, this
test is performed just once at the top level, not at every level.) *)letinterft1t2=ifseems_smallert1t2theninterft1t2elseinter(funkd1d2->fkd2d1)t2t1(* We could avoid creating this closure, which adds overhead to
every call to [f], by duplicating the code of [inter1l] and
[inter] for the case where the arguments of [f] are flipped.
It would be great if the compiler would create a specialized
copy of [inter] for this situation. *)# 1 "Diff.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Difference. *)(* This is a simple, elegant version of [diff]. This version splits the
tree [t1]. (Set variant only.)
let rec diff (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _ ->
leaf
| _, LEAF ->
t1
| NODENODE(_, _, _, l2, k2, r2)
let l1, r1 = split13 k2 t1 in
let l = diff l1 l2
and r = diff r1 r2 in
join2 l r
*)(* This version of [diff] guarantees that if the result is equal to [t1]
then [t1] itself is returned. It splits the tree [t2]. *)letrecdiff(t1:# 37 "Diff.frag.ml"(key*_)tree# 37 "Diff.frag.ml")(t2:# 37 "Diff.frag.ml"(key*_)tree# 37 "Diff.frag.ml"):# 37 "Diff.frag.ml"(key*_)tree# 37 "Diff.frag.ml"=match# 38 "Diff.frag.ml"(t1)# 38 "Diff.frag.ml",# 38 "Diff.frag.ml"(t2)# 38 "Diff.frag.ml"with|# 39 "Diff.frag.ml"TLeaf# 39 "Diff.frag.ml",_->leaf|_,# 41 "Diff.frag.ml"TLeaf# 41 "Diff.frag.ml"->t1|# 43 "Diff.frag.ml"TNode{l=l1;k=_k1;d=_d1;r=r1;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->letv1=(_k1,_d1)andv2=(_k2,_d2)in# 44 "Diff.frag.ml"letk1=# 44 "Diff.frag.ml"(let(_k,_)=v1in_k)# 44 "Diff.frag.ml"in# 48 "Diff.frag.ml"if# 48 "Diff.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 48 "Diff.frag.ml"then(* [t1] is [singleton v1]. *)ifmemk1t2thenleafelset1elseif# 51 "Diff.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 51 "Diff.frag.ml"then(* [t2] is [singleton v2]. *)letk2=# 53 "Diff.frag.ml"(let(_k,_)=v2in_k)# 53 "Diff.frag.ml"inremovek2t1elseletl2,b,r2=splitk1t2inletl=diffl1l2andr=diffr1r2in# 59 "Diff.frag.ml"matchbwithSome_-># 60 "Diff.frag.ml"join2lr# 61 "Diff.frag.ml"|None-># 62 "Diff.frag.ml"ifl==l1&&r==r1thent1else(* preserve sharing *)joinlv1r# 1 "Xor.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Symmetric difference. *)(* This is a simple, elegant version of [xor]. (Set variant only.)
let rec xor (t1 : TREE) (t2 : TREE) : TREE =
match VIEW(t1), VIEW(t2) with
| LEAF, _ ->
t2
| _, LEAF ->
t1
| NODENODE(_, _, _, l2, k2, r2)
let l1, b, r1 = split k2 t1 in
let l = xor l1 l2
and r = xor r1 r2 in
if b then join2 l r else join l k2 r
*)(* Except in the case where [t1] or [t2] is empty, [xor t1 t2] cannot be
equal to [t1] or [t2]. So there is no need to attempt to preserve
sharing when constructing new nodes. *)letrecxor(t1:# 37 "Xor.frag.ml"(key*_)tree# 37 "Xor.frag.ml")(t2:# 37 "Xor.frag.ml"(key*_)tree# 37 "Xor.frag.ml"):# 37 "Xor.frag.ml"(key*_)tree# 37 "Xor.frag.ml"=match# 38 "Xor.frag.ml"(t1)# 38 "Xor.frag.ml",# 38 "Xor.frag.ml"(t2)# 38 "Xor.frag.ml"with|# 39 "Xor.frag.ml"TLeaf# 39 "Xor.frag.ml",_->t2|_,# 41 "Xor.frag.ml"TLeaf# 41 "Xor.frag.ml"->t1|# 43 "Xor.frag.ml"TNode{l=_;k=_k1;d=_d1;r=_;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->let_=(_k1,_d1)andv2=(_k2,_d2)in# 44 "Xor.frag.ml"ift1==t2thenleafelse(* fast path *)letk2=# 45 "Xor.frag.ml"(let(_k,_)=v2in_k)# 45 "Xor.frag.ml"inif# 46 "Xor.frag.ml"((match(l2)withTLeaf->true|_->false)&&(match(r2)withTLeaf->true|_->false))# 46 "Xor.frag.ml"then(* [t2] is [singleton v2]. *)ifmemk2t1thenremovek2t1elseadd_absentv2t1elseletl1,b,r1=splitk2t1inletl=xorl1l2andr=xorr1r2in# 56 "Xor.frag.ml"matchbwithSome_-># 57 "Xor.frag.ml"join2lr# 58 "Xor.frag.ml"|None-># 59 "Xor.frag.ml"joinlv2r# 1 "Disjoint.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* Disjointness. *)(* This simple version of [disjoint] has the same structure as [inter]. *)(* (Disabled.) (Set variant only.)
let rec disjoint (t1 : tree) (t2 : tree) : bool =
match VIEW(t1), VIEW(t2) with
| LEAF, _
| _, LEAF ->
true
| NODE(_, _, _), NODE(l2, k2, r2) ->
let l1, b, r1 = split k2 t1 in
not b && disjoint l1 l2 && disjoint r1 r2
*)(* The above code can be improved by adding a fast path (based on physical
equality), by adding special cases for singletons, and by using a copy of
[split] that does not construct the subtrees [l] and [r] if the Boolean
result [b] is true. *)(* I have played with these variations, but I find them to be consistently
slower than the following approach, which is based on [Enum.disjoint]. *)letdisjointt1t2=match# 41 "Disjoint.frag.ml"(t1)# 41 "Disjoint.frag.ml",# 41 "Disjoint.frag.ml"(t2)# 41 "Disjoint.frag.ml"with|# 42 "Disjoint.frag.ml"TLeaf# 42 "Disjoint.frag.ml",_|_,# 43 "Disjoint.frag.ml"TLeaf# 43 "Disjoint.frag.ml"->true(* fast path *)|_,_-># 49 "Disjoint.frag.ml"Enum.(disjoint(enumt1)(enumt2))(* I have also played with a version of [disjoint] that does not use [split],
therefore does not construct new trees; it does not allocate memory or
perform rebalancing work. It can be fast, but I believe that its worst-case
time complexity is not optimal. *)# 1 "Subset.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* Inclusion. *)(* -------------------------------------------------------------------------- *)(* The set variant. *)# 68 "Subset.frag.ml"(* -------------------------------------------------------------------------- *)(* The map variant. *)(* In the map variant, the name [subset] does not seem appropriate.
I prefer to name this function [sub]. *)(* [sub] is parameterized with a data comparison function [f]. *)(* The physical equality tests disappear, because they impose undesirable
type equality constraints. *)letrecsub(f:'a1->'a2->bool)(t1:'a1bindingtree)(t2:'a2bindingtree):bool=match# 83 "Subset.frag.ml"(t1)# 83 "Subset.frag.ml",# 83 "Subset.frag.ml"(t2)# 83 "Subset.frag.ml"with|# 84 "Subset.frag.ml"TLeaf# 84 "Subset.frag.ml",_->true|_,# 86 "Subset.frag.ml"TLeaf# 86 "Subset.frag.ml"->false|# 88 "Subset.frag.ml"TNode{l=l1;k=_k1;d=_d1;r=r1;_},TNode{l=l2;k=_k2;d=_d2;r=r2;_}->letv1=(_k1,_d1)andv2=(_k2,_d2)in# 89 "Subset.frag.ml"let(k1,d1)=v1inif# 90 "Subset.frag.ml"((match(l1)withTLeaf->true|_->false)&&(match(r1)withTLeaf->true|_->false))# 90 "Subset.frag.ml"thenbegin(* The tree [t1] is [singleton v1]. *)matchfind_optk1t2with|None->false|Somed2->fd1d2endelseweightt1<=weightt2&&(* fast path *)let(k2,d2)=v2inletl1,od1,r1=splitk2t1in(matchod1withNone->true|Somed1->fd1d2)&&subfl1l2&&subfr1r2# 1 "Map.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [map] and [filter_map]. *)(* The set variant is more complex because the function [f] is not
necessarily monotone. The map variant is simpler because its API is
less expressive; by construction, the key component is preserved
and the function [f] transforms only the data component, so the
transformation that is applied to the key-data pair is monotone. *)# 114 "Map.frag.ml"(* -------------------------------------------------------------------------- *)(* The map variant. *)(* [map] is defined in the same way as in OCaml's Map library. *)letrecmapft=match# 121 "Map.frag.ml"(t)# 121 "Map.frag.ml"with|# 122 "Map.frag.ml"TLeaf# 122 "Map.frag.ml"->leaf|# 124 "Map.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 125 "Map.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=mapflinlet(k,d)=vinletd'=fdinletr'=mapfrinletv'=(k,d')injoin_siblingsl'v'r'(* [mapi] is defined in the same way as in OCaml's Map library. *)letrecmapift=match# 136 "Map.frag.ml"(t)# 136 "Map.frag.ml"with|# 137 "Map.frag.ml"TLeaf# 137 "Map.frag.ml"->leaf|# 139 "Map.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 140 "Map.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=mapiflinlet(k,d)=vinletd'=fkdinletr'=mapifrinletv'=(k,d')injoin_siblingsl'v'r'(* [filter_map] is defined in the same way as in OCaml's Map library. *)letrecfilter_mapft=match# 151 "Map.frag.ml"(t)# 151 "Map.frag.ml"with|# 152 "Map.frag.ml"TLeaf# 152 "Map.frag.ml"->leaf|# 154 "Map.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 155 "Map.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=filter_mapflinlet(k,d)=vinletod'=fkdinletr'=filter_mapfrinojoinl'kod'r'# 1 "Filter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* [filter] is the same as in OCaml's Set library. *)(* Because [join] and [join2] have logarithmic cost, this implementation
of [filter] has linear time complexity. *)(* One could imagine a completely different implementation of [filter],
also with linear time complexity, as follows: copy the data to an
array, filter the array, reconstruct a tree. However, this approach
would require linear auxiliary storage, may be slower in practice, and
would be less effective at preserving sharing in scenarios where many
elements are retained. *)letrecfilterp(t:# 25 "Filter.frag.ml"(key*_)tree# 25 "Filter.frag.ml"):# 25 "Filter.frag.ml"(key*_)tree# 25 "Filter.frag.ml"=match# 26 "Filter.frag.ml"(t)# 26 "Filter.frag.ml"with|# 27 "Filter.frag.ml"TLeaf# 27 "Filter.frag.ml"->leaf|# 29 "Filter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 30 "Filter.frag.ml"(* Enforce left-to-right evaluation order. *)letl'=filterplinletkeep=# 32 "Filter.frag.ml"(let(_k,_d)=vinp_k_d)# 32 "Filter.frag.ml"inletr'=filterprinifkeepthenifl==l'&&r==r'thentelsejoinl'vr'elsejoin2l'r'(* [partition] is the same as in OCaml's Set library, with one extra
optimization: as in [filter], we attempt to preserve sharing where
possible. *)letrecpartitionp(t:# 43 "Filter.frag.ml"(key*_)tree# 43 "Filter.frag.ml"):# 43 "Filter.frag.ml"(key*_)tree# 43 "Filter.frag.ml"*# 43 "Filter.frag.ml"(key*_)tree# 43 "Filter.frag.ml"=match# 44 "Filter.frag.ml"(t)# 44 "Filter.frag.ml"with|# 45 "Filter.frag.ml"TLeaf# 45 "Filter.frag.ml"->leaf,leaf|# 47 "Filter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 48 "Filter.frag.ml"(* Enforce left-to-right evaluation order. *)letlt,lf=partitionplinletkeep=# 50 "Filter.frag.ml"(let(_k,_d)=vinp_k_d)# 50 "Filter.frag.ml"inletrt,rf=partitionprinifkeepthen(iflt==l&&rt==rthentelsejoinltvrt),join2lfrfelsejoin2ltrt,(iflf==l&&rf==rthentelsejoinlfvrf)# 1 "Conversions.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* -------------------------------------------------------------------------- *)(* [elements] converts a set, in linear time, to a sorted list. *)letrecto_list(t:# 17 "Conversions.frag.ml"(key*_)tree# 17 "Conversions.frag.ml")(k:# 17 "Conversions.frag.ml"(key*_)# 17 "Conversions.frag.ml"list):# 17 "Conversions.frag.ml"(key*_)# 17 "Conversions.frag.ml"list=match# 18 "Conversions.frag.ml"(t)# 18 "Conversions.frag.ml"with|# 19 "Conversions.frag.ml"TLeaf# 19 "Conversions.frag.ml"->k|# 21 "Conversions.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 22 "Conversions.frag.ml"to_listl(v::to_listrk)let[@inline]to_list(t:# 24 "Conversions.frag.ml"(key*_)tree# 24 "Conversions.frag.ml"):# 24 "Conversions.frag.ml"(key*_)# 24 "Conversions.frag.ml"list=to_listt[](* -------------------------------------------------------------------------- *)(* [to_seq] constructs the increasing sequence of the elements of the
tree [t]. *)letto_seq(t:# 32 "Conversions.frag.ml"(key*_)tree# 32 "Conversions.frag.ml"):# 32 "Conversions.frag.ml"(key*_)# 32 "Conversions.frag.ml"Seq.t=fun()->Enum.(to_seq_node(enumt))(* [to_seq_from low t] constructs the increasing sequence of the
elements [x] of the tree [t] such that [low <= x] holds. *)letto_seq_from(low:key)(t:# 38 "Conversions.frag.ml"(key*_)tree# 38 "Conversions.frag.ml"):# 38 "Conversions.frag.ml"(key*_)# 38 "Conversions.frag.ml"Seq.t=fun()->Enum.(to_seq_node(from_enumlowt))(* [to_rev_seq] constructs the decreasing sequence of the elements of
the tree [t]. *)letto_rev_seq(t:# 44 "Conversions.frag.ml"(key*_)tree# 44 "Conversions.frag.ml"):# 44 "Conversions.frag.ml"(key*_)# 44 "Conversions.frag.ml"Seq.t=fun()->RevEnum.(to_seq_node(enumt))(* -------------------------------------------------------------------------- *)(* [to_array_slice t a i] writes the elements of the tree [t] to the
array slice determined by the array [a] and the start index [i].
It returns the end index of this slice. *)letrecto_array_slice(t:# 53 "Conversions.frag.ml"(key*_)tree# 53 "Conversions.frag.ml")ai:int=assert(0<=i&&i+cardinalt<=Array.lengtha);match# 55 "Conversions.frag.ml"(t)# 55 "Conversions.frag.ml"with|# 56 "Conversions.frag.ml"TLeaf# 56 "Conversions.frag.ml"->i|# 58 "Conversions.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 59 "Conversions.frag.ml"leti=to_array_slicelaiina.(i)<-v;leti=i+1into_array_slicerai(* -------------------------------------------------------------------------- *)(* [to_array] converts a set, in linear time, to a sorted array. *)letto_array(t:# 68 "Conversions.frag.ml"(key*_)tree# 68 "Conversions.frag.ml"):# 68 "Conversions.frag.ml"(key*_)# 68 "Conversions.frag.ml"array=match# 69 "Conversions.frag.ml"(t)# 69 "Conversions.frag.ml"with|# 70 "Conversions.frag.ml"TLeaf# 70 "Conversions.frag.ml"->[||]|# 72 "Conversions.frag.ml"TNode{l=_;k=_k;d=_d;r=_;_}->letdummy=(_k,_d)in# 73 "Conversions.frag.ml"letn=cardinaltinleta=Array.makendummyinletj=to_array_sliceta0inassert(n=j);a(* -------------------------------------------------------------------------- *)(* [of_sorted_unique_array_slice] is available as part of the [BASE_SET]
or [BASE_MAP] signature. *)(* -------------------------------------------------------------------------- *)(* [of_sorted_unique_array a] requires the array [a] to be sorted and to
contain no duplicate elements. It converts this array, in linear time,
to a set. *)(* Because this function is unsafe (the user can provide an array that
is not sorted and/or that has duplicate elements), it is disabled.
[to_array] (below) is safe and is almost just as fast.
let[@inline] of_sorted_unique_array a =
of_sorted_unique_array_slice a 0 (Array.length a)
*)(* -------------------------------------------------------------------------- *)(* [of_array] converts an array to a set. This algorithm is adaptive. If the
array is sorted, then its time complexity is O(n). If the array is not
sorted, then its time complexity gradually degenerates to O(n.log n). *)(* Each run of consecutive increasing elements is converted to a set, in
linear time in the length of this run. Then, the union of these sets
is computed. *)(* [override] is [union] with priority to the right-hand argument. So,
in the map variant, if a key appears twice in the list, the rightmost
binding takes over. *)letof_arraya=letyieldaccuij=overrideaccu(of_sorted_unique_array_sliceaij)inArrayExtra.foreach_increasing_runcompare_eltsyieldemptya(* -------------------------------------------------------------------------- *)(* [of_list] converts a list to a set. It is adaptive. *)(* OCaml's Set library constructs a sorted list (using [List.sort_uniq]) and
converts it directly to a tree. Instead, we convert the list to an array
and use [of_array]. On random data, our approach seems slower by about 50%.
On sorted data, our approach can be 2x or 3x faster. One drawback of our
approach is that it requires linear auxiliary storage. *)letof_listxs=xs|>Array.of_list|>of_array(* -------------------------------------------------------------------------- *)(* [of_seq] converts a sequence to a set. It is adaptive. *)(* [of_seq] in OCaml's Set library is implemented using [add_seq], which
itself is naively implemented by iterated insertions, so its complexity
is O(n.log n), whereas it could be O(n). *)letof_seqxs=xs|>Array.of_seq|>of_array(* [add_seq] inserts a sequence into a set. *)letadd_seqxst=overridet(of_seqxs)# 1 "RandomAccess.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)(* The functions in this file assume that we have a constant-time [cardinal]
function. *)(* -------------------------------------------------------------------------- *)(* Access to an element, based on its index. *)(* [get] has logarithmic complexity. *)(* If [cardinal] requires linear time then this implementation of [get] has
quadratic time complexity, which is unacceptable. In that case, it is
preferable to just use [to_array], which has linear time complexity,
followed with [Array.get]. *)letrecget(t:# 27 "RandomAccess.frag.ml"(key*_)tree# 27 "RandomAccess.frag.ml")(i:int):# 27 "RandomAccess.frag.ml"(key*_)# 27 "RandomAccess.frag.ml"=assert(0<=i&&i<cardinalt);match# 29 "RandomAccess.frag.ml"(t)# 29 "RandomAccess.frag.ml"with|# 30 "RandomAccess.frag.ml"TLeaf# 30 "RandomAccess.frag.ml"->assertfalse|# 32 "RandomAccess.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 33 "RandomAccess.frag.ml"letcl=cardinallinifi=clthenvelseifi<clthengetlielsegetr(i-(cl+1))letget(t:# 41 "RandomAccess.frag.ml"(key*_)tree# 41 "RandomAccess.frag.ml")(i:int):# 41 "RandomAccess.frag.ml"(key*_)# 41 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<cardinaltthengettielsePrintf.sprintf"get: index %d is out of expected range [0, %d)"i(cardinalt)|>invalid_argelsefailwith"get: operation is not available"(* -------------------------------------------------------------------------- *)(* Discovering the index of an element, based on its value. *)(* [index] has logarithmic complexity. *)(* [index] is roughly analogous to [List.find_index], but has a different
type; [index] expects an element [x], whereas [List.find_index] expects
a predicate of type [elt -> bool]. *)(* We could offer [find_index] on sets, with linear time complexity, but
this seems pointless. The user can implement this function using an
enumeration, if she so wishes. *)letrecindex(i:int)(x:key)(t:# 66 "RandomAccess.frag.ml"(key*_)tree# 66 "RandomAccess.frag.ml"):int=match# 67 "RandomAccess.frag.ml"(t)# 67 "RandomAccess.frag.ml"with|# 68 "RandomAccess.frag.ml"TLeaf# 68 "RandomAccess.frag.ml"->raiseNot_found|# 70 "RandomAccess.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 71 "RandomAccess.frag.ml"letc=E.comparex(# 71 "RandomAccess.frag.ml"(let(_k,_)=vin_k)# 71 "RandomAccess.frag.ml")inifc<0thenindexixlelseleti=i+cardinallinifc=0thenielseindex(i+1)xrlet[@inline]indexxt=index0xtletindexxt=ifconstant_time_cardinalthenindexxtelsefailwith"index: operation is not available"(* -------------------------------------------------------------------------- *)(* Splitting by index -- in two parts. *)letreccut(t:# 94 "RandomAccess.frag.ml"(key*_)tree# 94 "RandomAccess.frag.ml")(i:int):# 94 "RandomAccess.frag.ml"(key*_)tree# 94 "RandomAccess.frag.ml"*# 94 "RandomAccess.frag.ml"(key*_)tree# 94 "RandomAccess.frag.ml"=assert(0<=i&&i<=cardinalt);ifi=0thenleaf,telseifi=cardinaltthent,leafelsematch# 101 "RandomAccess.frag.ml"(t)# 101 "RandomAccess.frag.ml"with|# 102 "RandomAccess.frag.ml"TLeaf# 102 "RandomAccess.frag.ml"->assertfalse|# 104 "RandomAccess.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 105 "RandomAccess.frag.ml"letcl=cardinallinifi<=clthenletll,lr=cutliinassert(lr!=l);ll,joinlrvrelse(* [cl < i] *)letrl,rr=cutr(i-(cl+1))inassert(rl!=r);joinlvrl,rrletcut(t:# 115 "RandomAccess.frag.ml"(key*_)tree# 115 "RandomAccess.frag.ml")(i:int):# 115 "RandomAccess.frag.ml"(key*_)tree# 115 "RandomAccess.frag.ml"*# 115 "RandomAccess.frag.ml"(key*_)tree# 115 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<=cardinaltthencuttielsePrintf.sprintf"cut: index %d is out of expected range [0, %d]"i(cardinalt)|>invalid_argelsefailwith"cut: operation is not available"(* -------------------------------------------------------------------------- *)(* Splitting by index -- in three parts. *)letreccut_and_get(t:# 130 "RandomAccess.frag.ml"(key*_)tree# 130 "RandomAccess.frag.ml")(i:int):# 130 "RandomAccess.frag.ml"(key*_)tree# 130 "RandomAccess.frag.ml"*# 130 "RandomAccess.frag.ml"(key*_)# 130 "RandomAccess.frag.ml"*# 130 "RandomAccess.frag.ml"(key*_)tree# 130 "RandomAccess.frag.ml"=assert(0<=i&&i<cardinalt);match# 132 "RandomAccess.frag.ml"(t)# 132 "RandomAccess.frag.ml"with|# 133 "RandomAccess.frag.ml"TLeaf# 133 "RandomAccess.frag.ml"->assertfalse|# 135 "RandomAccess.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 136 "RandomAccess.frag.ml"letcl=cardinallinifi=clthenl,v,relseifi<clthenletll,lv,lr=cut_and_getliinll,lv,joinlrvrelseletrl,rv,rr=cut_and_getr(i-(cl+1))injoinlvrl,rv,rrletcut_and_get(t:# 146 "RandomAccess.frag.ml"(key*_)tree# 146 "RandomAccess.frag.ml")(i:int):# 146 "RandomAccess.frag.ml"(key*_)tree# 146 "RandomAccess.frag.ml"*# 146 "RandomAccess.frag.ml"(key*_)# 146 "RandomAccess.frag.ml"*# 146 "RandomAccess.frag.ml"(key*_)tree# 146 "RandomAccess.frag.ml"=ifconstant_time_cardinalthenif0<=i&&i<cardinaltthencut_and_gettielsePrintf.sprintf"cut_and_get: index %d is out of expected range [0, %d)"i(cardinalt)|>invalid_argelsefailwith"cut_and_get: operation is not available"# 1 "Iter.frag.ml"(******************************************************************************)(* *)(* Baby *)(* *)(* François Pottier, Inria Paris *)(* *)(* Copyright 2024--2024 Inria. All rights reserved. This file is *)(* distributed under the terms of the GNU Library General Public *)(* License, with an exception, as described in the file LICENSE. *)(* *)(******************************************************************************)letreciterf(t:# 13 "Iter.frag.ml"(key*_)tree# 13 "Iter.frag.ml")=match# 14 "Iter.frag.ml"(t)# 14 "Iter.frag.ml"with|# 15 "Iter.frag.ml"TLeaf# 15 "Iter.frag.ml"->()|# 17 "Iter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 18 "Iter.frag.ml"iterfl;# 18 "Iter.frag.ml"(let(_k,_d)=vinf_k_d)# 18 "Iter.frag.ml";iterfrletrecfoldf(t:# 20 "Iter.frag.ml"(key*_)tree# 20 "Iter.frag.ml")accu=match# 21 "Iter.frag.ml"(t)# 21 "Iter.frag.ml"with|# 22 "Iter.frag.ml"TLeaf# 22 "Iter.frag.ml"->accu|# 24 "Iter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 25 "Iter.frag.ml"foldfr(# 25 "Iter.frag.ml"(let(_k,_d)=vinf_k_d(foldflaccu))# 25 "Iter.frag.ml")letrecfor_allp(t:# 27 "Iter.frag.ml"(key*_)tree# 27 "Iter.frag.ml")=match# 28 "Iter.frag.ml"(t)# 28 "Iter.frag.ml"with|# 29 "Iter.frag.ml"TLeaf# 29 "Iter.frag.ml"->true|# 31 "Iter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 32 "Iter.frag.ml"(let(_k,_d)=vinp_k_d)# 32 "Iter.frag.ml"&&for_allpl&&for_allprletrecexistsp(t:# 34 "Iter.frag.ml"(key*_)tree# 34 "Iter.frag.ml")=match# 35 "Iter.frag.ml"(t)# 35 "Iter.frag.ml"with|# 36 "Iter.frag.ml"TLeaf# 36 "Iter.frag.ml"->false|# 38 "Iter.frag.ml"TNode{l=l;k=_k;d=_d;r=r;_}->letv=(_k,_d)in# 39 "Iter.frag.ml"(let(_k,_d)=vinp_k_d)# 39 "Iter.frag.ml"||existspl||existspr# 143 "UpperLayer.frag.ml"(* Our internal function [singleton] expects a pair [(k, d)], but the
public function [singleton] expects separate arguments [k] and [d]. *)let[@inline]singletonkd=singleton(k,d)(* In the map API, [to_list] is published under the name [bindings]. *)letbindings=to_list# 155 "UpperLayer.frag.ml"(* -------------------------------------------------------------------------- *)# 41 "W.cppo.ml"endendmodule[@inline]Make(E:OrderedType)=structmoduleSet=Set.Make(E)moduleMap=Map.Make(E)(* Because we have access to the concrete view of sets and maps, and because
we know that sets and maps use the same balancing scheme, we can copy the
balancing information (that is, the field [w]). We save the cost of
recomputing this information at each node. *)(* Because we use concrete data constructors (as opposed to smart
constructor functions), we can annotate these recursive functions with
[@tail_mod_cons], which presumably makes them faster. *)let[@tail_mod_cons]recdomainm=matchmwith|WeightMap.TLeaf->WeightSet.TLeaf|WeightMap.TNode{l;k;d;r;w}->ignored;letl=domainlinletv=kinWeightSet.TNode{l;v;r=domainr;w}let[@tail_mod_cons]recliftfs=matchswith|WeightSet.TLeaf->WeightMap.TLeaf|WeightSet.TNode{l;v;r;w}->(* Enforce left-to-right evaluation order. *)letl=liftflinletk=vinletd=fkinWeightMap.TNode{l;k;d;r=liftfr;w}end