Section power_div_with_rest.
(** * Division by a power of two. *)
(** To [x:Z] and [p:positive], [q],[r] are associated such that [x = 2^p.q + r] and [0 <= r < 2^p] *)
(** Invariant: [d*q + r = d'*q + r /\ d' = 2*d /\ 0<=r<d /\ 0<=r'<d'] *)
Definition Zdiv_rest_aux (qrd:Z * Z * Z) :=
let '(q,r,d) := qrd in
(match q with
| Z0 => (0, r)
| Zpos xH => (0, d + r)
| Zpos (xI n) => (Zpos n, d + r)
| Zpos (xO n) => (Zpos n, r)
| Zneg xH => (-1, d + r)
| Zneg (xI n) => (Zneg n - 1, d + r)
| Zneg (xO n) => (Zneg n, r)
end, 2 * d).
Definition Zdiv_rest (x:Z) (p:positive) :=
let (qr, d) := Pos.iter Zdiv_rest_aux (x, 0, 1) p in qr.
(** Old-style rich specification by proof of existence *)
Inductive Zdiv_rest_proofs (x:Z) (p:positive) : Set :=
Zdiv_rest_proof :
forall q r:Z,
x = q * two_power_pos p + r ->
0 <= r -> r < two_power_pos p -> Zdiv_rest_proofs x p.
(** Direct correctness of [Zdiv_rest] *)

Lemma Zdiv_rest_ok x p :
let (q,r) := Zdiv_rest x p in
x = q * 2^(Zpos p) + r /\ 0 <= r < 2^(Zpos p).