(** * 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.