123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116(**************************************************************************)(* This file is part of the Codex semantics library. *)(* *)(* Copyright (C) 2013-2025 *)(* 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 LICENSE). *)(* *)(**************************************************************************)(* Okasakis big endiant fast integer maps, with the change that when a key is not present, we find
the one which is just below. *)moduleOkasaki=struct(* A mask is an integer with a single bit set (i.e. a power of 2). *)typemask=intletlowest_bitx=xland(-x)letrechighest_bitx=letm=lowest_bitxinifx=mthenmelsehighest_bit(x-m);;letbranching_bitab=highest_bit(alxorb);;letmaskim=iland(lnot(2*m-1));;typekey=inttype'at=|Empty|Leafof{key:key;value:'a}(* The entire key. *)|Branchof{prefix:key;branching_bit:mask;tree0:'at;tree1:'at}let_leafkeyvalue=Leaf{key;value}letbranch~prefix~branching_bit~tree0~tree1=Branch{prefix;branching_bit;tree0;tree1}letmatch_prefixkpm=maskkm=p;;(* Merge trees whose prefix disagree. *)letjoinpatreeapbtreeb=(* Printf.printf "join %d %d\n" pa pb; *)letm=branching_bitpapbinletp=maskpa(* for instance *)minif(palandm)=0thenbranch~prefix:p~branching_bit:m~tree0:treea~tree1:treebelsebranch~prefix:p~branching_bit:m~tree0:treeb~tree1:treea;;(* Standard insertion in a Patricia tree. *)letinsert~mergekeyvaluenode=letrecinsnode=matchnodewith|Empty->Leaf{key;value}|Leaf{key=j;value=old}->ifkey=jthenLeaf{key;value=(merge~oldvalue)}elsejoinkey(Leaf{key;value})jnode|Branch{prefix;branching_bit;tree0;tree1}->ifmatch_prefixkeyprefixbranching_bitthenif(keylandbranching_bit)==0thenbranch~prefix~branching_bit~tree0:(instree0)~tree1elsebranch~prefix~branching_bit~tree0~tree1:(instree1)elsejoinkey(Leaf{key;value})prefixnodeininsnode;;(* Find the value associated to the highest key which is <= [key]. *)letfindkeynode=letexceptionToo_much_on_the_rightinletrecloopnode=matchnodewith|Empty->raiseNot_found|Leaf{key=key';_}whenkey'>key->raiseToo_much_on_the_right|Leaf{value=data;_}->data|Branch{prefix;tree0;tree1;_}->(* Printf.printf "prefix %d branch %d key %d\n" prefix branching_bit key; *)ifprefix>key(* The minimum key. *)thenraiseToo_much_on_the_rightelsetrylooptree1withToo_much_on_the_right->looptree0inloopnode(* let (node,zipper) as res = loop node End in *)(* assert (match node with Leaf{key=key'} when key' > key -> true | _ -> false); *)(* res *);;endtype'at='aOkasaki.tletinsert=Okasaki.insertletfind=Okasaki.findletempty=Okasaki.Empty