package bitvec
Library
Module
Module type
Parameter
Class
Class type
val modulus : int -> modulus
modulus s
is the modulus of bitvectors with size s
.
This is a number $2^s-1$, also known as a Mersenne number.
val m1 : modulus
m1 = modulus 1
= $1$ is the modulus of bitvectors with size 1
val m8 : modulus
m8 = modulus 8
= $255$ is the modulus of bitvectors with size 8
val m16 : modulus
m16 = modulus 16
= $65535$ is the modulus of bitvectors with size 16
val m32 : modulus
m32 = modulus 32
= $2^32-1$ is the modulus of bitvectors with size 32
val m64 : modulus
m64 = modulus 64
= $2^64-1$ is the modulus of bitvectors with size 64
(x <op> y) mod m
applies operation <op>
modulo m
.
Example: (x + y) mod m
returns the sum of x
and y
modulo m
.
Note: the mod
function is declared as a primitive to enable support for inlining in non flambda versions of OCaml. Indeed, underneath the hood the 'a m
type is defined as the reader monad modulus -> 'a
, however we don't want to create a closure every time we compute an operation over bitvectors. With this trick, all versions of OCaml no matter the optimization options will inline (x+y) mod m
and won't create any closures, even if m
is not known at compile time.
module type S = sig ... end
compare x y
compares x
and y
as unsigned integers, i.e., compare x y
= compare (to_nat x) (to_nat y)
val hash : t -> int
hash x
returns such z
that forall y
s.t. x=y
, hash y = z
val pp : Format.formatter -> t -> unit
pp ppf x
is a pretty printer for the bitvectors.
Could be used standalone or as an argument to the %a
format specificator, e.g.,
Format.fprintf "0xBEEF != %a" Bitvec.pp !$"0xBEAF"
val to_binary : t -> string
to_binary x
returns a canonical binary representation of x
val of_binary : string -> t
of_binary s
returns a bitvector x
s.t. to_binary x = s
.
val to_string : t -> string
to_string x
returns a textual (human readable) representation of the bitvector x
.
val of_string : string -> t
of_string s
returns a bitvector that corresponds to s
.
The set of accepted strings is defined by the following EBNF grammar:
valid-numbers ::= | "0b", bin-digit, {bin-digit} | "0o", oct-digit, {oct-digit} | "0x", hex-digit, {hex-digit} | dec-digit, {dec-digit} bin-digit ::= '0' | '1' oct-digit ::= '0'-'7' dec-digit ::= '0'-'9' hex-digit ::= '0'-'9' |'a'-'f'|'A'-'F'
bigint_unsafe x
directly interprets a zarith value as bitvector.
The function is safe only if x
is the result of to_bigint
, otherwise the resulting value is unpredictable.
val of_substring : ?pos:int -> ?len:int -> string -> t
of_substring ~pos ~len s
is a bitvector that corresponds to a substring of s
designated by the start position pos
and length len
.
The result is the same as of_string (String.sub s pos len)
, except that no intermediate substring is created.
val of_string_base : int -> string -> t
of_string_base b x
is a bitvector that corresponds to s
represented in base b
.
The base b
must be between 2
and 16
. The textual representation shall not contain a prefix that designates the base and must be a sequence of digits that are less than b
.
Examples
Valid inputs:
of_string_base 16 "DEADBEEF"
;of_string_base 2 "010110"
;of_string_base 11 "AAAAAA"
.
Invalid inputs:
of_string_base 16 "0xDEADBEEF"
;of_string_base 2 "-010100"
;of_string_base 10 "AAAAA"
.
val of_substring_base : ?pos:int -> ?len:int -> int -> string -> t
of_substring_base b x
is a bitvector that corresponds to a substring of s
designated by the start position pos
and length len
that is a sequence of digits in base b
.
The result is the same as of_string_base b x (String.sub s pos
len)
, except that no intermediate substring is created.
val fits_int : t -> bool
fits_int x
is true
if x
could be represented with the OCaml int
type.
Note: it is not always true that fits_int (int x mod m)
, since depending on m
a negative number might not fit into the OCaml representation. For positive numbers it is true, however.
val to_int : t -> int
to_int x
returns an OCaml integer that has the same representation as x
.
The function is undefined if not (fits_int x)
.
val fits_int32 : t -> bool
fits_int32 x
is true
if x
could be represented with the OCaml int
type.
Note: it is not always true that fits_int32 (int32 x mod m)
, since depending on m
the negative x
may not fit back into the int32
representation. For positive numbers it is true, however.
val to_int32 : t -> int32
to_int32 x
returns an OCaml integer that has the same representation as x
.
The function is undefined if not (fits_int32 x)
.
val fits_int64 : t -> bool
fits_int64 x
is true
if x
could be represented with the OCaml int
type.
Note: it is not always true that fits_int64 (int64 x mod m)
, since depending on m
the negative x
might not fit back into the int64
representation. For positive numbers it is true, however.
val to_int64 : t -> int64
to_int64 x
returns an OCaml integer that has the same representation as x
.
The function is undefined if not (fits_int64 x)
.
to_bigint x
returns a natural number that corresponds to x
.
The returned value is always positive.
extract ~hi ~lo x
extracts bits from lo
to hi
.
The operation is effectively equivalent to (x lsr lo) mod (hi-lo+1)
select bits x
builds a bitvector from bits
of x
.
Returns a bitvector y
such that nth
bit of it is equal to List.nth bits n
bit of x
.
Returns zero
if bits
are empty.
append m n x y
takes m
bits of x
and n
bits of y
and returns their concatenation. The result has m+n
bits.
Examples:
append 16 16 !$"0xdead" !$"0xbeef" = !$"0xdeadbeef"
;append 12 20 !$"0xbadadd" !$"0xbadbeef" = !$"0xadddbeef"
;;
repeat m ~times:n x
repeats m
bits of x
n
times.
The result has m*n
bits.
concat m xs
concatenates m
bits of each x
in xs
.
The operation is the reduction of the append
operation with m=n
. The result has m * List.length xs
bits and is equal to 0
if xs
is empty.
include S with type 'a m := 'a m
val bool : bool -> t
bool x
returns one
if x
and zero
otherwise.
val zero : t
zero
is 0
.
val one : t
one
is 1
.
abs x mod m
absolute value of x
modulo m
.
The absolute value of x
is equal to neg x
if msb x
and to x
otherwise.
div x y mod m
is x / y
modulo m
,
where /
is the truncating towards zero division, that returns ones m
if y = 0
.
sdiv x y mod m
is signed division of x
by y
modulo m
,
The signed division operator is defined in terms of the div
operator as follows:
/ | div x y mod m : if not mx /\ not my | neg (div (neg x) y) mod m if mx /\ not my x sdiv y mod m = < | neg (div x (neg y)) mod m if not mx /\ my | div (neg x) (neg y) mod m if mx /\ my \ where mx = msb x mod m, and my = msb y mod m.
srem x y mod m
is the signed remainder x / y
modulo m
.
This version of the signed remainder where the sign follows the dividend, and is defined via the rem
operation as follows
/ | rem x y mod m : if not mx /\ not my | neg (rem (neg x) y) mod m if mx /\ not my x srem y mod m = < | neg (rem x (neg y)) mod m if not mx /\ my | neg (rem (neg x) (neg y)) mod m if mx /\ my \ where mx = msb x mod m, and my = msb y mod m.
smod x y mod m
is the signed remainder of x / y
modulo m
.
This version of the signed remainder where the sign follows the divisor, and is defined in terms of the rem
operation as follows:
/ | u if u = 0 x smod y mod m = < | v if u <> 0 \ / | u if not mx /\ not my | add (neg u) y mod m if mx /\ not my v = < | add u x mod m if not mx /\ my | neg u mod m if mx /\ my \ where mx = msb x mod m, and my = msb y mod m, and u = rem s t mod m.
nth x n mod m
is true
if n
th bit of x
is set
.
Returns msb x mod m
if n >= m
and lsb x mod m
if n < 0
arshift x y mod m
shifts x
right by y
with msb x
filling.
Returns ones mod m
if y >= m /\ msb x mod m
and zero
if y >= m /\ msb x mod m = 0
gcd x y mod m
returns the greatest common divisor modulo m
gcd x y
is the meet operation of the divisibility lattice, with 0
being the top of the lattice and 1
being the bottom, therefore gcd x 0 = gcd x 0 = x
.
lcm x y mod
returns the least common multiplier modulo m
.
lcm x y
is the meet operation of the divisibility lattice, with 0
being the top of the lattice and 1
being the bottom, therefore lcm x 0 = lcm 0 x = 0
(g,a,b) = gcdext x y mod m
, where
g = gcd x y mod m
,g = (a * x + b * y) mod m
.
The operation is well defined if one or both operands are equal to 0
, in particular:
(x,1,0) = gcdext(x,0)
,(x,0,1) = gcdext(0,x)
.
val (!$) : string -> t
!$x
is of_string x
module type Modulus = sig ... end
module Mx = Make(Modulus)
produces a module Mx
which implements all operation in S
modulo Modulus.modulus
, so that all operations return a bitvector directly.
val modular : int -> (module D)
modular n
returns a module M
, which implements all operations in S
modulo the bitwidth n
.