intros; elim (Zdiv_rest_correct x p); intros q r; elim r;
[ intros Hx Hr; exists q; rewrite Hx; rewrite <- Zplus_0_r_reverse; split;
[ apply Zmult_gt_0_lt_compat_r;
[ compute in |- *; reflexivity | apply Zlt_pred ]
| apply Zle_refl ]
| intros p0 Hx Hr1 Hr2; exists (Zsucc q); rewrite Hx; split;
[ replace (Zpred (Zsucc q) * two_power_pos p)%Z with
(q * two_power_pos p + 0)%Z;
[ apply Zplus_lt_compat_l; compute in |- *; reflexivity
| rewrite <- Zpred_succ; rewrite <- Zplus_0_r_reverse; reflexivity ]
| unfold Zsucc in |- *; rewrite Zmult_plus_distr_l;
apply Zplus_le_compat_l; rewrite Zmult_1_l;
apply Zlt_le_weak; assumption ]
| intros p0 Hx Hr1 Hr2; absurd (Datatypes.Gt = Datatypes.Gt);
[ exact Hr1 | reflexivity ] ].
Qed.
Definition ZROUND_sup (p : positive) (x : Z) :=
let (x', p) := ZROUND_sup_spec p x in x'.

(* Specifications: *)
Lemma ZROUND_correct :
forall (m : rounding_mode) (p : positive) (x : Z),
{y : Z |
match m with
| Rounding_inf => (y * two_power_pos p <= x < Zsucc y * two_power_pos p)%Z
| Rounding_sup => (Zpred y * two_power_pos p < x <= y * two_power_pos p)%Z
| Rounding_nearest =>
match (x - ZROUND_inf p x ?= ZROUND_sup p x - x)%Z with
| Datatypes.Eq =>
if Zeven.Zeven_bool (ZROUND_inf p x)
then (y * two_power_pos p <= x < Zsucc y * two_power_pos p)%Z
else (Zpred y * two_power_pos p < x <= y * two_power_pos p)%Z
| Datatypes.Gt =>
(Zpred y * two_power_pos p < x <= y * two_power_pos p)%Z
| Datatypes.Lt =>
(y * two_power_pos p <= x < Zsucc y * two_power_pos p)%Z
end
| Rounding_zero =>
match x with
| Zpos _ => (y * two_power_pos p <= x < Zsucc y * two_power_pos p)%Z
| Z0 => y = 0%Z
| Zneg _ => (Zpred y * two_power_pos p < x <= y * two_power_pos p)%Z
end
end}.