1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)type('a,_)node=|Empty:('a,[<`Empty|`Item_or_empty|`Any])node|Item:{lo:Z.t;hi:Z.t;elt:'a;}->('a,[<`Non_empty|`Item|`Item_or_empty|`Any])node|Node:{lo:Z.t;hi:Z.t;mask:Z.t;zero:'atree;one:'atree;}->('a,[<`Non_empty|`Node|`Any])nodeand'atree=('a,[`Non_empty])nodeand'at=('a,[`Any])nodeand'aitem=('a,[`Item])nodeand'aitem_opt=('a,[`Item_or_empty])nodeand'abranch=('a,[`Node])nodetype('a,'b)continuation=|Root:('a,[<`Root|`Any])continuation|Right:'apath*'atree->('a,[<`Right|`Any])continuationand'apath=('a,[`Any])continuationand'aright=('a,[`Right])continuation(* most significant bit of difference betweeb two key *)letdiffkk'=Z.numbits(Z.logxorkk')letany:'atree->'at=function(Item_|Node_)ast->tletiter:('aitem->unit)->'at->unit=letreciter:('aitem->unit)->'atree->unit=funft->matchtwith|Item_asitem->fitem|Node{zero;one;_}->iterfzero;iterfoneinfunft->matchtwithEmpty->()|(Item_|Node_)astree->iterftreeletrev_iter:('aitem->unit)->'at->unit=letrecrev_iter:('aitem->unit)->'atree->unit=funft->matchtwith|Item_asitem->fitem|Node{zero;one;_}->rev_iterfone;rev_iterfzeroinfunft->matchtwithEmpty->()|(Item_|Node_)astree->rev_iterftreeletfold:('aitem->'b->'b)->'b->'at->'b=letrecfold:('aitem->'b->'b)->'b->'atree->'b=funfacct->matchtwith|Item_asitem->fitemacc|Node{zero;one;_}->foldf(foldfacczero)oneinfunfacct->matchtwithEmpty->acc|(Item_|Node_)astree->foldfacctreeletrev_fold:('aitem->'b->'b)->'b->'at->'b=letrecrev_fold:('aitem->'b->'b)->'b->'atree->'b=funfacct->matchtwith|Item_asitem->fitemacc|Node{zero;one;_}->rev_foldf(rev_foldfaccone)zeroinfunfacct->matchtwith|Empty->acc|(Item_|Node_)astree->rev_foldfacctreeletis_empty:'at->bool=function|Empty->true|Item_|Node_->falseletlower_bound:'atree->Z.t=function|Item{lo;_}|Node{lo;_}->loletupper_bound:'atree->Z.t=function|Item{hi;_}|Node{hi;_}->hiletrecis_empty_between_left:Z.t->Z.t->'atree->bool=funlo'hi'tree->matchtreewith|Item_->false|Node{lo;zero;one;_}->Z.ltlolo'&&is_empty_between_choicelo'hi'zerooneandis_empty_between_right:Z.t->Z.t->'atree->bool=funlo'hi'tree->matchtreewith|Item_->false|Node{hi;zero;one;_}->Z.lthi'hi&&is_empty_between_choicelo'hi'zerooneandis_empty_between_choice:Z.t->Z.t->'atree->'atree->bool=funlo'hi'zeroone->letub=upper_boundzeroinifZ.leqhi'ubthenis_empty_between_leftlo'hi'zeroelseletlb=lower_boundoneinifZ.leqlblo'thenis_empty_between_rightlo'hi'oneelseZ.ltublo'&&Z.lthi'lbletis_empty_between:Z.t->Z.t->'at->bool=funlo'hi't->matchtwith|Empty->true|Item{lo;hi;_}->Z.lthi'lo||Z.lthilo'|Node{lo;hi;zero;one;_}->Z.lthi'lo||Z.lthilo'||is_empty_between_choicelo'hi'zerooneletmap:('aitem->'b)->'at->'bt=letrecmap:('aitem->'b)->'atree->'btree=funft->matchtwith|Item{lo;hi;_}asitem->Item{lo;hi;elt=fitem}|Node{lo;hi;mask;zero;one}->Node{lo;hi;mask;zero=mapfzero;one=mapfone}infunft->matchtwith|Empty->Empty|(Item_|Node_)astree->any(mapftree)letbindings:'at->'aitemlist=letrecbindings:'atree->'aitemlist->'aitemlist=funtacc->matchtwith|Item_asitem->item::acc|Node{zero;one;_}->bindingszero(bindingsoneacc)infunctionEmpty->[]|(Item_|Node_)astree->bindingstree[]letmem:Z.t->'at->bool=letrecmem:Z.t->'atree->bool=funindextree->matchtreewith|Item_->true|Node{zero;one;_}->mem_choiceindexzerooneandmem_choice:Z.t->'atree->'atree->bool=funindexzeroone->letub=upper_boundzeroinifZ.leqindexubthenmemindexzeroelseletlb=lower_boundoneinZ.leqlbindex&&memindexoneinfunindext->matchtwith|Empty->false|Item{lo;hi;_}->Z.leqloindex&&Z.leqindexhi|Node{lo;hi;zero;one;_}->Z.leqloindex&&Z.leqindexhi&&mem_choiceindexzerooneletfind_opt:Z.t->'at->'aitem_opt=letrecfind:Z.t->'atree->'aitem_opt=funindextree->matchtreewith|Item_asitem->item|Node{zero;one;_}->find_choiceindexzerooneandfind_choice:Z.t->'atree->'atree->'aitem_opt=funindexzeroone->letub=upper_boundzeroinifZ.leqindexubthenfindindexzeroelseletlb=lower_boundoneinifZ.leqlbindexthenfindindexoneelseEmptyinfunindext->matchtwith|Empty->Empty|Item{lo;hi;_}asitem->ifZ.ltindexlo||Z.lthiindexthenEmptyelseitem|Node{lo;hi;zero;one;_}->ifZ.ltindexlo||Z.lthiindexthenEmptyelsefind_choiceindexzerooneletnone:'aitem_opt=Emptyletfind:Z.t->'at->'aitem=funindext->matchfind_optindextwith|Empty->raiseNot_found|Item_asitem->itemletchoose:'at->'aitem=letrecchoose:'atree->'aitem=function|Item_asitem->item|Node{zero;_}->choosezeroinfunctionEmpty->raiseNot_found|(Item_|Node_)astree->choosetreeletempty:'at=Emptyletsingleton:lo:Z.t->hi:Z.t->'a->'at=fun~lo~hielt->ifZ.lthilothenraise(Invalid_argument"singleton");Item{lo;hi;elt}letrecjoin:stich:('aitem->'aitem->'aoption)option->'atree->'atree->'atree=letjoin_make_nodes:stich:('aitem->'aitem->'aoption)option->lo:Z.t->hi:Z.t->mask:Z.t->zero:'atree->one:'atree->'atree=letrecunion_eq_make_nodes_rebuilt_left:'abranchlist->'atree->Z.t->'atree=funpath0rightmost1hi1->matchpath0with|[]->rightmost1|Node{lo=lo0;mask=mask0;zero=zero0;_}::path0->union_eq_make_nodes_rebuilt_leftpath0(Node{lo=lo0;hi=hi1;mask=mask0;zero=zero0;one=rightmost1;})hi1inletrecjoin_make_nodes_rebuilt_right:'atree->Z.t->'abranchlist->'atree=funleftmost0lo0path1->matchpath1with|[]->leftmost0|Node{hi=hi1;mask=mask1;one=one1;_}::path1->join_make_nodes_rebuilt_right(Node{lo=lo0;hi=hi1;mask=mask1;zero=leftmost0;one=one1;})lo0path1inletrecjoin_make_nodes_leftmost:stich:('aitem->'aitem->'aoption)->lo:Z.t->hi:Z.t->mask:Z.t->zero:'atree->one:'atree->'aitem->'abranchlist->'atree->'abranchlist->'atree=fun~stich~lo~hi~mask~zero~one(Item{lo=lo0;_}asrightmost0)path0leftmost1path1->matchleftmost1with|Item{hi=hi1;_}asleftmost1->(matchstichrightmost0leftmost1with|None->Node{lo;hi;mask;zero;one}|Someelt->(letzero=union_eq_make_nodes_rebuilt_leftpath0(Item{lo=lo0;hi=hi1;elt})hi1inmatchpath1with|[]->zero|Node{one=one1;_}::path1->Node{lo;hi;mask;zero;one=join_make_nodes_rebuilt_rightone1(lower_boundone1)path1;}))|Node{zero=zero0;_}asnode1->join_make_nodes_leftmost~stich~lo~hi~mask~zero~onerightmost0path0zero0(node1::path1)inletrecjoin_make_nodes_rightmost:stich:('aitem->'aitem->'aoption)->lo:Z.t->hi:Z.t->mask:Z.t->zero:'atree->one:'atree->'atree->'abranchlist->'atree=fun~stich~lo~hi~mask~zero~onerightmost0path0->matchrightmost0with|Item_asitem0->join_make_nodes_leftmost~stich~lo~hi~mask~zero~oneitem0path0one[]|Node{one=one1;_}asnode0->join_make_nodes_rightmost~stich~lo~hi~mask~zero~oneone1(node0::path0)infun~stich~lo~hi~mask~zero~one->matchstichwith|SomestichwhenZ.equalZ.one(Z.sub(lower_boundone)(upper_boundzero))->join_make_nodes_rightmost~stich~lo~hi~mask~zero~onezero[]|Some_|None->Node{lo;hi;mask;zero;one}inletjoin_disjoint_items:stich:('aitem->'aitem->'aoption)option->'aitem->'aitem->'atree=fun~stich(Item{lo=lo0;_}asitem0)(Item{lo=lo1;hi=hi1;_}asitem1)->join_make_nodes~stich~lo:lo0~hi:hi1~mask:(Z.logandlo1(Z.shift_leftZ.minus_one(difflo0lo1-1)))~zero:item0~one:item1andjoin_disjoint_item_node:stich:('aitem->'aitem->'aoption)option->'aitem->'abranch->'atree=fun~stich(Item{lo=lo0;_}asitem0)(Node{hi=hi1;mask=mask1;zero=zero1;one=one1;_}asnode1)->letn=difflo0mask1inletz'=Z.trailing_zerosmask1inifz'+1>=nthenjoin_make_nodes~stich~lo:lo0~hi:hi1~mask:mask1~zero:(join~stichitem0zero1)~one:one1elsejoin_make_nodes~stich~lo:lo0~hi:hi1~mask:(Z.logandmask1(Z.shift_leftZ.minus_one(n-1)))~zero:item0~one:node1andjoin_disjoint_node_item:stich:('aitem->'aitem->'aoption)option->'abranch->'aitem->'atree=fun~stich(Node{lo=lo0;mask=mask0;zero=zero0;one=one0;_}asnode0)(Item{lo=lo1;hi=hi1;_}asitem1)->letn=diffmask0lo1andz=Z.trailing_zerosmask0inifz>=nthenjoin_make_nodes~stich~lo:lo0~hi:hi1~mask:mask0~zero:zero0~one:(join~stichone0item1)elsejoin_make_nodes~stich~lo:lo0~hi:hi1~mask:(Z.logandlo1(Z.shift_leftZ.minus_one(n-1)))~zero:node0~one:item1andjoin_disjoint_nodes:stich:('aitem->'aitem->'aoption)option->'abranch->'abranch->'atree=fun~stich(Node{lo=lo0;mask=mask0;zero=zero0;one=one0;_}asnode0)(Node{hi=hi1;mask=mask1;zero=zero1;one=one1;_}asnode1)->letn=diffmask0mask1andz=Z.trailing_zerosmask0inifz>=nthenjoin_make_nodes~stich~lo:lo0~hi:hi1~mask:mask0~zero:zero0~one:(join~stichone0node1)elseletz'=Z.trailing_zerosmask1inifz'+1>=nthenjoin_make_nodes~stich~lo:lo0~hi:hi1~mask:mask1~zero:(join~stichnode0zero1)~one:one1elsejoin_make_nodes~stich~lo:lo0~hi:hi1~mask:(Z.logandmask1(Z.shift_leftZ.minus_one(n-1)))~zero:node0~one:node1infun~stichtree0tree1->match(tree0,tree1)with|(Item_asitem0),(Item_asitem1)->join_disjoint_items~stichitem0item1|(Item_asitem0),(Node_asnode1)->join_disjoint_item_node~stichitem0node1|(Node_asnode0),(Item_asitem1)->join_disjoint_node_item~stichnode0item1|(Node_asnode0),(Node_asnode1)->join_disjoint_nodes~stichnode0node1letjoin_left:stich:('aitem->'aitem->'aoption)option->'atree->'at->'atree=fun~stichtree0t1->matcht1with|Empty->tree0|(Item_|Node_)astree1->join~stichtree0tree1letjoin_right:stich:('aitem->'aitem->'aoption)option->'at->'atree->'atree=fun~sticht0tree1->matcht0with|Empty->tree1|(Item_|Node_)astree0->join~stichtree0tree1(* (* type mode =
| Left_right (** Left and right *)
| Left_acc (** Left and accumulator *)
| Acc_right (** Accumulator and right *) *)
type 'a overlap =
| Ll_Rl_Ru_Lu : [ `Four_endpoints ] overlap
(** Left starts before and ends after right.
\[ left \]
\[ right \]
*)
| Rl_Ll_Lu_Ru : [ `Four_endpoints ] overlap
(** Right starts before and ends after left.
\[ left \]
\[ right \]
*)
| Ll_Rl_Lu_Ru : [ `Four_endpoints ] overlap
(** Right starts and ends after left.
\[ left \]
\[ right \]
*)
| Rl_Ll_Ru_Lu : [ `Four_endpoints ] overlap
(** Left starts and ends after right.
\[ left \]
\[ right \]
*)
| LRl_Ru_Lu : [ `Three_endpoints ] overlap
(** Left ends after right.
\[ left \]
\[ right \]
*)
| LRl_Lu_Ru : [ `Three_endpoints ] overlap
(** Right ends after left.
\[ left \]
\[ right \]
*)
| Ll_Rl_LRu : [ `Three_endpoints ] overlap
(** Left starts before right.
\[ left \]
\[ right \]
*)
| Rl_Ll_LRu : [ `Three_endpoints ] overlap
(** Right starts before left.
\[ left \]
\[ right \]
*)
| LRl_LRu : [ `Two_endpoints ] overlap
(** Left and right are equal.
\[ left \]
\[ right \]
*)
type ('a, 'b) update =
| Left_overlay
: ('a, [< `Two_endpoints | `Three_endpoints | `Four_endpoints ]) update
| Right_overlay
: ('a, [< `Two_endpoints | `Three_endpoints | `Four_endpoints ]) update
| Merge_overlay :
'a
-> ('a, [< `Two_endpoints | `Three_endpoints | `Four_endpoints ]) update
(** Insert a single item ranging from first to last endpoints *)
| Split_FSL : 'a * 'a -> ('a, [< `Three_endpoints | `Four_endpoints ]) update
(** Insert one item between first and second endpoints, then one item between second and last endpoints. *)
| Split_FPL : 'a * 'a -> ('a, [< `Three_endpoints | `Four_endpoints ]) update
(** Insert one item between first and penultimate endpoints, then one item between penultimate and last endpoints. *)
| Split_FSTL : 'a * 'a * 'a -> ('a, [< `Four_endpoints ]) update
(** Insert three items between the four endpoints. *)
type 'a update_handler = {
f : 'k. 'k overlap -> 'a item -> 'a item -> ('a, 'k) update;
}
[@@unboxed]
let union_update : 'a update_handler -> 'a t -> 'a t -> 'a t =
let union_update_overlap_items_ordered :
'a update_handler -> 'a item -> 'a item -> 'a tree =
fun { f = update } (Item { lo = lo0; hi = hi0; elt = elt0 } as item0)
(Item { lo = lo1; hi = hi1; elt = elt1 } as item1) ->
if Z.equal lo0 lo1 then
if Z.equal hi0 hi1 then
match update LRl_LRu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
else if Z.lt hi0 hi1 then
match update LRl_Lu_Ru item0 item1 with
| Left_overlay -> Item { lo = lo0; hi = hi1; elt = elt0 }
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo0; hi = hi1; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi0; elt = eltf })
(Item { lo = hi0; hi = hi1; elt = elts })
else
match update LRl_Ru_Lu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> Item { lo = lo0; hi = hi0; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi1; elt = eltf })
(Item { lo = hi1; hi = hi0; elt = elts })
else if Z.equal hi0 hi1 then
match update Ll_Rl_LRu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> Item { lo = lo0; hi = hi0; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred lo1; elt = eltf })
(Item { lo = lo1; hi = hi1; elt = elts })
else if Z.lt hi0 hi1 then
match update Ll_Rl_Lu_Ru item0 item1 with
| Left_overlay -> Item { lo = lo0; hi = hi1; elt = elt0 }
| Right_overlay -> Item { lo = lo0; hi = hi1; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo0; hi = hi1; elt }
| Split_FSL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred lo1; elt = eltf })
(Item { lo = lo1; hi = hi1; elt = elts })
| Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi0; elt = eltf })
(Item { lo = hi0; hi = hi1; elt = elts })
| Split_FSTL (eltf, eltm, eltl) ->
join
(join
(Item { lo = lo0; hi = Z.pred lo1; elt = eltf })
(Item { lo = lo1; hi = Z.pred hi0; elt = eltm }))
(Item { lo = hi0; hi = hi1; elt = eltl })
else
match update Ll_Rl_Ru_Lu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> Item { lo = lo0; hi = hi0; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
| Split_FSL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred lo1; elt = eltf })
(Item { lo = lo1; hi = hi0; elt = elts })
| Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi1; elt = eltf })
(Item { lo = hi1; hi = hi0; elt = elts })
| Split_FSTL (eltf, eltm, eltl) ->
join
(join
(Item { lo = lo0; hi = Z.pred lo1; elt = eltf })
(Item { lo = lo1; hi = Z.pred hi0; elt = eltm }))
(Item { lo = hi0; hi = hi1; elt = eltl })
in
let union_update_overlap_items_reverted :
'a update_handler -> 'a item -> 'a item -> 'a tree =
fun { f = update } (Item { lo = lo0; hi = hi0; elt = elt0 } as item0)
(Item { lo = lo1; hi = hi1; elt = elt1 } as item1) ->
if Z.equal lo0 lo1 then
if Z.equal hi0 hi1 then
match update LRl_LRu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
else if Z.lt hi0 hi1 then
match update LRl_Lu_Ru item0 item1 with
| Left_overlay -> Item { lo = lo0; hi = hi1; elt = elt0 }
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo0; hi = hi1; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi0; elt = eltf })
(Item { lo = hi0; hi = hi1; elt = elts })
else
match update LRl_Ru_Lu item0 item1 with
| Left_overlay -> item0
| Right_overlay -> Item { lo = lo0; hi = hi0; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo0; hi = hi0; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo0; hi = Z.pred hi1; elt = eltf })
(Item { lo = hi1; hi = hi0; elt = elts })
else if Z.equal hi0 hi1 then
match update Rl_Ll_LRu item0 item1 with
| Left_overlay -> Item { lo = lo1; hi = hi1; elt = elt0 }
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo1; hi = hi1; elt }
| Split_FSL (eltf, elts) | Split_FPL (eltf, elts) ->
join
(Item { lo = lo1; hi = Z.pred lo0; elt = eltf })
(Item { lo = lo0; hi = hi0; elt = elts })
else if Z.lt hi0 hi1 then
match update Rl_Ll_Lu_Ru item0 item1 with
| Left_overlay -> Item { lo = lo1; hi = hi1; elt = elt0 }
| Right_overlay -> item1
| Merge_overlay elt -> Item { lo = lo1; hi = hi1; elt }
| Split_FSL (eltf, elts) ->
join
(Item { lo = lo1; hi = Z.pred lo0; elt = eltf })
(Item { lo = lo0; hi = hi1; elt = elts })
| Split_FPL (eltf, elts) ->
join
(Item { lo = lo1; hi = Z.pred hi0; elt = eltf })
(Item { lo = hi0; hi = hi1; elt = elts })
| Split_FSTL (eltf, eltm, eltl) ->
join
(join
(Item { lo = lo1; hi = Z.pred lo0; elt = eltf })
(Item { lo = lo0; hi = Z.pred hi0; elt = eltm }))
(Item { lo = hi0; hi = hi1; elt = eltl })
else
match update Rl_Ll_Ru_Lu item0 item1 with
| Left_overlay -> Item { lo = lo1; hi = hi0; elt = elt0 }
| Right_overlay -> Item { lo = lo1; hi = hi0; elt = elt1 }
| Merge_overlay elt -> Item { lo = lo1; hi = hi0; elt }
| Split_FSL (eltf, elts) ->
join
(Item { lo = lo1; hi = Z.pred lo0; elt = eltf })
(Item { lo = lo0; hi = hi0; elt = elts })
| Split_FPL (eltf, elts) ->
join
(Item { lo = lo1; hi = Z.pred hi1; elt = eltf })
(Item { lo = hi1; hi = hi0; elt = elts })
| Split_FSTL (eltf, eltm, eltl) ->
join
(join
(Item { lo = lo1; hi = Z.pred lo0; elt = eltf })
(Item { lo = lo0; hi = Z.pred hi1; elt = eltm }))
(Item { lo = hi1; hi = hi0; elt = eltl })
in
let union_update_overlap_items :
'a update_handler -> 'a item -> 'a item -> bool -> 'a tree =
fun update item0 item1 swap ->
if swap then union_update_overlap_items_reverted update item1 item0
else union_update_overlap_items_ordered update item0 item1
in
let rec union_update_ordered :
'a update_handler -> 'a tree -> 'a tree -> bool -> 'a tree =
fun update tree0 tree1 swap ->
if tree0 == tree1 then tree0
else
let ub0 = upper_bound tree0 and lb1 = lower_bound tree1 in
if Z.lt ub0 lb1 then join tree0 tree1
else union_update_overlap update tree0 tree1 swap
and union_update_overlap :
'a update_handler -> 'a tree -> 'a tree -> bool -> 'a tree =
fun update tree0 tree1 swap ->
match (tree0, tree1) with
| (Item _ as item0), (Item _ as item1) ->
union_update_overlap_items update item0 item1 swap
| ( (Item { hi = hi0; _ } as item0),
(Node { zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq hi0 (upper_bound zero1) then
join (union_update_overlap update item0 zero1 swap) one1
else union_update_destruct_left update Root Root item0 node1 swap
| ( (Node { zero = zero0; one = one0; _ } as node0),
(Item { lo = lo1; _ } as item1) ) ->
if Z.leq (upper_bound one0) lo1 then
join zero0 (union_update_overlap update one0 item1 swap)
else union_update_destruct_left update Root Root node0 item1 swap
| ( (Node { hi = hi0; zero = zero0; one = one0; _ } as node0),
(Node { lo = lo1; zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq hi0 (upper_bound zero1) then
join (union_update_overlap update node0 zero1 swap) one1
else if Z.leq (lower_bound one0) lo1 then
join zero0 (union_update_overlap update one0 node1 swap)
else union_update_destruct_left update Root Root node0 node1 swap
and union_update_destruct_left :
'a update_handler ->
'a path ->
'a path ->
'a tree ->
'a tree ->
bool ->
'a tree =
fun update path0 path1 tree0 tree1 swap ->
match (tree0, tree1) with
| (Item _ as item0), (Item _ as item1) ->
union_update_destruct_right update path0 path1
(union_update_overlap_items update item0 item1 swap)
swap
| (Item _ as item0), Node { zero = zero1; one = one1; _ } ->
union_update_destruct_left update path0
(Right (path1, one1))
item0 zero1 swap
| Node { zero = zero0; one = one0; _ }, (Item { lo = lo1; _ } as item1) ->
if Z.leq (lower_bound one0) lo1 then
union_update_destruct_right update path0 path1
(join zero0 (union_update_overlap update one0 item1 swap))
swap
else if Z.lt (upper_bound zero0) lo1 then
union_update_destruct_right update path0 path1
(join zero0 (union_update_ordered update item1 one0 (not swap)))
swap
else
union_update_destruct_left update
(Right (path0, one0))
path1 zero0 item1 swap
| ( Node { zero = zero0; one = one0; _ },
(Node { lo = lo1; zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq (lower_bound one0) lo1 then
union_update_destruct_right update path0 path1
(join zero0 (union_update_overlap update one0 node1 swap))
swap
else if Z.lt (upper_bound zero0) lo1 then
union_update_destruct_right update path0 path1
(join zero0 (union_update_ordered update node1 one0 (not swap)))
swap
else
union_update_destruct_left update
(Right (path0, one0))
(Right (path1, one1))
zero0 zero1 swap
and union_update_destruct_right :
'a update_handler -> 'a path -> 'a path -> 'a tree -> bool -> 'a tree =
let rec union_update_destruct_right_single :
'a update_handler -> 'a right -> 'a tree -> bool -> 'a tree =
fun update (Right (path0, tree0)) acc swap ->
if Z.lt (upper_bound acc) (lower_bound tree0) then
union_update_destruct_right_single_disjoint path0 (join acc tree0)
else
match path0 with
| Root -> union_update_overlap update acc tree0 (not swap)
| Right _ as right0 ->
union_update_destruct_right_single update right0
(union_update_overlap update acc tree0 (not swap))
swap
and union_update_destruct_right_single_disjoint :
'a path -> 'a tree -> 'a tree =
fun path0 acc ->
match path0 with
| Root -> acc
| Right (path0, tree0) ->
union_update_destruct_right_single_disjoint path0 (join acc tree0)
and union_update_destruct_right_double :
'a update_handler -> 'a right -> 'a right -> 'a tree -> bool -> 'a tree
=
fun update (Right (_, tree0) as right0) (Right (_, tree1) as right1) acc
swap ->
if Z.lt (lower_bound tree1) (lower_bound tree0) then
union_update_destruct_right_double_ordered update right1 right0 acc
(not swap)
else
union_update_destruct_right_double_ordered update right0 right1 acc swap
and union_update_destruct_right_double_ordered :
'a update_handler -> 'a right -> 'a right -> 'a tree -> bool -> 'a tree
=
fun update (Right (path0, tree0)) (Right (path1, tree1) as right1) acc swap ->
if Z.lt (upper_bound tree0) (lower_bound tree1) then
union_update_destruct_right update path0 right1
(union_update_ordered update acc tree0 (not swap))
swap
else
union_update_destruct_left update path0 path1
(union_update_ordered update acc tree0 (not swap))
tree1 swap
in
fun update path0 path1 acc swap ->
match (path0, path1) with
| Root, Root -> acc
| Root, (Right _ as right1) ->
union_update_destruct_right_single update right1 acc (not swap)
| (Right _ as right0), Root ->
union_update_destruct_right_single update right0 acc swap
| (Right _ as right0), (Right _ as right1) ->
union_update_destruct_right_double update right0 right1 acc swap
in
fun update t0 t1 ->
match (t0, t1) with
| Empty, t1 -> t1
| t0, Empty -> t0
| ( ((Item { lo = lo0; _ } | Node { lo = lo0; _ }) as tree0),
((Item { lo = lo1; _ } | Node { lo = lo1; _ }) as tree1) ) ->
any
(if Z.lt lo1 lo0 then union_update_ordered update tree1 tree0 true
else union_update_ordered update tree0 tree1 false) *)letunion_update:?stich:('aitem->'aitem->'aoption)->('aitem->'aitem->'at)->'at->'at->'at=letunion_update_overlap_items:('aitem->'aitem->'at)->'aitem->'aitem->bool->'at=funupdateitem0item1swap->ifswapthenupdateitem1item0elseupdateitem0item1inletrecunion_update_ordered:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'atree->'atree->bool->'at=fun~stichupdatetree0tree1swap->iftree0==tree1thenanytree0elseletub0=upper_boundtree0andlb1=lower_boundtree1inifZ.ltub0lb1thenany(join~stichtree0tree1)elseunion_update_overlap~stichupdatetree0tree1swapandunion_update_overlap:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'atree->'atree->bool->'at=fun~stichupdatetree0tree1swap->match(tree0,tree1)with|(Item_asitem0),(Item_asitem1)->union_update_overlap_itemsupdateitem0item1swap|((Item{hi=hi0;_}asitem0),(Node{zero=zero1;one=one1;_}asnode1))->ifZ.leqhi0(upper_boundzero1)thenany(join_right~stich(union_update_overlap~stichupdateitem0zero1swap)one1)elseunion_update_destruct_left~stichupdateRootRootitem0node1swap|((Node{zero=zero0;one=one0;_}asnode0),(Item{lo=lo1;_}asitem1))->ifZ.leq(upper_boundone0)lo1thenany(join_left~stichzero0(union_update_overlap~stichupdateone0item1swap))elseunion_update_destruct_left~stichupdateRootRootnode0item1swap|((Node{hi=hi0;zero=zero0;one=one0;_}asnode0),(Node{lo=lo1;zero=zero1;one=one1;_}asnode1))->ifZ.leqhi0(upper_boundzero1)thenany(join_right~stich(union_update_overlap~stichupdatenode0zero1swap)one1)elseifZ.leq(lower_boundone0)lo1thenany(join_left~stichzero0(union_update_overlap~stichupdateone0node1swap))elseunion_update_destruct_left~stichupdateRootRootnode0node1swapandunion_update_destruct_left:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'apath->'apath->'atree->'atree->bool->'at=fun~stichupdatepath0path1tree0tree1swap->match(tree0,tree1)with|(Item_asitem0),(Item_asitem1)->union_update_destruct_right~stichupdatepath0path1(union_update_overlap_itemsupdateitem0item1swap)swap|(Item_asitem0),Node{zero=zero1;one=one1;_}->union_update_destruct_left~stichupdatepath0(Right(path1,one1))item0zero1swap|Node{zero=zero0;one=one0;_},(Item{lo=lo1;_}asitem1)->ifZ.leq(lower_boundone0)lo1thenunion_update_destruct_right_acc~stichupdatepath0path1(join_left~stichzero0(union_update_overlap~stichupdateone0item1swap))swapelseifZ.lt(upper_boundzero0)lo1thenunion_update_destruct_right_acc~stichupdatepath0path1(join_left~stichzero0(union_update_ordered~stichupdateitem1one0(notswap)))swapelseunion_update_destruct_left~stichupdate(Right(path0,one0))path1zero0item1swap|(Node{zero=zero0;one=one0;_},(Node{lo=lo1;zero=zero1;one=one1;_}asnode1))->ifZ.leq(lower_boundone0)lo1thenunion_update_destruct_right_acc~stichupdatepath0path1(join_left~stichzero0(union_update_overlap~stichupdateone0node1swap))swapelseifZ.lt(upper_boundzero0)lo1thenunion_update_destruct_right_acc~stichupdatepath0path1(join_left~stichzero0(union_update_ordered~stichupdatenode1one0(notswap)))swapelseunion_update_destruct_left~stichupdate(Right(path0,one0))(Right(path1,one1))zero0zero1swapandunion_update_destruct_right:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'apath->'apath->'at->bool->'at=fun~stichupdatepath0path1accswap->match(path0,path1)with|Root,Root->acc|Root,(Right_asright1)->union_update_destruct_right_single~stichupdateright1acc(notswap)|(Right_asright0),Root->union_update_destruct_right_single~stichupdateright0accswap|(Right_asright0),(Right_asright1)->union_update_destruct_right_double~stichupdateright0right1accswapandunion_update_destruct_right_acc:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'apath->'apath->'atree->bool->'at=fun~stichupdatepath0path1accswap->match(path0,path1)with|Root,Root->anyacc|Root,(Right_asright1)->union_update_destruct_right_single_acc~stichupdateright1acc(notswap)|(Right_asright0),Root->union_update_destruct_right_single_acc~stichupdateright0accswap|(Right_asright0),(Right_asright1)->union_update_destruct_right_double~stichupdateright0right1(anyacc)swapandunion_update_destruct_right_single:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'aright->'at->bool->'at=fun~stichupdate(Right(path0,tree0)asright0)accswap->matchaccwith|Empty->union_update_destruct_right_single_disjoint~stichpath0tree0|(Item_|Node_)asacc->union_update_destruct_right_single_acc~stichupdateright0accswapandunion_update_destruct_right_single_acc:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'aright->'atree->bool->'at=fun~stichupdate(Right(path0,tree0))accswap->ifZ.lt(upper_boundacc)(lower_boundtree0)thenunion_update_destruct_right_single_disjoint~stichpath0(join~stichacctree0)elsematchpath0with|Root->union_update_overlap~stichupdateacctree0(notswap)|Right_asright0->union_update_destruct_right_single~stichupdateright0(union_update_overlap~stichupdateacctree0(notswap))swapandunion_update_destruct_right_single_disjoint:stich:('aitem->'aitem->'aoption)option->'apath->'atree->'at=fun~stichpath0acc->matchpath0with|Root->anyacc|Right(path0,tree0)->union_update_destruct_right_single_disjoint~stichpath0(join~stichacctree0)andunion_update_destruct_right_double:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'aright->'aright->'at->bool->'at=fun~stichupdate(Right(_,tree0)asright0)(Right(_,tree1)asright1)accswap->ifZ.lt(lower_boundtree1)(lower_boundtree0)thenunion_update_destruct_right_double_ordered~stichupdateright1right0acc(notswap)elseunion_update_destruct_right_double_ordered~stichupdateright0right1accswapandunion_update_destruct_right_double_ordered:stich:('aitem->'aitem->'aoption)option->('aitem->'aitem->'at)->'aright->'aright->'at->bool->'at=fun~stichupdate(Right(path0,tree0))(Right(path1,tree1)asright1)accswap->ifZ.lt(upper_boundtree0)(lower_boundtree1)thenmatchaccwith|Empty->union_update_destruct_right_acc~stichupdatepath0right1tree0swap|(Item_|Node_)asacc->union_update_destruct_right~stichupdatepath0right1(union_update_ordered~stichupdateacctree0(notswap))swapelsematchaccwith|Empty->union_update_destruct_left~stichupdatepath0path1tree0tree1swap|(Item_|Node_)asacc->(matchunion_update_ordered~stichupdateacctree0(notswap)with|Empty->union_update_destruct_right~stichupdatepath0right1Emptyswap|(Item_|Node_)asacc->union_update_destruct_left~stichupdatepath0path1acctree1swap)infun?stichupdatet0t1->match(t0,t1)with|Empty,t1->t1|t0,Empty->t0|(((Item{lo=lo0;_}|Node{lo=lo0;_})astree0),((Item{lo=lo1;_}|Node{lo=lo1;_})astree1))->ifZ.ltlo1lo0thenunion_update_ordered~stichupdatetree1tree0trueelseunion_update_ordered~stichupdatetree0tree1false(* let union_eq : ('a item -> 'a item -> 'a) -> 'a t -> 'a t -> 'a t =
let union_eq_overlap_items :
('a item -> 'a item -> 'a) -> 'a item -> 'a item -> 'a tree =
fun merge (Item { lo = lo0; hi = hi0; elt = elt0 } as item0)
(Item { hi = hi1; elt = elt1; _ } as item1) ->
if Z.leq hi1 hi0 && elt0 == elt1 then item0
else Item { lo = lo0; hi = Z.max hi0 hi1; elt = merge item0 item1 }
in
let rec union_eq_ordered :
('a item -> 'a item -> 'a) -> 'a tree -> 'a tree -> 'a tree =
fun merge tree0 tree1 ->
(* invariant: lower_bound(tree0) <= lower_bound(tree1) *)
(* assert (Z.leq (lower_bound tree0) (lower_bound tree1)); *)
if tree0 == tree1 then tree0
else
let ub0 = upper_bound tree0 and lb1 = lower_bound tree1 in
if Z.lt ub0 lb1 then join tree0 tree1
else union_eq_overlap merge tree0 tree1
and union_eq_overlap :
('a item -> 'a item -> 'a) -> 'a tree -> 'a tree -> 'a tree =
fun merge tree0 tree1 ->
match (tree0, tree1) with
| (Item _ as item0), (Item _ as item1) ->
union_eq_overlap_items merge item0 item1
| ( (Item { hi = hi0; _ } as item0),
(Node { zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq hi0 (upper_bound zero1) then
join (union_eq_overlap merge item0 zero1) one1
else union_eq_destruct_left merge Root Root item0 node1
| ( (Node { zero = zero0; one = one0; _ } as node0),
(Item { lo = lo1; _ } as item1) ) ->
if Z.leq (upper_bound one0) lo1 then
join zero0 (union_eq_overlap merge one0 item1)
else union_eq_destruct_left merge Root Root node0 item1
| ( (Node { hi = hi0; zero = zero0; one = one0; _ } as node0),
(Node { lo = lo1; zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq hi0 (upper_bound zero1) then
join (union_eq_overlap merge node0 zero1) one1
else if Z.leq (lower_bound one0) lo1 then
join zero0 (union_eq_overlap merge one0 node1)
else union_eq_destruct_left merge Root Root node0 node1
and union_eq_destruct_left :
('a item -> 'a item -> 'a) ->
'a path ->
'a path ->
'a tree ->
'a tree ->
'a tree =
fun merge path0 path1 tree0 tree1 ->
match (tree0, tree1) with
| (Item _ as item0), (Item _ as item1) ->
union_eq_destruct_right merge path0 path1
(union_eq_overlap_items merge item0 item1)
| (Item _ as item0), Node { zero = zero1; one = one1; _ } ->
union_eq_destruct_left merge path0 (Right (path1, one1)) item0 zero1
| Node { zero = zero0; one = one0; _ }, (Item { lo = lo1; _ } as item1) ->
if Z.leq (lower_bound one0) lo1 then
union_eq_destruct_right merge path0 path1
(join zero0 (union_eq_overlap merge one0 item1))
else if Z.lt (upper_bound zero0) lo1 then
union_eq_destruct_right merge path0 path1
(join zero0 (union_eq_ordered merge item1 one0))
else
union_eq_destruct_left merge (Right (path0, one0)) path1 zero0 item1
| ( Node { zero = zero0; one = one0; _ },
(Node { lo = lo1; zero = zero1; one = one1; _ } as node1) ) ->
if Z.leq (lower_bound one0) lo1 then
union_eq_destruct_right merge path0 path1
(join zero0 (union_eq_overlap merge one0 node1))
else if Z.lt (upper_bound zero0) lo1 then
union_eq_destruct_right merge path0 path1
(join zero0 (union_eq_ordered merge node1 one0))
else
union_eq_destruct_left merge
(Right (path0, one0))
(Right (path1, one1))
zero0 zero1
and union_eq_destruct_right :
('a item -> 'a item -> 'a) -> 'a path -> 'a path -> 'a tree -> 'a tree =
let rec union_eq_destruct_right_single :
('a item -> 'a item -> 'a) -> 'a right -> 'a tree -> 'a tree =
fun merge (Right (path0, tree0)) acc ->
if Z.lt (upper_bound acc) (lower_bound tree0) then
union_eq_destruct_right_single_disjoint path0 (join acc tree0)
else
match path0 with
| Root -> union_eq_overlap merge acc tree0
| Right _ as right0 ->
union_eq_destruct_right_single merge right0
(union_eq_overlap merge acc tree0)
and union_eq_destruct_right_single_disjoint : 'a path -> 'a tree -> 'a tree
=
fun path0 acc ->
match path0 with
| Root -> acc
| Right (path0, tree0) ->
union_eq_destruct_right_single_disjoint path0 (join acc tree0)
and union_eq_destruct_right_double :
('a item -> 'a item -> 'a) -> 'a right -> 'a right -> 'a tree -> 'a tree
=
fun merge (Right (_, tree0) as right0) (Right (_, tree1) as right1) acc ->
if Z.lt (lower_bound tree1) (lower_bound tree0) then
union_eq_destruct_right_double_ordered merge right1 right0 acc
else union_eq_destruct_right_double_ordered merge right0 right1 acc
and union_eq_destruct_right_double_ordered :
('a item -> 'a item -> 'a) -> 'a right -> 'a right -> 'a tree -> 'a tree
=
fun merge (Right (path0, tree0)) (Right (path1, tree1) as right1) acc ->
if Z.lt (upper_bound tree0) (lower_bound tree1) then
union_eq_destruct_right merge path0 right1
(union_eq_ordered merge acc tree0)
else
union_eq_destruct_left merge path0 path1
(union_eq_ordered merge acc tree0)
tree1
in
fun merge path0 path1 acc ->
match (path0, path1) with
| Root, Root -> acc
| Root, (Right _ as right1) ->
union_eq_destruct_right_single merge right1 acc
| (Right _ as right0), Root ->
union_eq_destruct_right_single merge right0 acc
| (Right _ as right0), (Right _ as right1) ->
union_eq_destruct_right_double merge right0 right1 acc
in
fun merge t0 t1 ->
match (t0, t1) with
| Empty, t1 -> t1
| t0, Empty -> t0
| ( ((Item { lo = lo0; _ } | Node { lo = lo0; _ }) as tree0),
((Item { lo = lo1; _ } | Node { lo = lo1; _ }) as tree1) ) ->
any
(if Z.lt lo1 lo0 then union_eq_ordered merge tree1 tree0
else union_eq_ordered merge tree0 tree1) *)letunion_eq:?stich:('aitem->'aitem->'aoption)->('aitem->'aitem->'a)->'at->'at->'at=letunion:('aitem->'aitem->'a)->'aitem->'aitem->'at=funmerge(Item{lo=lo0;hi=hi0;elt=elt0}asitem0)(Item{lo=lo1;hi=hi1;elt=elt1;_}asitem1)->ifelt0==elt1thenifZ.leqlo0lo1thenifZ.leqhi1hi0thenitem0elseItem{lo=lo0;hi=hi1;elt=elt0}elseifZ.leqhi0hi1thenitem1elseItem{lo=lo1;hi=hi0;elt=elt0}elseItem{lo=Z.minlo0lo1;hi=Z.maxhi0hi1;elt=mergeitem0item1}infun?stichmerget0t1->union_update?stich(unionmerge)t0t1letunion_left:?stich:('aitem->'aitem->'aoption)->?crop:(lo:Z.t->hi:Z.t->'a->'a)->'at->'at->'at=letkeep_left:(lo:Z.t->hi:Z.t->'a->'a)->'aitem->'aitem->'at=funcrop(Item{lo=lo0;hi=hi0;_}asitem0)(Item{lo=lo1;hi=hi1;elt=elt1})->ifZ.leqlo0lo1thenifZ.leqhi1hi0then(* Ll Rl Rh Lh *)item0else(* Ll Rl Lh Rh *)letloa=Z.succhi0inany(join~stich:Noneitem0(Item{lo=loa;hi=hi1;elt=crop~lo:(Z.subloalo1)~hi:(Z.subhi1lo1)elt1;}))elselethib=Z.predlo0inifZ.leqhi1hi0then(* Rl Ll Rh Lh *)any(join~stich:None(Item{lo=lo1;hi=hib;elt=crop~lo:Z.zero~hi:(Z.subhiblo1)elt1;})item0)else(* Rl Ll Lh Rh *)letloa=Z.succhi0inany(join~stich:None(join~stich:None(Item{lo=lo1;hi=hib;elt=crop~lo:Z.zero~hi:(Z.subhiblo1)elt1;})item0)(Item{lo=loa;hi=hi1;elt=crop~lo:(Z.subloalo1)~hi:(Z.subhi1lo1)elt1;}))infun?stich?(crop=fun~lo:_~hi:_a->a)t0t1->union_update?stich(keep_leftcrop)t0t1(* let union_split :
?crop:(lo:Z.t -> hi:Z.t -> 'a -> 'a) ->
('a item -> 'a item -> 'a) ->
'a t ->
'a t ->
'a t =
let split :
(lo:Z.t -> hi:Z.t -> 'a -> 'a) ->
('a item -> 'a item -> 'a) ->
'a item ->
'a item ->
'a t =
fun crop merge (Item { lo = lo0; hi = hi0; elt = elt0 } as item0)
(Item { lo = lo1; hi = hi1; elt = elt1 } as item1) ->
if Z.leq lo0 lo1 then
if Z.equal lo0 lo1 then
if Z.leq hi0 hi1 then
if Z.equal hi0 hi1 then
(Item
{
lo = lo0;
hi = hi0;
elt = merge item0 item1;
})
else assert false
else assert false
else if Z.leq hi1 hi0 then
(* Ll Rl Rh Lh *)
let hib = Z.pred lo1 and loa = Z.succ hi1 in
any
(join
(join
(Item
{
lo = lo0;
hi = hib;
elt = crop ~lo:Z.zero ~hi:(Z.sub hib lo0) elt0;
})
(Item { lo = lo1; hi = hi1; elt = merge item0 item1 }))
(Item
{
lo = loa;
hi = hi0;
elt = crop ~lo:(Z.sub loa lo0) ~hi:(Z.sub hi0 lo0) elt0;
}))
else
(* Ll Rl Lh Rh *)
let loa = Z.succ hi0 in
any
(join item0
(Item
{
lo = loa;
hi = hi1;
elt = crop ~lo:(Z.sub loa lo1) ~hi:(Z.sub hi1 lo1) elt1;
}))
else
let hib = Z.pred lo0 in
if Z.leq hi1 hi0 then
(* Rl Ll Rh Lh *)
any
(join
(Item
{
lo = lo1;
hi = hib;
elt = crop ~lo:Z.zero ~hi:(Z.sub hib lo1) elt1;
})
item0)
else
(* Rl Ll Lh Rh *)
let loa = Z.succ hi0 in
any
(join
(join
(Item
{
lo = lo1;
hi = hib;
elt = crop ~lo:Z.zero ~hi:(Z.sub hib lo1) elt1;
})
item0)
(Item
{
lo = loa;
hi = hi1;
elt = crop ~lo:(Z.sub loa lo1) ~hi:(Z.sub hi1 lo1) elt1;
}))
in
fun ?(crop = fun ~lo:_ ~hi:_ a -> a) merge t0 t1 ->
union_update (split crop merge) t0 t1 *)letdisjoint:typeab.at->bt->bool=letrecdisjoint_ordered:typeab.atree->btree->bool=funtree0tree1->letub0=upper_boundtree0andlb1=lower_boundtree1inZ.ltub0lb1||match(tree0,tree1)with|Item_,Item_->false|Item{lo=lb0;_},Node{zero=zero1;one=one1;_}->is_empty_between_choicelb0ub0zero1one1|Node{zero=zero0;one=one0;_},Item{hi=ub1;_}->is_empty_between_choicelb1ub1zero0one0|((Node{zero=zero0;one=one0;_}asnode0),(Node{zero=zero1;one=one1;_}asnode1))->ifZ.leq(lower_boundone0)lb1thendisjoint_orderedone0node1elseifZ.ltub0(lower_boundone1)thendisjoint_orderednode0zero1elsedisjoint_orderedzero0node1&&disjoint_orderednode1one0infunt0t1->match(t0,t1)with|Empty,_|_,Empty->true|(((Item{lo=lo0;_}|Node{lo=lo0;_})astree0),((Item{lo=lo1;_}|Node{lo=lo1;_})astree1))->ifZ.ltlo1lo0thendisjoint_orderedtree1tree0elsedisjoint_orderedtree0tree1letsubstract:typeab.?crop:(lo:Z.t->hi:Z.t->a->a)->at->bt->at=letunion_disjoint:typea.at->at->at=funt0t1->match(t0,t1)with|Empty,t1->t1|t0,Empty->t0|((Item_|Node_)astree0),((Item_|Node_)astree1)->any(join~stich:Nonetree0tree1)inletrecsubstract:typeab.crop:(lo:Z.t->hi:Z.t->a->a)->atree->btree->at=fun~croptree0tree1->letub0=upper_boundtree0andlb1=lower_boundtree1inifZ.ltub0lb1thenanytree0elseletlb0=lower_boundtree0andub1=upper_boundtree1inifZ.ltub1lb0thenanytree0elsematch(tree0,tree1)with|(Item{lo=lo0;hi=hi0;elt=elt0},Item{lo=lo1;hi=hi1;_})->ifZ.leqlo1lo0thenifZ.leqhi0hi1thenEmptyelseletloa=Z.succhi1inItem{lo=loa;hi=hi0;elt=crop~lo:(Z.subloalo0)~hi:(Z.subhi0lo0)elt0;}elseifZ.leqhi0hi1thenlethib=Z.predlo1inItem{lo=lo0;hi=hib;elt=crop~lo:Z.zero~hi:(Z.subhiblo0)elt0;}elseletloa=Z.succhi1andhib=Z.predlo1inany(join~stich:None(Item{lo=lo0;hi=hib;elt=crop~lo:Z.zero~hi:(Z.subhiblo0)elt0;})(Item{lo=loa;hi=hi0;elt=crop~lo:(Z.subloalo0)~hi:(Z.subhi0lo0)elt0;}))|(Item_asitem0),Node{zero=zero1;one=one1;_}->(letitem0'=substract~cropitem0zero1inmatchitem0'with|Empty->Empty|(Item_|Node_)astree0'->substract~croptree0'one1)|((Node{zero=zero0;one=one0;_}asnode0),((Item_|Node_)astree1))->letzero0'=substract~cropzero0tree1andone0'=substract~cropone0tree1inifanyzero0==zero0'&&anyone0==one0'thennode0elseunion_disjointzero0'one0'infun?(crop=fun~lo:_~hi:_a->a)t0t1->match(t0,t1)with|Empty,_->Empty|t0,Empty->t0|((Item_|Node_)astree0),((Item_|Node_)astree1)->substract~croptree0tree1letfold_inter:typeab.(aitem->bitem->'c->'c)->'c->at->bt->'c=letrecfold_inter:typeab.(aitem->bitem->'c->'c)->'c->atree->btree->'c=funfacctree0tree1->letub0=upper_boundtree0andlb1=lower_boundtree1inifZ.ltub0lb1thenaccelseletlb0=lower_boundtree0andub1=upper_boundtree1inifZ.ltub1lb0thenaccelsematch(tree0,tree1)with|(Item_asitem0),(Item_asitem1)->fitem0item1acc|(Item_asitem0),Node{zero=zero1;one=one1;_}->fold_interf(fold_interfaccitem0zero1)item0one1|Node{zero=zero0;one=one0;_},((Item_|Node_)astree1)->fold_interf(fold_interfacczero0tree1)one0tree1infunfacct0t1->match(t0,t1)with|Empty,_|_,Empty->acc|((Item_|Node_)astree0),((Item_|Node_)astree1)->fold_interfacctree0tree1