(* Flots d'entiers / Flots binaires*) (* A bit can be represented either as a Boolean or as an integer. *) let b2i (b : bool) : int = if b then 1 else 0 let i2b (i : int) : bool = assert (i = 0 || i = 1); i = 1 (* [unpack_int k i bs] is a producer. It constructs the concatenation of the [k] least significant bits of the integer [i] in front of the bit t [bs]. It is not lazy; [k] memory cells are allocated immediately. The bits are written from left to right, i.e., the most significant bit comes first. Note that bits may be lost if [k] exceeds [Sys.word_size - 1].*) let rec push_int_as_bits (k : int) (i : int) (bs : bool MyStream.t) : bool MyStream.t = if k = 0 then bs else (* Among the [k] rightmost bits of [i], compute the most significant one. This can be done by shifting [i] to the right by [k - 1] and reading the rightmost bit. *) let bit = (i lsr (k - 1)) land 1 in (* Continue. *) lazy (MyStream.Cons ( (i2b bit) , (push_int_as_bits (k - 1) i bs) )) (* [pack_int k accu bs] is a consumer. It reads up to [k] bits from the bit t [bs] and inserts them at the right end of the accumulator, which is shifted towards the left. If the end of the t [bs] is reached before [k] bits have been read, an appropriate number of zero bits are inserted at the end as padding. The function returns the updated accumulator and the remainder of the t. *) let rec pop_bits_as_int (k : int) (accu : int) (bs : bool MyStream.t) : int * bool MyStream.t = if k = 0 then accu, bs else let b, bs = match Lazy.force bs with | MyStream.Nil -> 0, bs (* padding *) | MyStream.Cons (b, bs) -> b2i b, bs in pop_bits_as_int (k - 1) (accu lsl 1 + b) bs let pop_bits_as_int k bs = pop_bits_as_int k 0 bs (* Remark that (unpack_int k) o (pack_int k) = id provided k ≤ (Sys.word_size) - 1 and (pack_int k) o (unpack_int k) = id provided k ≥ (Sys.word_size) -1 *)