Section definitions.
Variable radix : Z.
Hypothesis radixMoreThanOne : (1 < radix)%Z.
Let radixMoreThanZERO := Zlt_1_O _ (Zlt_le_weak _ _ radixMoreThanOne).
Hint Resolve radixMoreThanZERO: zarith.
(* The type float represents the set of numbers who can be written: x = n*b^p with  n and p in Z. (pdic numbers) n = Fnum and p = Fexp 						*)
Record float : Set := Float {Fnum : Z; Fexp : Z}.
intros p q; case p; case q; simpl in |- *; intros;
apply (f_equal2 (A1:=Z) (A2:=Z)); auto.
Qed.
intros x y; case x; case y; intros Fnum2 Fexp2 Fnum1 Fexp1.
case (Z.eq_dec Fnum1 Fnum2); intros H1.
case (Z.eq_dec Fexp1 Fexp2); intros H2.
left; apply floatEq; auto.
right; red in |- *; intros H'; Contradict H2; inversion H'; auto.
right; red in |- *; intros H'; Contradict H1; inversion H'; auto.
Qed.
Definition Fzero (x : Z) := Float 0 x.
Definition is_Fzero (x : float) := Fnum x = 0%Z.
unfold is_Fzero in |- *; intro; CaseEq (Fnum x); intros;
(right; discriminate) || (left; auto).
Qed.
Coercion IZR : Z >-> R.
Coercion INR : nat >-> R.
Coercion Z_of_nat : nat >-> Z.
Definition FtoR (x : float) := (Fnum x * powerRZ (IZR radix) (Fexp x))%R.
Local Coercion FtoR : float >-> R.
intros z; unfold FtoR in |- *; simpl in |- *; auto with real.
Qed.
intros x H; unfold FtoR in |- *.
red in H; rewrite H; simpl in |- *; auto with real.
Qed.
intros x; case x; unfold FtoR in |- *; simpl in |- *.
intros Fnum1 Fexp1 H'; replace 0%R with (Fnum1 * 0)%R;
[ apply Rmult_lt_compat_l | ring ]; auto with real zarith.
Qed.
intros x H'.
case (Rmult_integral _ _ H'); simpl in |- *; auto.
case x; simpl in |- *.
intros Fnum1 Fexp1 H'0; red in |- *; simpl in |- *; auto with real zarith.
apply eq_IZR_R0; auto.
intros H'0; Contradict H'0; apply powerRZ_NOR; auto with real zarith.
Qed.
intros x y H' H'0; Contradict H'.
apply is_Fzero_rep2; auto.
rewrite H'0.
apply is_Fzero_rep1; auto.
Qed.
(* Some inegalities that will be helpful *)
intros x y z H'; apply Rmult_lt_compat_r; auto with real zarith.
Qed.
intros x y z H'; apply Rmult_le_compat_r; auto with real zarith.
Qed.
intros x y z H'; apply Rmult_lt_reg_l with (r := powerRZ radix z);
auto with real zarith.
repeat rewrite (Rmult_comm (powerRZ radix z)); auto.
Qed.
intros x y z H'; apply Rmult_le_reg_l with (r := powerRZ radix z);
auto with real zarith.
repeat rewrite (Rmult_comm (powerRZ radix z)); auto.
Qed.
intros p q H' H'0 H'1.
apply floatEq; auto.
unfold FtoR in H'0.
apply Rpow_eq_inv with (r := IZR radix); auto 6 with real zarith.
apply Rlt_dichotomy_converse; right; red in |- *.
unfold Rabs in |- *; case (Rcase_abs radix).
intros H'2; Contradict H'2; apply Rle_not_lt; apply Ropp_le_cancel;
auto with real.
intros H'2; replace 1%R with (IZR 1); auto with real zarith.
apply Rmult_eq_reg_l with (r := IZR (Fnum p)); auto with real.
pattern (Fnum p) at 2 in |- *; rewrite H'1; auto.
Qed.
intros p q H' H'0.
apply floatEq; auto.
apply eq_IZR; auto.
apply Rmult_eq_reg_l with (r := powerRZ radix (Fexp p));
auto with real zarith.
repeat rewrite (Rmult_comm (powerRZ radix (Fexp p)));
pattern (Fexp p) at 2 in |- *; rewrite H'0; auto with real zarith.
Qed.
intros p q r H'.
apply lt_IZR.
apply Rlt_monotony_contra_exp with (z := r); auto with real.
Qed.
intros p q r H'.
apply le_IZR.
apply Rle_monotony_contra_exp with (z := r); auto with real.
Qed.
(* Properties for floats with 1 as mantissa *)
intros x y H'; unfold FtoR in |- *; simpl in |- *.
repeat rewrite Rmult_1_l; auto with real zarith.
apply Rle_powerRZ; try replace 1%R with (IZR 1); auto with real zarith zarith.
Qed.
intros x y H'; unfold FtoR in |- *; simpl in |- *.
repeat rewrite Rmult_1_l; auto with real zarith.
Qed.
intros x y H'; case (Zle_or_lt y x); auto; intros ZH; Contradict H'.
apply Rle_not_lt; apply oneExp_le; auto.
Qed.
intros x y H'; case (Zle_or_lt x y); auto; intros ZH; Contradict H'.
apply Rgt_not_le; red in |- *; apply oneExp_lt; auto.
Qed.
Definition Fdigit (p : float) := digit radix (Fnum p).
Definition Fshift (n : nat) (x : float) :=
Float (Fnum x * Zpower_nat radix n) (Fexp x - n).
intros p q; case p; case q; unfold FtoR in |- *; simpl in |- *.
intros Fnum1 Fexp1 Fnum2 Fexp2 H' H'0; rewrite H'0; rewrite H'0 in H'.
cut (Fnum1 = Fnum2).
intros H'1; rewrite <- H'1; auto.
apply eq_IZR; auto.
apply Rmult_eq_reg_l with (r := powerRZ radix Fexp1);
repeat rewrite (Rmult_comm (powerRZ radix Fexp1));
auto.
apply Rlt_dichotomy_converse; right; auto with real.
red in |- *; auto with real.
Qed.
intros n x; case x; unfold Fshift, Fdigit, is_Fzero in |- *; simpl in |- *.
intros p1 p2 H; apply digitAdd; auto.
Qed.
intros n x; unfold FtoR in |- *; simpl in |- *.
rewrite Rmult_IZR.
rewrite Zpower_nat_Z_powerRZ; auto.
repeat rewrite Rmult_assoc.
rewrite <- powerRZ_add; auto with real zarith.
rewrite Zplus_minus; auto.
Qed.

Theorem FshiftCorrectInv :
forall x y : float,
x = y :>R ->
(Fexp x <= Fexp y)%Z -> Fshift (Z.abs_nat (Fexp y - Fexp x)) y = x.