Section Powers_of_2.
(** * Powers of 2 *)
(** For the powers of two, that will be widely used, a more direct calculus is possible. [shift n m] computes [2^n * m], i.e. [m] shifted by [n] positions *)
Definition shift_nat (n:nat) (z:positive) := nat_rect _ z (fun _ => xO) n.
Definition shift_pos (n z:positive) := Pos.iter xO z n.
Definition shift (n:Z) (z:positive) :=
match n with
| Z0 => z
| Zpos p => Pos.iter xO z p
| Zneg p => z
end.
Definition two_power_nat (n:nat) := Zpos (shift_nat n 1).
Definition two_power_pos (x:positive) := Zpos (shift_pos x 1).
Definition two_p (x:Z) :=
match x with
| Z0 => 1
| Zpos y => two_power_pos y
| Zneg y => 0
end.
(** Equivalence with notions defined in BinInt *)
(** Properties of these old versions of powers of two *)
Proof (two_p_equiv x).

Theorem two_p_is_exp x y :
0 <= x -> 0 <= y -> two_p (x + y) = two_p x * two_p y.