123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238typeorder={mutablen:int;mutablen0:int;}typet={mutablerepr:Order_list.t;mutabletag:int;mutableprev:t;mutablenext:t;order:order;}letrecsentinel={repr=Order_list.root();tag=0;order={n=0;n0=0};prev=sentinel;next=sentinel}letis_global_lastt=t.next==tletis_global_firstt=t.prev==tletis_local_lastt=is_global_lastt||t.next.repr!=t.reprletis_local_firstt=is_global_firstt||t.prev.repr!=t.reprletaveragexy=(xlandy)+(xlxory)/2(** Check if two elements belong to the same order. O(1) *)letsame_ordert1t2=t1.order==t2.order(** Compare two elements. O(1) *)letcomparet1t2=ift1.repr==t2.reprthencomparet1.tagt2.tagelseOrder_list.comparet1.reprt2.repr(** How many elements are ordered. O(1) *)letcardinalt=t.order.nletis_validt=t.prev!=sentinelletroot()=letrect={repr=Order_list.root();tag=0;order={n=1;n0=1};prev=t;next=t}intletglobal_relabelt=(* prerr_endline "global_relabel"; *)lett=letrecfirstt=ifis_global_firsttthentelsefirstt.previnfirsttinletn=t.order.nint.order.n0<-n;letcount=int_of_float(log(floatn)*.4.0)inletstep=max_int/(count+1)*2inlettag=refmin_intinletrepr=reft.reprinletk=refcountinletr=reftinwhile!r!=sentineldolett=!rinif!k=0thenbeginletrepr'=Order_list.unsafe_next!reprinrepr:=(ifrepr'==!reprthenOrder_list.afterrepr'elserepr');tag:=min_int;k:=count;end;tag:=!tag+step;(* Printf.eprintf "tag = %d\n" !tag; *)t.tag<-!tag;t.repr<-!repr;decrk;ifis_global_lasttthenr:=sentinelelser:=(!r).nextdone;if!repr!=Order_list.unsafe_next!reprthenbeginletrecreleaserepr=letrepr'=Order_list.unsafe_nextreprinOrder_list.forgetrepr;ifrepr!=repr'thenreleaserepr'inrelease(Order_list.unsafe_next!repr)endletlocal_relabelt=(* prerr_endline "local_relabel"; *)letcount=ref1inletfirst=lett=reftinwhilenot(is_local_first!t)doincrcount;t:=(!t).prevdone;!tinletcount=lett=reftinwhilenot(is_local_last!t)doincrcount;t:=(!t).nextdone;!countinletstep=max_int/(count+1)*2inletrecaux0ttag=function|0->t|n->t.tag<-tag;(* Printf.eprintf "tag0 = %d\n" tag; *)aux0t.next(tag+step)(n-1)inletmid=aux0first(min_int+step)(count/2)inletrepr=Order_list.aftert.reprinletrecaux1ttag=letis_local_last=is_local_lasttint.repr<-repr;t.tag<-tag;(* Printf.eprintf "tag1 = %d\n" tag; *)ifnotis_local_lastthenaux1t.next(tag+step)inaux1mid(min_int+step)letrelabelt=(* prerr_endline "relabel"; *)let{n;n0}=t.orderinifn>Sys.word_size&&(n*3<n0*2||n0*3<n*2)thenglobal_relabeltelselocal_relabeltletaftert=(* prerr_endline "after"; *)assert(is_validt);lettag1=t.taginlettag2=ifis_local_lasttthenmax_intelset.next.taginlettag=averagetag1tag2inlet{next;repr;order;_}=tinlett'={repr;tag;order;prev=t;next}inifis_global_lasttthent'.next<-t'elsenext.prev<-t';t.next<-t';order.n<-order.n+1;iftag=tag1||tag=tag2thenrelabelt;t'letbeforet=(* prerr_endline "before"; *)assert(is_validt);lettag1=ifis_local_firsttthenmin_intelset.prev.taginlettag2=t.taginlettag=averagetag1tag2inlet{prev;repr;order;_}=tinlett'={repr;tag;order;prev;next=t}inifis_global_firsttthent'.prev<-t'elseprev.next<-t';t.prev<-t';order.n<-order.n+1;iftag=tag1||tag=tag2thenrelabelt';t'letforgett=(* prerr_endline "forget"; *)ifis_validtthenbegin(* Update inner order *)ifis_local_firstt&&is_local_lasttthenOrder_list.forgett.repr;(* Update linked list *)let{next;prev;_}=tinifis_global_firsttthennext.prev<-nextelsenext.prev<-prev;ifis_global_lasttthenprev.next<-prevelseprev.next<-next;(* Update global order *)t.order.n<-t.order.n-1;t.prev<-sentinel;t.next<-sentinel;t.repr<-sentinel.repr;endletcheckt=assert(Order_list.is_validt.repr);assert(t.order==t.next.order);assert(t.order==t.prev.order);assert(Order_list.comparet.prev.reprt.repr<=0);assert(Order_list.comparet.reprt.next.repr<=0);ifis_local_firsttthenbeginassert(Order_list.same_ordert.prev.reprt.repr);ifnot(is_global_firstt)thenassert(Order_list.comparet.prev.reprt.repr<0);endelsebeginassert(t.repr==t.prev.repr);assert(t.prev.tag<t.tag);end;ifis_local_lasttthenbeginassert(Order_list.same_ordert.reprt.next.repr);ifnot(is_global_lastt)thenassert(Order_list.comparet.reprt.next.repr<0);endelsebeginassert(t.repr==t.next.repr);assert(t.tag<t.next.tag);endletunsafe_checktmsg=Order_list.unsafe_checkt.reprmsg;tryifis_validtthenchecktelsebeginassert(t.prev==sentinel);assert(t.next==sentinel);endwithAssert_failure(file,line,col)->raise(Assert_failure(msg^": "^file,line,col))