(** Size of integers, in bits. *)
Definition Zsize (x: Z) : Z :=
match x with
| Zpos p => Zpos (Pos.size p)
| _ => 0
end.
Definition size (x: int) : Z := Zsize (unsigned x).
Remark Zsize_pos: forall x, 0 <= Zsize x.
Remark Zsize_pos': forall x, 0 < x -> 0 < Zsize x.

(* Specifications: *)
Lemma Zsize_shiftin:
forall b x, 0 < x -> Zsize (Zshiftin b x) = Z.succ (Zsize x).
Lemma Ztestbit_size_1:
forall x, 0 < x -> Z.testbit x (Z.pred (Zsize x)) = true.
Lemma Ztestbit_size_2:
forall x, 0 <= x -> forall i, i >= Zsize x -> Z.testbit x i = false.
Lemma Zsize_interval_1:
forall x, 0 <= x -> 0 <= x < two_p (Zsize x).
Lemma Zsize_interval_2:
forall x n, 0 <= n -> 0 <= x < two_p n -> n >= Zsize x.
Lemma Zsize_monotone:
forall x y, 0 <= x <= y -> Zsize x <= Zsize y.
Theorem size_zero: size zero = 0.
Theorem bits_size_1:
forall x, x = zero \/ testbit x (Z.pred (size x)) = true.
Theorem bits_size_2:
forall x i, size x <= i -> testbit x i = false.
Theorem size_range:
forall x, 0 <= size x <= zwordsize.
Theorem bits_size_3:
forall x n,
0 <= n ->
(forall i, n <= i < zwordsize -> testbit x i = false) ->
size x <= n.
Theorem bits_size_4:
forall x n,
0 <= n ->
testbit x (Z.pred n) = true ->
(forall i, n <= i < zwordsize -> testbit x i = false) ->
size x = n.
Theorem size_interval_1:
forall x, 0 <= unsigned x < two_p (size x).
Theorem size_interval_2:
forall x n, 0 <= n -> 0 <= unsigned x < two_p n -> n >= size x.
Theorem size_and:
forall a b, size (and a b) <= Z.min (size a) (size b).
Corollary and_interval:
forall a b, 0 <= unsigned (and a b) < two_p (Z.min (size a) (size b)).
Theorem size_or:
forall a b, size (or a b) = Z.max (size a) (size b).
Corollary or_interval:
forall a b, 0 <= unsigned (or a b) < two_p (Z.max (size a) (size b)).
Theorem size_xor:
forall a b, size (xor a b) <= Z.max (size a) (size b).
Corollary xor_interval:
forall a b, 0 <= unsigned (xor a b) < two_p (Z.max (size a) (size b)).