123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242(**************************************************************************)(* 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). *)(* *)(**************************************************************************)typet=Z.tletequal=Z.equalletcompare=Z.comparelettwo_power_of_intk=Z.shift_leftZ.oneklettwo_powern=letk=Z.to_intninifk>1024thenraiseZ.Overflowelsetwo_power_of_intkletpower_int_positive_int=Big_int_Z.power_int_positive_intletpopcount=Z.popcountletzero=Z.zeroletone=Z.oneletminus_one=Z.minus_onelettwo=Z.of_int2letfour=Z.of_int4leteight=Z.of_int8letsixteen=Z.of_int16letthirtytwo=Z.of_int32letonethousand=Z.of_int1000letbillion_one=Z.of_int1_000_000_001lettwo_power_32=two_power_of_int32lettwo_power_60=two_power_of_int60lettwo_power_64=two_power_of_int64letis_zerov=Z.equalvZ.zeroletadd=Z.addletsub=Z.subletsucc=Z.succletpred=Z.predletneg=Z.negletmul=Z.mullete_div=Z.edivlete_rem=Z.eremlete_div_rem=Z.ediv_remletc_div=Z.divletc_rem=Z.remletc_div_rem=Z.div_remletabs=Z.abslethash=Z.hashletshift_leftxy=Z.shift_leftx(Z.to_inty)letshift_rightxy=Z.shift_rightx(Z.to_inty)letshift_right_logicalxy=(* no meaning for negative value of x *)if(Z.ltxZ.zero)thenraise(Invalid_argument"Integer.shift_right_logical")elseZ.shift_rightx(Z.to_inty)letlogand=Z.logandletlognot=Z.lognotletlogor=Z.logorletlogxor=Z.logxorletleab=Z.compareab<=0letgeab=Z.compareab>=0letltab=Z.compareab<0letgtab=Z.compareab>0letof_int=Z.of_intletof_int64=Z.of_int64letof_int32=Z.of_int32letto_int=Z.to_intletto_int64=Z.to_int64letto_int32=Z.to_int32letof_string=Z.of_stringletto_string=Z.to_stringletof_float=Z.of_floatletto_float=Z.to_floatletmax_int64=of_int64Int64.max_intletmin_int64=of_int64Int64.min_intletbdigits=[|"0000";(* 0 *)"0001";(* 1 *)"0010";(* 2 *)"0011";(* 3 *)"0100";(* 4 *)"0101";(* 5 *)"0110";(* 6 *)"0111";(* 7 *)"1000";(* 8 *)"1001";(* 9 *)"1010";(* 10 *)"1011";(* 11 *)"1100";(* 12 *)"1101";(* 13 *)"1110";(* 14 *)"1111";(* 15 *)|]letpp_bin_posfmtr=Format.pp_print_stringfmtbdigits.(r)letpp_bin_negfmtr=Format.pp_print_stringfmtbdigits.(15-r)letpp_hex_posfmtr=Format.fprintffmt"%04X"rletpp_hex_negfmtr=Format.fprintffmt"%04X"(0xFFFF-r)letbmask_bin=Z.of_int0xF(* 4 bits mask *)letbmask_hex=Z.of_int0xFFFF(* 64 bits mask *)typedigits={nbits:int;(* max number of bits *)bsize:int;(* bits in each bloc *)bmask:Z.t;(* block mask, must be (1 << bsize) - 1 *)sep:string;pp:Format.formatter->int->unit;(* print one block *)}letrecpp_digitsdfmtnv=ifgtvzero||n<d.nbitsthenbeginletr=Z.to_int(Z.logandvd.bmask)inletk=d.bsizeinpp_digitsdfmt(n+k)(Z.shift_right_truncvk);ifgtvd.bmask||(n+k)<d.nbitsthenFormat.pp_print_stringfmtd.sep;d.ppfmtr;endletpp_bin?(nbits=1)?(sep="")fmtv=letnbits=ifnbits<=0then1elsenbitsiniflezerovthen(Format.pp_print_stringfmt"0b";pp_digits{nbits;sep;bsize=4;bmask=bmask_bin;pp=pp_bin_pos}fmt0v)else(Format.pp_print_stringfmt"1b";pp_digits{nbits;sep;bsize=4;bmask=bmask_bin;pp=pp_bin_neg}fmt0(Z.lognotv))letpp_hex?(nbits=1)?(sep="")fmtv=letnbits=ifnbits<=0then1elsenbitsiniflezerovthen(Format.pp_print_stringfmt"0x";pp_digits{nbits;sep;bsize=16;bmask=bmask_hex;pp=pp_hex_pos}fmt0v)else(Format.pp_print_stringfmt"1x";pp_digits{nbits;sep;bsize=16;bmask=bmask_hex;pp=pp_hex_neg}fmt0(Z.lognotv))letpretty?(hexa=false)fmtv=letrecauxv=ifgtvtwo_power_60thenletquo,rem=Z.ediv_remvtwo_power_60inauxquo;Format.fprintffmt"%015LX"(to_int64rem)elseFormat.fprintffmt"%LX"(to_int64v)inifhexathenifequalvzerothenFormat.pp_print_stringfmt"0"elseifgtvzerothen(Format.pp_print_stringfmt"0x";auxv)else(Format.pp_print_stringfmt"-0x";aux(Z.negv))elseFormat.pp_print_stringfmt(to_stringv)letis_onev=equalonevletcast~size~signed~value=if(notsigned)thenletfactor=two_powersizeinlogandvalue(predfactor)elseletmask=two_power(subsizeone)inletp_mask=predmaskinifequal(logandmaskvalue)zerothenlogandvaluep_maskelselogor(lognotp_mask)valueletlengthuv=succ(subvu)letextract_bits~start~stopv=assert(gestartzero&&gestopstart);(*Format.printf "%a[%a..%a]@\n" pretty v pretty start pretty stop;*)letr=Z.extractv(to_intstart)(to_int(lengthstartstop))in(*Format.printf "%a[%a..%a]=%a@\n" pretty v pretty start pretty stop pretty r;*)rletis_evenv=is_zero(logandonev)letpgcduv=ifis_zerovthenabsu(* Zarith raises an exception on zero arguments *)elseifis_zerouthenabsvelseZ.gcduvletppcmuv=ifu=zero||v=zerothenzeroelseZ.lcmuvletmin=Z.minletmax=Z.maxletround_down_to_zerovmodu=mul(e_divvmodu)moduletround_up_to_r~min:m~r~modu=add(add(round_down_to_zero(pred(submr))modu)r)moduletround_down_to_r~max:m~r~modu=add(round_down_to_zero(submr)modu)r