123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105(**************************************************************************)(* 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). *)(* *)(**************************************************************************)moduleLog=Tracelog.Make(structletcategory="Bitfield_Lattice"end);;(* Warn if we create too large bitfields.
Probably no real performance issue below this value. *)letbitfield_perf_warn_size=512;;letbitfield_perf_warn_done=reffalse;;letbitfield_perf_warn~size=if(!bitfield_perf_warn_done&&size>bitfield_perf_warn_size)thenbeginLog.warning(funp->p"Data structure may not suit large bit values");bitfield_perf_warn_done:=trueend;;moduleBitfieldDT=(structtypet=Z.tletpretty=Z.pp_printletequal=Z.equalletcompare=Z.comparelethash=Z.hashend)moduleBitfield=struct(* type t = Z.t *)includeBitfieldDTletbottom()=Z.zeroletis_bottom=Z.equalZ.zerolettop~size=assert(0<=size);bitfield_perf_warn~size;Z.pred(Z.shift_leftZ.onesize)letsingletonidx=bitfield_perf_warn~size:idx;Z.shift_leftZ.oneidxletjoin=Z.logorletis_includedab=Z.equala(Z.logandab)letincludesab=is_includedbaletwiden~previous=joinpreviousletincludes_or_widen~previousa=ifincludespreviousathen(true,a)else(false,joinpreviousa)letinter=Z.logandendincludeBitfield(* https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 *)letis_singletonx=ifZ.equalZ.zeroxthenNoneelseifZ.equalZ.zero(Z.(land)x(Z.predx))thenSome(Z.log2x)elseNone;;(* Fold on indices that are set, by chunks of 64 bits, in ascending order. *)letfold_on_casesxaccf=assert(Z.signx>=0);letrecfold_on_wordposxacc=ifZ.equalxZ.zerothenaccelseletn=Z.trailing_zerosxinletacc=f(pos+n)accinletx=Z.(land)x(Z.lognot(Z.shift_leftZ.onen))infold_on_wordposxaccinletrecloopposxacc=ifZ.equalxZ.zerothenaccelseletword=Z.extractx064inletacc=fold_on_wordposwordaccinletx=Z.shift_rightx64inloop(pos+64)xaccinloop0xacc