123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131(* Copyright (c) 2015 ocaml-diet developpers.
SPDX-License-Identifier: ISC
*)typet=Empty|Nodeofnodeandnode={x:int;y:int;l:t;r:t;h:int}letheight=functionEmpty->0|Noden->n.hletempty=Emptyletis_empty=functionEmpty->true|_->falseletrecnodexylr=lethl=heightlandhr=heightrinifhl>hr+2thenlet[@warning"-8"](Node{x=lx;y=ly;l=ll;r=lr;_})=linifheightll>=heightlrthennodelxlyll(nodexylrr)elselet[@warning"-8"](Node{x=lrx;y=lry;l=lrl;r=lrr;_})=lrinnodelrxlry(nodelxlylllrl)(nodexylrrr)elseifhr>hl+2thenlet[@warning"-8"](Node{x=rx;y=ry;l=rl;r=rr;_})=rinifheightrr>=heightrlthennoderxry(nodexylrl)rrelselet[@warning"-8"](Node{x=rlx;y=rly;l=rll;r=rlr;_})=rlinnoderlxrly(nodexylrll)(noderxryrlrrr)elseleth=Int.max(heightl)(heightr)+1inNode{x;y;l;r;h}letrecsplit_max=function|{x;y;l;r=Empty;_}->(x,y,l)|{r=Noder;_}asn->letu,v,r'=split_maxrin(u,v,noden.xn.yn.lr')(*
let rec split_min = function
| { x; y; l= Empty; r; _ } -> x, y, r
| { l= Node l; _ } as n ->
let u, v, l' = split_min l in
u, v, node n.x n.y l' n.r
let add_left = function
| { l= Empty; _ } as n -> n
| { l= Node l; _ } as n ->
let x', y', l' = split_max l in
if y' + 1 == n.x
then { n with x= x'; l= l' }
else n
let add_right = function
| { r= Empty; _ } as n -> n
| { r= Node r; _ } as n ->
let x', y', r' = split_min r in
if n.y + 1 == x'
then { n with y= y'; r= r' }
else n
*)exceptionOverlaplet()=Printexc.register_printer@@function|Overlap->Some"Fragment overlap"|_->Noneletrecadd(x,y)t=matchtwith|Empty->nodexyEmptyEmpty|Nodenwheny<n.x->letl=add(x,y)n.linnoden.xn.yln.r|Nodenwhenn.y<x->letr=add(x,y)n.rinnoden.xn.yn.lr|_->raise_notraceOverlapletadd~off~lent=letx=offandy=off+len-1inadd(x,y)tletmergelr=match(l,r)with|l,Empty->l|Empty,r->r|Nodel,r->letx,y,l'=split_maxlinnodexyl'rletrecremove(x,y)t=matchtwith|Empty->Empty(* completely to the left *)|Nodenwheny<n.x->letl=remove(x,y)n.linnoden.xn.yln.r(* completely to the right *)|Nodenwhenn.y<x->letr=remove(x,y)n.rinnoden.xn.yn.lr(* overlap on the left only *)|Nodenwhenx<n.x&&y<n.y->letn'=node(y+1)n.yn.ln.rinremove(x,n.x-1)n'(* overlap on the right only *)|Nodenwheny>n.y&&x>n.x->letn'=noden.x(x-1)n.ln.rinremove(n.y+1,y)n'(* overlap on both side *)|Nodenwhenx<=n.x&&y>=n.y->letl=remove(x,n.x)n.linletr=remove(n.y,y)n.rinmergelr(* completely within *)|Nodenwheny==n.y->noden.x(x-1)n.ln.r|Nodenwhenx==n.x->node(y+1)n.yn.ln.r|Noden->assert(n.x<=x-1);assert(y+1<=n.y);letr=node(y+1)n.yEmptyn.rinnoden.x(x-1)n.lrletrecfoldfntacc=matchtwith|Empty->acc|Noden->letacc=foldfnn.laccinletacc=fn(n.x,n.y)accinfoldfnn.raccletdiffab=foldremoveab