diff --git a/src/libraries/stdlib/integer.ml b/src/libraries/stdlib/integer.ml index 55d36122770094da3949f3540941b9fdc0bdccbd..ae5d130f21722546db97672ac56bcc8dfd85b14a 100644 --- a/src/libraries/stdlib/integer.ml +++ b/src/libraries/stdlib/integer.ml @@ -120,6 +120,74 @@ let popcount = Z.popcount try Z.of_float z with Z.Overflow -> raise Too_big + let bdigits = [| + "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 *) + |] + + let pp_bin_pos fmt r = Format.pp_print_string fmt bdigits.(r) + let pp_bin_neg fmt r = Format.pp_print_string fmt bdigits.(15-r) + + let pp_hex_pos fmt r = Format.fprintf fmt "%04X" r + let pp_hex_neg fmt r = Format.fprintf fmt "%04X" (0xFFFF-r) + + let bmask_bin = Z.of_int 15 + let bmask_hex = Z.of_int 0xFFFF + + type digits = { + nbits : int ; (* max number of bits *) + bsize : int ; (* bits in each bloc *) + bmask : Z.t ; (* block mask *) + sep : string ; + pp : Format.formatter -> int -> unit ; (* print one block *) + } + + let rec pp_digits d fmt n v = + if gt v zero || n < d.nbits then + begin + let r = Z.to_int (Z.logand v d.bmask) in + let k = d.bsize in + pp_digits d fmt (n + k) (Z.shift_right_trunc v k) ; + if gt v d.bmask || (n + k) < d.nbits + then Format.pp_print_string fmt d.sep ; + d.pp fmt r ; + end + + let pp_bin ?(nbits=0) ?(sep="") fmt v = + if le zero v then + ( Format.pp_print_string fmt "0b" ; + pp_digits { nbits ; sep ; bsize=4 ; + bmask = bmask_bin ; pp = pp_bin_pos } fmt 0 v ) + else + ( Format.pp_print_string fmt "1b" ; + pp_digits { nbits ; sep ; bsize=4 ; + bmask = bmask_bin ; pp = pp_bin_neg } fmt 0 (Z.lognot v) ) + + let pp_hex ?(nbits=0) ?(sep="") fmt v = + if le zero v then + ( Format.pp_print_string fmt "0x" ; + pp_digits { nbits ; sep ; bsize=16 ; + bmask = bmask_hex ; pp = pp_hex_pos } fmt 0 v ) + + else + ( Format.pp_print_string fmt "1x" ; + pp_digits { nbits ; sep ; bsize=16 ; + bmask = bmask_hex ; pp = pp_hex_neg } fmt 0 (Z.lognot v) ) + let pretty ?(hexa=false) fmt v = let rec aux v = if gt v two_power_60 then diff --git a/src/libraries/stdlib/integer.mli b/src/libraries/stdlib/integer.mli index 4e939382bf131017b673f534505420f04c0df94c..7c1c663bea3af17aa4cdb2b0a660402920e9d4ac 100644 --- a/src/libraries/stdlib/integer.mli +++ b/src/libraries/stdlib/integer.mli @@ -150,8 +150,21 @@ val popcount: t -> int val pretty : ?hexa:bool -> t Pretty_utils.formatter - +val pp_bin : ?nbits:int -> ?sep:string -> t Pretty_utils.formatter +(** Print binary format. Digits are output by blocs of 4 bits + separated by [~sep] with at least [~nbits] total bits. + + Positive values are preffixed with ["0b"] and negative values + are printed as their 2-complement ([lnot]) with prefix ["1b"]. *) + +val pp_hex : ?nbits:int -> ?sep:string -> t Pretty_utils.formatter +(** Print hexadecimal format. Digits are output by blocs of 16 bits + (4 hex digits) separated by [~sep] with at least [~nbits] total bits. + + Positive values are preffixed with ["0x"] and negative values + are printed as their 2-complement ([lnot]) with prefix ["1x"]. *) (* + Local Variables: compile-command: "make -C ../../.." End: