#[global]
Hint Resolve two_p_gt_ZERO: zarith.
#[global]
Hint Immediate two_p_pred two_p_S: zarith.
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.

(* Specifications: *)
Lemma Zdiv_rest_correct1 (x:Z) (p:positive) :
let (_, d) := Pos.iter Zdiv_rest_aux (x, 0, 1) p in
d = two_power_pos p.
Lemma Zdiv_rest_correct2 (x:Z) (p:positive) :
let '(q,r,d) := Pos.iter Zdiv_rest_aux (x, 0, 1) p in
x = q * d + r /\ 0 <= r < d.