mirror of
https://github.com/AdaCore/why3.git
synced 2026-02-12 12:34:55 -08:00
5010 lines
153 KiB
Coq
5010 lines
153 KiB
Coq
(********************************************************************)
|
|
(* *)
|
|
(* The Why3 Verification Platform / The Why3 Development Team *)
|
|
(* Copyright 2010-2025 -- Inria - CNRS - Paris-Saclay University *)
|
|
(* *)
|
|
(* This software is distributed under the terms of the GNU Lesser *)
|
|
(* General Public License version 2.1, with the special exception *)
|
|
(* on linking described in file LICENSE. *)
|
|
(********************************************************************)
|
|
|
|
(* This file is generated by Why3's Coq-realize driver *)
|
|
(* Beware! Only edit allowed sections below *)
|
|
Require Import BuiltIn.
|
|
Require Reals.Rbasic_fun.
|
|
Require Reals.R_sqrt.
|
|
Require BuiltIn.
|
|
Require int.Int.
|
|
Require real.Real.
|
|
Require real.RealInfix.
|
|
Require real.Abs.
|
|
Require real.FromInt.
|
|
Require real.Truncate.
|
|
Require real.Square.
|
|
Require bv.Pow2int.
|
|
Require ieee_float.RoundingMode.
|
|
|
|
Require Import Psatz.
|
|
Require Import ZArith Reals.
|
|
Require Import Flocq.Core.Core.
|
|
Require Import Flocq.IEEE754.BinarySingleNaN.
|
|
Require Import Flocq.Calc.Bracket.
|
|
Require Import Flocq.Calc.Round.
|
|
Require Import Flocq.Prop.Plus_error.
|
|
Require Flocq.Prop.Sterbenz.
|
|
Import real.Truncate.
|
|
Import ieee_float.RoundingMode.
|
|
|
|
Arguments B754_zero {prec} {emax}.
|
|
Arguments B754_infinity {prec} {emax}.
|
|
Arguments B754_nan {prec} {emax}.
|
|
Arguments B754_finite {prec} {emax}.
|
|
|
|
Local Open Scope R_scope.
|
|
|
|
Definition mode_to_IEEE : mode -> BinarySingleNaN.mode.
|
|
exact (fun m =>
|
|
match m with
|
|
| RNE => mode_NE
|
|
| RNA => mode_NA
|
|
| RTP => mode_UP
|
|
| RTN => mode_DN
|
|
| RTZ => mode_ZR
|
|
end).
|
|
Defined.
|
|
|
|
Coercion mode_to_IEEE : mode >-> BinarySingleNaN.mode.
|
|
|
|
Section GenericFloat.
|
|
|
|
Variable eb_pos sb_pos : positive.
|
|
|
|
(* Why3 goal *)
|
|
Definition eb : Numbers.BinNums.Z.
|
|
Proof.
|
|
exact (Z.pos eb_pos).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition sb : Numbers.BinNums.Z.
|
|
Proof.
|
|
exact (Z.pos sb_pos).
|
|
Defined.
|
|
|
|
Hypothesis Heb : Zlt_bool 1 eb = true.
|
|
Hypothesis Hsbb : Zlt_bool 1 sb = true.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eb_gt_1 : (1%Z < eb)%Z.
|
|
Proof.
|
|
rewrite Zlt_is_lt_bool.
|
|
apply Heb.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sb_gt_1 : (1%Z < sb)%Z.
|
|
Proof.
|
|
rewrite Zlt_is_lt_bool.
|
|
apply Hsbb.
|
|
Qed.
|
|
|
|
(* power of infinities *)
|
|
Definition emax : Z.
|
|
Proof.
|
|
exact (radix2 ^ (eb - 1))%Z.
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition t : Type.
|
|
Proof.
|
|
exact (binary_float sb emax).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition zeroF : t.
|
|
Proof.
|
|
exact (B754_zero false).
|
|
Defined.
|
|
|
|
Definition emin := (3 - emax - sb)%Z.
|
|
Notation fexp := (FLT_exp emin sb).
|
|
|
|
Lemma Hsb : Zlt_bool 0 sb = true.
|
|
Proof.
|
|
auto with zarith.
|
|
Qed.
|
|
|
|
Lemma Hsb': (0 < sb)%Z.
|
|
Proof.
|
|
unfold sb; auto with zarith.
|
|
Qed.
|
|
|
|
Hypothesis Hemax : Zlt_bool sb emax = true.
|
|
|
|
Lemma Hemax': (sb < emax)%Z.
|
|
Proof.
|
|
rewrite Zlt_is_lt_bool.
|
|
apply Hemax.
|
|
Qed.
|
|
|
|
Instance Hsb'' : Prec_gt_0 sb := Hsb'.
|
|
|
|
Lemma fexp_Valid : Valid_exp fexp.
|
|
Proof.
|
|
apply (fexp_correct _ _ Hsb'').
|
|
Qed.
|
|
|
|
Definition r_to_fp rnd x : binary_float sb emax :=
|
|
let r := round radix2 fexp (round_mode rnd) x in
|
|
let m := Ztrunc (scaled_mantissa radix2 fexp r) in
|
|
let e := cexp radix2 fexp r in
|
|
binary_normalize sb emax Hsb' Hemax' rnd m e false.
|
|
|
|
Theorem r_to_fp_correct :
|
|
forall rnd x,
|
|
let r := round radix2 fexp (round_mode rnd) x in
|
|
(Rabs r < bpow radix2 emax)%R ->
|
|
is_finite (r_to_fp rnd x) = true /\
|
|
B2R (r_to_fp rnd x) = r.
|
|
Proof with auto with typeclass_instances.
|
|
intros rnd x r Bx.
|
|
unfold r_to_fp. fold r.
|
|
generalize (binary_normalize_correct sb emax Hsb' Hemax' rnd (Ztrunc (scaled_mantissa radix2 fexp r)) (cexp radix2 fexp r) false).
|
|
unfold r.
|
|
elim generic_format_round...
|
|
fold emin r.
|
|
rewrite round_generic...
|
|
rewrite Rlt_bool_true with (1 := Bx).
|
|
now split.
|
|
apply generic_format_round...
|
|
Qed.
|
|
|
|
Theorem r_to_fp_format :
|
|
forall rnd x,
|
|
FLT_format radix2 emin sb x ->
|
|
(Rabs x < bpow radix2 emax)%R ->
|
|
B2R (r_to_fp rnd x) = x.
|
|
Proof with auto with typeclass_instances.
|
|
intros rnd x Fx Bx.
|
|
assert (Gx: generic_format radix2 fexp x).
|
|
apply generic_format_FLT.
|
|
apply Fx.
|
|
pattern x at 2 ; rewrite <- round_generic with (rnd := round_mode rnd) (2 := Gx)...
|
|
refine (proj2 (r_to_fp_correct _ _ _)).
|
|
rewrite round_generic...
|
|
Qed.
|
|
|
|
Lemma max_eb_bounded : SpecFloat.bounded sb emax (2 ^ sb_pos - 1) (emax - sb) = true.
|
|
Proof.
|
|
assert (0 <= sb - 1)%Z.
|
|
apply Zlt_0_le_0_pred, Hsb'.
|
|
unfold SpecFloat.bounded; apply Bool.andb_true_iff; split.
|
|
unfold SpecFloat.canonical_mantissa, SpecFloat.fexp, FLT_exp, SpecFloat.emin.
|
|
apply Zeq_bool_true.
|
|
rewrite Digits.Zpos_digits2_pos.
|
|
rewrite (Digits.Zdigits_unique radix2 _ sb).
|
|
assert (sb + (emax - sb) - sb = emax - sb)%Z by ring; rewrite H0.
|
|
apply Zmax_left.
|
|
assert (1 < emax)%Z.
|
|
apply Z.le_lt_trans with (m := sb).
|
|
change (Z.succ 0 <= sb)%Z; apply Zgt_le_succ; easy.
|
|
apply Hemax'.
|
|
auto with zarith.
|
|
rewrite Z.abs_eq by auto with zarith.
|
|
change ((2 ^ (sb - 1) <= Z.pos (2 ^ sb_pos - 1) < 2 ^ sb)%Z).
|
|
assert (Z.pos (2 ^ sb_pos - 1) = 2 ^ sb -1)%Z.
|
|
rewrite Pos2Z.inj_sub, Pos2Z.inj_pow.
|
|
fold sb; reflexivity.
|
|
apply Pos.pow_gt_1; easy.
|
|
rewrite H0.
|
|
split; auto with zarith.
|
|
assert (sb = Z.succ (sb - 1)) by auto with zarith.
|
|
rewrite H1 at 2.
|
|
rewrite Z.pow_succ_r by trivial.
|
|
assert (1 <= 2 ^ (sb - 1))%Z.
|
|
apply Z.lt_pred_le, (Zpower_gt_0 radix2 (sb - 1)); trivial.
|
|
lia.
|
|
apply Zle_bool_true; auto with zarith.
|
|
Qed.
|
|
|
|
Definition max_value: t.
|
|
Proof.
|
|
exact (B754_finite false (2 ^ sb_pos - 1) (emax - sb) max_eb_bounded).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition add : ieee_float.RoundingMode.mode -> t -> t -> t.
|
|
Proof.
|
|
exact (@Bplus sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition sub : ieee_float.RoundingMode.mode -> t -> t -> t.
|
|
Proof.
|
|
exact (@Bminus sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition mul : ieee_float.RoundingMode.mode -> t -> t -> t.
|
|
Proof.
|
|
exact (@Bmult sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition div : ieee_float.RoundingMode.mode -> t -> t -> t.
|
|
Proof.
|
|
exact (@Bdiv sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition abs : t -> t.
|
|
Proof.
|
|
exact (@Babs sb emax).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition neg : t -> t.
|
|
Proof.
|
|
exact (@Bopp sb emax).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition fma : ieee_float.RoundingMode.mode -> t -> t -> t -> t.
|
|
Proof.
|
|
exact (@Bfma sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition sqrt : ieee_float.RoundingMode.mode -> t -> t.
|
|
Proof.
|
|
exact (@Bsqrt sb emax Hsb' Hemax').
|
|
Defined.
|
|
|
|
Definition z_to_fp m x := binary_normalize sb emax Hsb' Hemax' (mode_to_IEEE m) x 0 false.
|
|
|
|
Definition fp_to_z: mode -> t -> Z.
|
|
Proof.
|
|
exact (fun m x => match m with
|
|
| RNA => ZnearestA
|
|
| RNE => ZnearestE
|
|
| RTP => Zceil
|
|
| RTN => Zfloor
|
|
| RTZ => Ztrunc
|
|
end (B2R x)).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition roundToIntegral : ieee_float.RoundingMode.mode -> t -> t.
|
|
Proof.
|
|
exact (fun m x =>
|
|
match x with
|
|
| B754_zero b => x
|
|
| B754_infinity b => x
|
|
| B754_nan => x
|
|
| B754_finite b ma e _ =>
|
|
let x_int := fp_to_z m x in
|
|
match Z.eq_dec x_int 0%Z with
|
|
| left _ => B754_zero b
|
|
| right _ => z_to_fp RTZ x_int
|
|
end
|
|
end).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition min : t -> t -> t.
|
|
Proof.
|
|
exact (fun x y => match Bcompare x y with
|
|
| Some Lt => x
|
|
| Some Gt | Some Eq => y
|
|
| None => B754_nan
|
|
end).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition max : t -> t -> t.
|
|
Proof.
|
|
exact (fun x y => match Bcompare x y with
|
|
| Some Lt => y
|
|
| Some Gt | Some Eq => x
|
|
| None => B754_nan
|
|
end).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition le : t -> t -> Prop.
|
|
Proof.
|
|
exact (fun a b => match Bcompare a b with Some Lt | Some Eq => True | _ => False end).
|
|
Defined.
|
|
|
|
Hint Unfold le.
|
|
|
|
(* Why3 goal *)
|
|
Definition lt : t -> t -> Prop.
|
|
Proof.
|
|
exact (fun a b => Bcompare a b = Some Lt).
|
|
Defined.
|
|
|
|
Hint Unfold lt.
|
|
|
|
Lemma gt_bcompare : forall {x y}, lt y x <-> Bcompare x y = Some Gt.
|
|
Proof.
|
|
intros x y.
|
|
rewrite Bcompare_swap.
|
|
unfold lt.
|
|
destruct Bcompare.
|
|
destruct c; simpl; split; intro h; inversion h; auto.
|
|
split; intro h; inversion h; auto.
|
|
Qed.
|
|
|
|
(*
|
|
Lemma ge_bcompare : forall {x y}, le y x <-> Bcompare _ _ x y = Some Gt \/ Bcompare _ _ x y = Some Eq.
|
|
Proof.
|
|
intros x y.
|
|
unfold le.
|
|
rewrite <-gt_bcompare.
|
|
assert (Bcompare _ _ y x = Some Eq <-> Bcompare _ _ x y = Some Eq).
|
|
rewrite Bcompare_swap.
|
|
destruct Bcompare; try (split; now auto).
|
|
destruct c; simpl; split; intro h; inversion h; auto.
|
|
rewrite H; reflexivity.
|
|
Qed.
|
|
*)
|
|
|
|
(* Why3 goal *)
|
|
Definition eq : t -> t -> Prop.
|
|
Proof.
|
|
exact (fun a b => Bcompare a b = Some Eq).
|
|
Defined.
|
|
|
|
Hint Unfold eq.
|
|
|
|
Lemma le_correct: forall x y, le x y <-> lt x y \/ eq x y.
|
|
Proof.
|
|
intros x y; unfold lt, le, eq.
|
|
destruct Bcompare as [[ | | ] | ] ; split ; try easy.
|
|
now right.
|
|
now left.
|
|
now intros [|].
|
|
now intros [|].
|
|
Qed.
|
|
|
|
Lemma lt_le: forall {x y}, lt x y -> le x y.
|
|
Proof.
|
|
intros x y.
|
|
rewrite le_correct; auto.
|
|
Qed.
|
|
|
|
Lemma eq_zero_iff: forall {x}, eq zeroF x <-> x = zeroF \/ x = neg zeroF.
|
|
Proof.
|
|
intro; unfold eq; destruct x; simpl; try destruct s; simpl.
|
|
split; auto.
|
|
split; auto.
|
|
split; [easy| intro h; destruct h; easy].
|
|
split; [easy| intro h; destruct h; easy].
|
|
split; [easy| intro h; destruct h; easy].
|
|
split; [easy| intro h; destruct h; easy].
|
|
split; [easy| intro h; destruct h; easy].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_normal : t -> Prop.
|
|
Proof.
|
|
exact (fun x => match x with
|
|
| B754_zero _ => True
|
|
| B754_finite _ _ e _ => (emin < e)%Z
|
|
| _ => False
|
|
end).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_subnormal : t -> Prop.
|
|
Proof.
|
|
exact (fun x => match x with
|
|
| B754_finite _ _ e _ => (emin = e)%Z
|
|
| _ => False
|
|
end).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_zero : t -> Prop.
|
|
Proof.
|
|
exact (fun x => eq zeroF x).
|
|
Defined.
|
|
|
|
Lemma zero_is_zero: forall {b}, is_zero (B754_zero b).
|
|
Proof.
|
|
easy.
|
|
Qed.
|
|
|
|
Lemma is_zero_B754_zero :
|
|
forall x, is_zero x <-> exists b, x = B754_zero b.
|
|
Proof.
|
|
intro.
|
|
unfold is_zero; rewrite eq_zero_iff.
|
|
unfold zeroF.
|
|
simpl neg.
|
|
split; intro h; destruct h; auto; try easy.
|
|
exists false; assumption.
|
|
exists true; assumption.
|
|
destruct x0;[right|left];auto.
|
|
Qed.
|
|
|
|
Lemma zero_or_not : forall x, ~ is_zero x \/ is_zero x.
|
|
Proof.
|
|
destruct x.
|
|
- now right.
|
|
- left. now destruct s.
|
|
- now left.
|
|
- left. now destruct s.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_infinite : t -> Prop.
|
|
Proof.
|
|
exact (fun x => match x with
|
|
| B754_infinity _ => True
|
|
| _ => False
|
|
end).
|
|
Defined.
|
|
|
|
Coercion is_true : bool >-> Sortclass.
|
|
|
|
Lemma eq_infinite_dist: forall {x y}, eq x y -> is_infinite x -> is_infinite y.
|
|
Proof.
|
|
intros; destruct x, y; try easy; destruct s; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_nan : t -> Prop.
|
|
Proof.
|
|
exact is_nan.
|
|
Defined.
|
|
|
|
Lemma is_infinite_not_nan: forall {x}, is_infinite x -> ~ is_nan x.
|
|
Proof.
|
|
intro x; destruct x; easy.
|
|
Qed.
|
|
|
|
Lemma le_infinity: forall {x}, ~ is_nan x -> le x (B754_infinity false).
|
|
Proof.
|
|
intros.
|
|
unfold le.
|
|
destruct x; try easy.
|
|
+ now destruct s.
|
|
+ now elim H.
|
|
Qed.
|
|
|
|
Lemma is_nan_dec: forall x, {is_nan x} + {~ is_nan x}.
|
|
Proof.
|
|
intro; destruct x; compute; intuition.
|
|
Qed.
|
|
|
|
Lemma eq_not_nan_refl: forall {x : t}, ~ is_nan x -> eq x x.
|
|
Proof.
|
|
intros; destruct x; auto.
|
|
destruct s; auto.
|
|
destruct H; easy.
|
|
unfold eq.
|
|
rewrite Bcompare_correct by easy.
|
|
now rewrite Rcompare_Eq.
|
|
Qed.
|
|
|
|
Lemma eq_not_nan: forall {x y}, eq x y -> ~ is_nan x /\ ~ is_nan y.
|
|
Proof.
|
|
intros; destruct x; destruct y; easy.
|
|
Qed.
|
|
|
|
Lemma lt_not_nan: forall {x y}, lt x y -> ~ is_nan x /\ ~ is_nan y.
|
|
Proof.
|
|
intros; destruct x, y; easy.
|
|
Qed.
|
|
|
|
Lemma le_or_lt_or_nan: forall x y, le x y \/ lt y x \/ is_nan x \/ is_nan y.
|
|
Proof.
|
|
unfold is_nan, le, lt.
|
|
intros x y.
|
|
rewrite Bcompare_swap.
|
|
case_eq (Bcompare y x).
|
|
intros [| |] ; try now left.
|
|
now (right ; left).
|
|
destruct x, y; auto; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_positive : t -> Prop.
|
|
Proof.
|
|
exact (fun x => match x with
|
|
| B754_zero false => True
|
|
| B754_finite false _ e _ => True
|
|
| B754_infinity false => True
|
|
| _ => False
|
|
end).
|
|
Defined.
|
|
|
|
Hint Unfold is_positive.
|
|
|
|
Lemma is_positive_Bsign: forall x, ~ is_nan x -> (is_positive x <-> Bsign x = false).
|
|
Proof.
|
|
split.
|
|
destruct x; try destruct s; try easy.
|
|
destruct x; try destruct s; try easy.
|
|
contradict H; easy.
|
|
Qed.
|
|
|
|
Lemma is_positive_correct: forall x, is_positive x <-> lt zeroF x \/ x = B754_zero false.
|
|
Proof.
|
|
split.
|
|
intro h; destruct x; try destruct s; auto; easy.
|
|
intro h; destruct h; destruct x; try destruct s; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_negative : t -> Prop.
|
|
Proof.
|
|
exact (fun x => match x with
|
|
| B754_zero true => True
|
|
| B754_finite true _ e _ => True
|
|
| B754_infinity true => True
|
|
| _ => False
|
|
end).
|
|
Defined.
|
|
|
|
Hint Unfold is_negative.
|
|
|
|
Lemma is_negative_Bsign: forall x, ~ is_nan x -> (is_negative x <-> Bsign x = true).
|
|
Proof.
|
|
split.
|
|
destruct x; try destruct s; easy.
|
|
destruct x; try destruct s; easy.
|
|
Qed.
|
|
|
|
Lemma is_negative_correct: forall x, is_negative x <-> lt x zeroF \/ x = B754_zero true.
|
|
Proof.
|
|
split.
|
|
intro h; destruct x; try destruct s; auto; easy.
|
|
intro h; destruct h; destruct x; try destruct s; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_finite : t -> Prop.
|
|
Proof.
|
|
exact is_finite.
|
|
Defined.
|
|
|
|
Lemma not_nan: forall x, ~ (is_nan x) -> {is_finite x} + {is_infinite x}.
|
|
Proof.
|
|
unfold is_nan, is_finite.
|
|
intro x; try destruct x; simpl; intro; auto.
|
|
Qed.
|
|
|
|
Lemma is_finite_not_nan: forall {x}, is_finite x -> ~ is_nan x.
|
|
Proof.
|
|
intro x; destruct x; easy.
|
|
Qed.
|
|
|
|
Lemma Finite_Infinite_Nan_dec: forall x:t, {is_finite x} + {is_infinite x} + {is_nan x}.
|
|
Proof.
|
|
intro x; destruct x; simpl.
|
|
left; left; easy.
|
|
left; right; easy.
|
|
right; easy.
|
|
left; left; easy.
|
|
Qed.
|
|
|
|
Lemma eq_finite_dist: forall {x y}, eq x y -> is_finite x -> is_finite y.
|
|
Proof.
|
|
intros; destruct x, y; try easy; destruct s0; easy.
|
|
Qed.
|
|
|
|
Lemma bounded_floats :
|
|
forall x:t, (is_finite x) ->
|
|
Bcompare (abs x) max_value = Some Lt
|
|
\/ Bcompare (abs x) max_value = Some Eq.
|
|
Proof.
|
|
destruct x; try easy; auto; (* simpl; *) intros.
|
|
destruct (andb_prop _ _ e0) as (H1,H2).
|
|
generalize (Zeq_bool_eq _ _ H1); clear H1; intro H1.
|
|
generalize (Zle_bool_imp_le _ _ H2); clear H2; intro H2.
|
|
destruct (Z_le_lt_eq_dec _ _ H2); clear H2.
|
|
unfold Bcompare.
|
|
simpl; rewrite (Zcompare_Lt _ _ l); auto.
|
|
unfold Bcompare.
|
|
simpl; rewrite (Zcompare_Eq _ _ e1).
|
|
unfold SpecFloat.fexp, FLT_exp, SpecFloat.emin in H1.
|
|
rewrite Digits.Zpos_digits2_pos in H1.
|
|
assert (3 - emax - sb <= Digits.Zdigits radix2 (Z.pos m) + e - sb)%Z.
|
|
rewrite e1.
|
|
pose sb_gt_1. pose Hemax'.
|
|
assert (Z.pos m <> 0)%Z. pose (Pos2Z.is_pos m); auto with zarith.
|
|
pose (Digits.Zdigits_gt_0 radix2 (Z.pos m) H0).
|
|
auto with zarith.
|
|
rewrite <-Z.max_l_iff in H0.
|
|
rewrite H0 in H1; clear H0.
|
|
assert (Digits.Zdigits radix2 (Z.pos m) = sb) by auto with zarith; clear H1.
|
|
pose (Digits.Zdigits_correct radix2 (Z.pos m)).
|
|
rewrite H0 in a.
|
|
replace (Z.abs (Z.pos m)) with (Z.pos m) in a by auto with zarith.
|
|
destruct a. clear H1.
|
|
assert (Z.pos m = radix2 ^ sb - 1 \/ Z.pos m < radix2 ^ sb - 1)%Z by lia.
|
|
destruct H1.
|
|
right.
|
|
replace (radix2 ^ sb)%Z with (Z.pos 2 ^ Z.pos sb_pos)%Z in H1 by auto.
|
|
rewrite <-Pos2Z.inj_pow, <-Pos2Z.inj_sub, <-Zpos_eq_iff in H1.
|
|
rewrite H1.
|
|
rewrite Pcompare_refl; reflexivity.
|
|
apply Pos.pow_gt_1; easy.
|
|
left.
|
|
rewrite nat_of_P_lt_Lt_compare_complement_morphism. reflexivity.
|
|
apply Pos2Nat.inj_lt.
|
|
replace (radix2 ^ sb)%Z with (Z.pos 2 ^ Z.pos sb_pos)%Z in H1 by auto.
|
|
rewrite <-Pos2Z.inj_pow, <-Pos2Z.inj_sub in H1.
|
|
auto with zarith.
|
|
apply Pos.pow_gt_1; easy.
|
|
Qed.
|
|
|
|
Lemma bounded_floats_le: forall x, is_finite x -> le (abs x) max_value.
|
|
Proof.
|
|
intros x Fx.
|
|
unfold le.
|
|
now destruct (bounded_floats x Fx) as [-> | ->].
|
|
Qed.
|
|
|
|
Lemma is_finite_B: forall (x:t),
|
|
is_finite x ->
|
|
exists b, x = B754_zero b \/ exists b m e p, x = B754_finite b m e p.
|
|
Proof.
|
|
intro x.
|
|
destruct x; try easy; intros.
|
|
exists s; auto.
|
|
exists s; right.
|
|
exists s, m, e, e0; trivial.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition is_plus_infinity (x:t) : Prop := is_infinite x /\ is_positive x.
|
|
|
|
(* Why3 assumption *)
|
|
Definition is_minus_infinity (x:t) : Prop := is_infinite x /\ is_negative x.
|
|
|
|
(* Why3 assumption *)
|
|
Definition is_plus_zero (x:t) : Prop := is_zero x /\ is_positive x.
|
|
|
|
(* Why3 assumption *)
|
|
Definition is_minus_zero (x:t) : Prop := is_zero x /\ is_negative x.
|
|
|
|
(* Why3 assumption *)
|
|
Definition is_not_nan (x:t) : Prop := is_finite x \/ is_infinite x.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_not_nan1 : forall (x:t), is_not_nan x <-> ~ is_nan x.
|
|
Proof.
|
|
unfold is_not_nan; split; intro H.
|
|
destruct H; [apply is_finite_not_nan|apply is_infinite_not_nan];trivial.
|
|
destruct (not_nan _ H); auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_not_finite :
|
|
forall (x:t), ~ is_finite x <-> is_infinite x \/ is_nan x.
|
|
Proof.
|
|
intros x.
|
|
destruct x; split; intro h; try easy.
|
|
contradict h; easy.
|
|
destruct h as [h|h]; contradict h; easy.
|
|
left; easy.
|
|
right; easy.
|
|
contradict h; easy.
|
|
destruct h as [h|h]; contradict h; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition plus_infinity : t.
|
|
Proof.
|
|
exact (B754_infinity false).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma plus_infinity_spec : is_plus_infinity plus_infinity.
|
|
Proof.
|
|
unfold is_plus_infinity, plus_infinity.
|
|
now simpl.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition minus_infinity : t.
|
|
Proof.
|
|
exact (B754_infinity true).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma minus_infinity_spec : is_minus_infinity minus_infinity.
|
|
Proof.
|
|
unfold is_minus_infinity, minus_infinity.
|
|
now simpl.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition not_a_number : t.
|
|
Proof.
|
|
exact B754_nan.
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma not_a_number_spec : is_nan not_a_number.
|
|
Proof.
|
|
unfold is_nan, not_a_number.
|
|
now simpl.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition to_real : t -> Reals.Rdefinitions.R.
|
|
Proof.
|
|
exact B2R.
|
|
Defined.
|
|
|
|
Lemma Some_ext: forall {T} (a b:T), Some a = Some b <-> a = b.
|
|
Proof.
|
|
intros; split; intro H;[inversion H|rewrite H]; reflexivity.
|
|
Qed.
|
|
|
|
Lemma to_real_eq: forall {x:t} {y:t}, is_finite x -> is_finite y ->
|
|
(eq x y <-> to_real x = to_real y).
|
|
Proof.
|
|
intros x y h1 h2.
|
|
unfold eq.
|
|
rewrite (Bcompare_correct _ _ x y h1 h2), Some_ext.
|
|
split; intro H; [apply (Rcompare_Eq_inv _ _ H)|
|
|
apply (Rcompare_Eq _ _ H)].
|
|
Qed.
|
|
|
|
Lemma to_real_eq_alt: forall {x y}, eq x y -> to_real x = to_real y.
|
|
Proof.
|
|
destruct x, y; try destruct s; try destruct s0; unfold eq, Bcompare; simpl; try easy.
|
|
- destruct (Z_dec e e1) as [[s|s]|s].
|
|
+ rewrite Zcompare_Lt by auto; intro; easy.
|
|
+ apply Z.gt_lt in s.
|
|
rewrite Zcompare_Gt by auto; intro; easy.
|
|
+ rewrite Zcompare_Eq by auto; intro.
|
|
inversion H.
|
|
rewrite <-ZC4 in H1.
|
|
apply Pcompare_Eq_eq in H1.
|
|
destruct m; simpl; subst; auto.
|
|
- destruct (Z_dec e e1) as [[s|s]|s].
|
|
+ rewrite Zcompare_Lt by auto; intro; easy.
|
|
+ apply Z.gt_lt in s.
|
|
rewrite Zcompare_Gt by auto; intro; easy.
|
|
+ rewrite Zcompare_Eq by auto; intro.
|
|
inversion H.
|
|
apply Pcompare_Eq_eq in H1.
|
|
destruct m; simpl; subst; auto.
|
|
Qed.
|
|
|
|
Lemma le_to_real: forall (x:t) (y:t), is_finite x -> is_finite y ->
|
|
(le x y <-> (to_real x <= to_real y)%R).
|
|
Proof.
|
|
intros x y h1 h2.
|
|
unfold le.
|
|
rewrite (Bcompare_correct _ _ x y h1 h2).
|
|
split; intro H.
|
|
- apply Rnot_lt_le.
|
|
intros H'.
|
|
now rewrite Rcompare_Gt in H.
|
|
- case Rcompare_spec; try easy.
|
|
now apply Rle_not_lt.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma zeroF_is_positive : is_positive zeroF.
|
|
Proof.
|
|
easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma zeroF_is_zero : is_zero zeroF.
|
|
Proof.
|
|
apply eq_refl; easy.
|
|
Qed.
|
|
|
|
Lemma zeroF_to_real : ((to_real zeroF) = 0%R).
|
|
Proof.
|
|
easy.
|
|
Qed.
|
|
|
|
Lemma B754_zero_to_real: forall {b}, to_real (B754_zero b) = 0%R.
|
|
Proof.
|
|
intro b.
|
|
rewrite <-(to_real_eq_alt zero_is_zero).
|
|
apply zeroF_to_real.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma zero_to_real :
|
|
forall (x:t), is_zero x <-> is_finite x /\ ((to_real x) = 0%R).
|
|
Proof.
|
|
unfold is_zero.
|
|
assert (is_finite zeroF) by easy.
|
|
intros x; split; intro H0.
|
|
assert (is_finite x) by apply (eq_finite_dist H0 H).
|
|
split; auto.
|
|
symmetry.
|
|
rewrite <-(to_real_eq H H1); auto.
|
|
destruct H0.
|
|
rewrite to_real_eq; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Notation of_int := z_to_fp.
|
|
|
|
(* Why3 goal *)
|
|
Notation to_int := fp_to_z.
|
|
|
|
Lemma to_int_zeroF: forall m, to_int m zeroF = 0%Z.
|
|
Proof.
|
|
intro m.
|
|
destruct (valid_rnd_round_mode m) as (_,b).
|
|
pose proof (b 0%Z) as H; simpl in H.
|
|
destruct m; simpl; auto.
|
|
Qed.
|
|
|
|
(* add to theory ? *)
|
|
Lemma to_int_eq: forall {m x y}, eq x y -> to_int m x = to_int m y.
|
|
Proof.
|
|
destruct x, y; try destruct s; try destruct s0; unfold eq, Bcompare; simpl; try easy.
|
|
- destruct (Z_dec e e1) as [[s|s]|s].
|
|
+ rewrite Zcompare_Lt by auto; intro; easy.
|
|
+ apply Z.gt_lt in s.
|
|
rewrite Zcompare_Gt by auto; intro; easy.
|
|
+ rewrite Zcompare_Eq by auto; intro.
|
|
inversion H.
|
|
rewrite <-ZC4 in H1.
|
|
apply Pcompare_Eq_eq in H1.
|
|
destruct m; simpl; subst; auto.
|
|
- destruct (Z_dec e e1) as [[s|s]|s].
|
|
+ rewrite Zcompare_Lt by auto; intro; easy.
|
|
+ apply Z.gt_lt in s.
|
|
rewrite Zcompare_Gt by auto; intro; easy.
|
|
+ rewrite Zcompare_Eq by auto; intro.
|
|
inversion H.
|
|
apply Pcompare_Eq_eq in H1.
|
|
destruct m; simpl; subst; auto.
|
|
Qed.
|
|
|
|
Lemma to_int_B754_zero: forall {b m}, to_int m (B754_zero b) = 0%Z.
|
|
Proof.
|
|
intros b m.
|
|
rewrite <-(to_int_eq zero_is_zero).
|
|
apply to_int_zeroF.
|
|
Qed.
|
|
|
|
(* add to theory ? *)
|
|
Lemma to_int_le: forall {x y m}, is_finite x -> is_finite y -> le x y -> (to_int m x <= to_int m y)%Z.
|
|
Proof.
|
|
intros.
|
|
destruct m;
|
|
|
|
[destruct (valid_rnd_round_mode mode_NE)|
|
|
destruct (valid_rnd_NA)|
|
|
destruct (valid_rnd_UP)|
|
|
destruct (valid_rnd_DN)|
|
|
destruct (valid_rnd_ZR)];
|
|
apply Zrnd_le;
|
|
apply le_to_real; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma zero_of_int :
|
|
forall (m:ieee_float.RoundingMode.mode), (zeroF = (of_int m 0%Z)).
|
|
Proof.
|
|
auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition round :
|
|
ieee_float.RoundingMode.mode -> Reals.Rdefinitions.R ->
|
|
Reals.Rdefinitions.R.
|
|
Proof.
|
|
exact (fun m => round radix2 fexp (round_mode m)).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Definition max_real : Reals.Rdefinitions.R.
|
|
Proof.
|
|
exact ((1 - bpow radix2 (- sb)) * bpow radix2 emax)%R.
|
|
Defined.
|
|
|
|
Lemma max_real_is_F2R: @F2R radix2 {| Fnum := Z.pos (2 ^ sb_pos - 1); Fexp := emax - sb |} = max_real.
|
|
Proof.
|
|
unfold F2R.
|
|
unfold Fnum, Fexp.
|
|
rewrite Pos2Z.inj_sub, Pos2Z.inj_pow, minus_IZR.
|
|
fold sb.
|
|
change 2%Z with (radix_val radix2).
|
|
rewrite IZR_Zpower by easy.
|
|
rewrite Int.infix_mn'def, bpow_plus.
|
|
rewrite Rmult_comm, Rmult_assoc, Rmult_comm, Rmult_minus_distr_l.
|
|
rewrite <-bpow_plus.
|
|
replace (- sb + sb)%Z with 0%Z by auto with zarith.
|
|
rewrite Rmult_1_r.
|
|
reflexivity.
|
|
apply Pos.pow_gt_1; easy.
|
|
Qed.
|
|
|
|
Lemma min_real_is_F2R: @F2R radix2 {| Fnum := Z.neg (2 ^ sb_pos - 1); Fexp := emax - sb |} = Ropp max_real.
|
|
Proof.
|
|
rewrite <-max_real_is_F2R.
|
|
rewrite <- Operations.F2R_opp.
|
|
unfold Operations.Fopp.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma max_value_to_real: to_real max_value = max_real.
|
|
Proof.
|
|
unfold B2R; simpl.
|
|
apply max_real_is_F2R.
|
|
Qed.
|
|
|
|
Lemma max_real_alt : (max_real = bpow radix2 emax - bpow radix2 (emax - sb))%R.
|
|
Proof.
|
|
unfold max_real.
|
|
rewrite Rmult_minus_distr_r, Rmult_1_l.
|
|
rewrite <-bpow_plus.
|
|
replace (- sb + emax)%Z with (emax - sb)%Z by auto with zarith.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma max_real_lt_bpow_radix2_emax : (max_real < bpow radix2 emax)%R.
|
|
Proof.
|
|
rewrite max_real_alt.
|
|
generalize (bpow_gt_0 radix2 (emax - sb)).
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma max_real_ge_6 : (6 <= max_real)%R.
|
|
Proof.
|
|
rewrite max_real_alt.
|
|
assert (2 <= sb)%Z by (pose proof sb_gt_1; auto with zarith).
|
|
assert (sb + 1 <= emax)%Z by (pose proof Hemax'; auto with zarith).
|
|
assert (8 <= bpow radix2 emax)%R.
|
|
apply (bpow_le radix2 3).
|
|
lia.
|
|
unfold Zminus.
|
|
rewrite bpow_plus.
|
|
assert (bpow radix2 emax * bpow radix2 (-sb) <= bpow radix2 emax * / 4)%R.
|
|
apply Rmult_le_compat_l.
|
|
apply bpow_ge_0.
|
|
apply (bpow_le radix2 _ (-2)).
|
|
now apply Z.opp_le_mono.
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma max_real_generic_format: generic_format radix2 fexp max_real.
|
|
Proof.
|
|
rewrite <-max_value_to_real.
|
|
apply generic_format_B2R.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition max_int : Numbers.BinNums.Z.
|
|
Proof.
|
|
exact (2 ^ emax - 2 ^ (emax - sb))%Z.
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma max_int_spec :
|
|
(max_int =
|
|
((bv.Pow2int.pow2 (bv.Pow2int.pow2 (eb - 1%Z)%Z)) -
|
|
(bv.Pow2int.pow2 ((bv.Pow2int.pow2 (eb - 1%Z)%Z) - sb)%Z))%Z).
|
|
Proof.
|
|
rewrite two_p_equiv, two_p_equiv, two_p_equiv.
|
|
now unfold max_int, emax.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma max_real_int : (max_real = (BuiltIn.IZR max_int)).
|
|
Proof.
|
|
unfold max_int.
|
|
rewrite minus_IZR.
|
|
change 2%Z with (radix_val radix2).
|
|
rewrite IZR_Zpower, IZR_Zpower by (pose Hsb'; pose Hemax'; auto with zarith).
|
|
apply max_real_alt.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition in_range (x:Reals.Rdefinitions.R) : Prop :=
|
|
((-max_real)%R <= x)%R /\ (x <= max_real)%R.
|
|
|
|
(* Why3 assumption *)
|
|
Definition in_int_range (i:Numbers.BinNums.Z) : Prop :=
|
|
((-max_int)%Z <= i)%Z /\ (i <= max_int)%Z.
|
|
|
|
Lemma in_range_bpow_radix2_emax: forall x, in_range x -> (Rabs x < bpow radix2 emax)%R.
|
|
Proof.
|
|
unfold in_range; intros.
|
|
apply Rle_lt_trans with (r2:= max_real).
|
|
apply Abs.Abs_le; apply H.
|
|
apply max_real_lt_bpow_radix2_emax.
|
|
Qed.
|
|
|
|
Lemma is_finite_abs : forall x:t, is_finite x -> is_finite (abs x).
|
|
Proof.
|
|
destruct x; try easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_finite1 : forall (x:t), is_finite x -> in_range (to_real x).
|
|
Proof.
|
|
intros x h1.
|
|
apply Rabs_le_inv.
|
|
rewrite <-max_value_to_real.
|
|
apply Rcompare_not_Lt_inv.
|
|
pose (is_finite_abs x h1).
|
|
pose (bounded_floats x h1).
|
|
rewrite Bcompare_correct in o; try easy.
|
|
unfold abs in o.
|
|
rewrite B2R_Babs in o.
|
|
unfold to_real.
|
|
intro H0.
|
|
destruct o as [H|H]; inversion H as (H1);
|
|
rewrite Rcompare_sym in H1; apply CompOpp_iff in H1;
|
|
simpl in H0; rewrite H0 in H1;
|
|
inversion H1.
|
|
Qed.
|
|
|
|
Lemma Rabs_round_max_real_emax:
|
|
forall {m} {x}, Rabs (round m x) <= max_real <-> Rabs (round m x) < bpow radix2 emax.
|
|
Proof.
|
|
intros m x; split; intro h.
|
|
- apply Rle_lt_trans with (r2 := max_real).
|
|
apply h.
|
|
apply max_real_lt_bpow_radix2_emax.
|
|
- destruct (r_to_fp_correct m x h).
|
|
unfold round.
|
|
rewrite <-H0, Abs.Abs_le.
|
|
apply (is_finite1 _ H).
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition no_overflow (m:ieee_float.RoundingMode.mode)
|
|
(x:Reals.Rdefinitions.R) : Prop :=
|
|
in_range (round m x).
|
|
|
|
Lemma no_overflow_Rabs_round_max_real: forall {m} {x}, no_overflow m x <-> Rabs (round m x) <= max_real.
|
|
Proof.
|
|
intro x.
|
|
split; intro h; apply Abs.Abs_le; easy.
|
|
Qed.
|
|
|
|
Lemma no_overflow_Rabs_round_emax: forall {m} {x}, no_overflow m x <-> Rabs (round m x) < bpow radix2 emax.
|
|
Proof.
|
|
intros m x.
|
|
apply (iff_trans no_overflow_Rabs_round_max_real Rabs_round_max_real_emax).
|
|
Qed.
|
|
|
|
Lemma IZR_alt: forall {x}, @F2R radix2 {| Fnum := x; Fexp := 0 |} = IZR x.
|
|
Proof.
|
|
intros; unfold F2R, Fnum, Fexp, FLT_exp.
|
|
assert (bpow radix2 0 = 1) as bpow_0 by easy.
|
|
rewrite bpow_0, Rmult_1_r.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
Lemma of_int_correct :
|
|
forall {m} {x},
|
|
no_overflow m (IZR x) ->
|
|
to_real (of_int m x) = round m (IZR x) /\ is_finite (of_int m x) /\
|
|
Bsign (of_int m x) =
|
|
match (x ?= 0)%Z with
|
|
| Eq => false
|
|
| Lt => true
|
|
| Gt => false
|
|
end.
|
|
Proof.
|
|
intros m x h1.
|
|
generalize (binary_normalize_correct sb emax Hsb' Hemax' m x 0 false).
|
|
simpl.
|
|
rewrite Rlt_bool_true.
|
|
- intro; destruct H; destruct H0.
|
|
rewrite IZR_alt in H1.
|
|
split.
|
|
rewrite IZR_alt in H; auto.
|
|
split; auto.
|
|
rewrite <- Rcompare_IZR.
|
|
exact H1.
|
|
|
|
- apply no_overflow_Rabs_round_emax.
|
|
rewrite IZR_alt; apply h1.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Bounded_real_no_overflow :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:Reals.Rdefinitions.R),
|
|
in_range x -> no_overflow m x.
|
|
Proof.
|
|
intros m x h1.
|
|
rewrite no_overflow_Rabs_round_max_real.
|
|
apply abs_round_le_generic.
|
|
apply fexp_Valid.
|
|
apply valid_rnd_round_mode.
|
|
apply max_real_generic_format.
|
|
rewrite Abs.Abs_le; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_monotonic :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:Reals.Rdefinitions.R)
|
|
(y:Reals.Rdefinitions.R),
|
|
(x <= y)%R -> ((round m x) <= (round m y))%R.
|
|
Proof.
|
|
intros m x y h1.
|
|
apply round_le.
|
|
apply fexp_Valid.
|
|
apply valid_rnd_round_mode.
|
|
apply h1.
|
|
Qed.
|
|
|
|
Lemma round_lt : forall {x y} {m:mode}, round m x < round m y -> x < y.
|
|
Proof.
|
|
intros x y m h.
|
|
case (Rlt_dec x y); auto.
|
|
intro.
|
|
apply Rnot_lt_le in n.
|
|
apply (Round_monotonic m) in n.
|
|
apply RIneq.Rle_not_lt in n.
|
|
contradict h; assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_idempotent :
|
|
forall (m1:ieee_float.RoundingMode.mode) (m2:ieee_float.RoundingMode.mode)
|
|
(x:Reals.Rdefinitions.R),
|
|
((round m1 (round m2 x)) = (round m2 x)).
|
|
Proof with auto with typeclass_instances.
|
|
intros m1 m2 x.
|
|
apply round_generic...
|
|
apply generic_format_round...
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_to_real :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
((round m (to_real x)) = (to_real x)).
|
|
Proof with auto with typeclass_instances.
|
|
intros m x h.
|
|
apply round_generic...
|
|
apply generic_format_B2R.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_down_le :
|
|
forall (x:Reals.Rdefinitions.R),
|
|
((round ieee_float.RoundingMode.RTN x) <= x)%R.
|
|
Proof with auto with typeclass_instances.
|
|
intros x.
|
|
apply round_DN_pt...
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_up_ge :
|
|
forall (x:Reals.Rdefinitions.R),
|
|
(x <= (round ieee_float.RoundingMode.RTP x))%R.
|
|
Proof with auto with typeclass_instances.
|
|
intros x.
|
|
apply round_UP_pt...
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_down_neg :
|
|
forall (x:Reals.Rdefinitions.R),
|
|
((round ieee_float.RoundingMode.RTN (-x)%R) =
|
|
(-(round ieee_float.RoundingMode.RTP x))%R).
|
|
Proof.
|
|
intros x.
|
|
apply round_opp.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Round_up_neg :
|
|
forall (x:Reals.Rdefinitions.R),
|
|
((round ieee_float.RoundingMode.RTP (-x)%R) =
|
|
(-(round ieee_float.RoundingMode.RTN x))%R).
|
|
Proof.
|
|
intros x.
|
|
pattern x at 2 ; rewrite <- Ropp_involutive.
|
|
rewrite Round_down_neg.
|
|
now rewrite Ropp_involutive.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition pow2sb : Numbers.BinNums.Z.
|
|
Proof.
|
|
exact (Zpower 2 sb).
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma pow2sb1 : (pow2sb = (bv.Pow2int.pow2 sb)).
|
|
Proof.
|
|
now rewrite two_p_equiv.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition in_safe_int_range (i:Numbers.BinNums.Z) : Prop :=
|
|
((-pow2sb)%Z <= i)%Z /\ (i <= pow2sb)%Z.
|
|
|
|
Lemma max_rep_int_bounded: SpecFloat.bounded sb emax (shift_pos (sb_pos - 1) 1) 1 = true.
|
|
Proof.
|
|
unfold SpecFloat.bounded.
|
|
apply Bool.andb_true_iff; split.
|
|
unfold SpecFloat.canonical_mantissa.
|
|
apply Zeq_bool_true.
|
|
rewrite Digits.Zpos_digits2_pos, shift_pos_correct.
|
|
rewrite Zmult_1_r, Z.pow_pos_fold.
|
|
rewrite Digits.Zdigits_Zpower by easy.
|
|
rewrite Pos2Z.inj_sub by exact sb_gt_1.
|
|
fold sb.
|
|
unfold SpecFloat.fexp, FLT_exp, SpecFloat.emin.
|
|
replace (sb - 1 + 1 + 1 - sb)%Z with 1%Z by ring.
|
|
apply Z.max_l.
|
|
pose sb_gt_1; pose Hemax'; lia.
|
|
apply Zle_bool_true.
|
|
pose Hemax'; pose Hsbb; lia.
|
|
Qed.
|
|
|
|
Definition Bmax_rep_int: t.
|
|
Proof.
|
|
exact (B754_finite false _ _ max_rep_int_bounded).
|
|
Defined.
|
|
|
|
Lemma IZR_pow2sb: IZR pow2sb = bpow radix2 sb.
|
|
Proof.
|
|
easy.
|
|
Qed.
|
|
|
|
Lemma Bmax_rep_int_to_real: to_real Bmax_rep_int = IZR pow2sb.
|
|
Proof.
|
|
rewrite IZR_pow2sb.
|
|
unfold B2R; simpl.
|
|
rewrite shift_pos_correct.
|
|
rewrite Z.pow_pos_fold.
|
|
unfold F2R.
|
|
unfold Fnum, Fexp.
|
|
rewrite Zmult_1_r.
|
|
change 2%Z with (radix_val radix2).
|
|
rewrite IZR_Zpower by easy.
|
|
rewrite <-bpow_plus.
|
|
rewrite Pos2Z.inj_sub by exact sb_gt_1.
|
|
replace (Z.pos sb_pos - 1 + 1)%Z with (Z.pos sb_pos).
|
|
reflexivity.
|
|
ring.
|
|
Qed.
|
|
|
|
Lemma pow2sb_lt_max_int: (pow2sb <= max_int)%Z.
|
|
Proof.
|
|
apply le_IZR.
|
|
rewrite <-max_real_int, <-Bmax_rep_int_to_real.
|
|
now apply is_finite1.
|
|
Qed.
|
|
|
|
Lemma rep_int_in_range:
|
|
forall i, (- pow2sb <= i <= pow2sb)%Z ->
|
|
in_range (IZR i).
|
|
Proof.
|
|
intros.
|
|
rewrite <-Z.abs_le in H.
|
|
pose (IZR_le _ _ H).
|
|
rewrite <-Rabs_Zabs in r.
|
|
unfold in_range.
|
|
apply Rabs_le_inv.
|
|
apply Rle_trans with (r2 := IZR pow2sb); auto.
|
|
|
|
rewrite <-Bmax_rep_int_to_real, <-max_value_to_real.
|
|
apply le_to_real; try easy.
|
|
|
|
assert (is_finite Bmax_rep_int) by easy.
|
|
pose (bounded_floats _ H0).
|
|
rewrite le_correct.
|
|
easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Exact_rounding_for_integers :
|
|
forall (m:ieee_float.RoundingMode.mode) (i:Numbers.BinNums.Z),
|
|
in_safe_int_range i -> ((round m (BuiltIn.IZR i)) = (BuiltIn.IZR i)).
|
|
Proof with auto with typeclass_instances.
|
|
intros m z Hz.
|
|
apply round_generic...
|
|
assert (Z.abs z <= pow2sb)%Z.
|
|
apply Z.abs_le with (1:=Hz).
|
|
destruct (Zle_lt_or_eq _ _ H) as [Bz|Bz] ; clear H Hz.
|
|
apply generic_format_FLT.
|
|
exists (Float radix2 z 0).
|
|
unfold F2R ; simpl.
|
|
now rewrite Rmult_1_r.
|
|
easy.
|
|
simpl; unfold emin; generalize Hsb' Hemax'; lia.
|
|
unfold pow2sb in Bz.
|
|
change 2%Z with (radix_val radix2) in Bz.
|
|
apply generic_format_abs_inv.
|
|
rewrite <- abs_IZR, Bz, IZR_Zpower.
|
|
apply generic_format_bpow.
|
|
unfold FLT_exp, emin.
|
|
clear Bz; generalize Hsb' Hemax'.
|
|
lia.
|
|
apply Zlt_le_weak.
|
|
apply Hsb'.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition from_real :
|
|
ieee_float.RoundingMode.mode -> Reals.Rdefinitions.R -> t.
|
|
Proof.
|
|
exact r_to_fp.
|
|
Defined.
|
|
|
|
(* Why3 goal *)
|
|
Lemma from_real_in_range :
|
|
forall (m:ieee_float.RoundingMode.mode) (r:Reals.Rdefinitions.R),
|
|
in_range (round m r) ->
|
|
let f := from_real m r in is_finite f /\ ((to_real f) = (round m r)).
|
|
Proof.
|
|
intros m r h1 f.
|
|
unfold from_real, round in *.
|
|
unfold is_finite, in_range, to_real in *.
|
|
apply r_to_fp_correct.
|
|
unfold max_real in *.
|
|
Admitted.
|
|
|
|
(* Why3 goal *)
|
|
Lemma from_real_large_neg :
|
|
forall (m:ieee_float.RoundingMode.mode) (r:Reals.Rdefinitions.R),
|
|
((round m r) < (-max_real)%R)%R ->
|
|
let f := from_real m r in is_infinite f /\ is_negative f.
|
|
Proof.
|
|
intros m r h1 f.
|
|
Admitted.
|
|
|
|
(* Why3 goal *)
|
|
Lemma from_real_large_pos :
|
|
forall (m:ieee_float.RoundingMode.mode) (r:Reals.Rdefinitions.R),
|
|
(max_real < (round m r))%R ->
|
|
let f := from_real m r in is_infinite f /\ is_positive f.
|
|
Proof.
|
|
intros m r h1 f.
|
|
Admitted.
|
|
|
|
Lemma in_safe_int_range_no_overflow : forall m {i}, in_safe_int_range i -> no_overflow m (IZR i).
|
|
Proof.
|
|
intros m i h.
|
|
apply Bounded_real_no_overflow.
|
|
unfold in_safe_int_range in h.
|
|
unfold in_range.
|
|
rewrite max_real_int, <- FromInt.Neg.
|
|
pose proof pow2sb_lt_max_int.
|
|
split; apply IZR_le; auto with zarith.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition same_sign (x:t) (y:t) : Prop :=
|
|
is_positive x /\ is_positive y \/ is_negative x /\ is_negative y.
|
|
|
|
Hint Unfold same_sign.
|
|
|
|
Lemma same_sign_refl: forall {x}, ~ is_nan x -> same_sign x x.
|
|
Proof.
|
|
unfold is_nan, same_sign.
|
|
intros x h.
|
|
destruct x; try easy; try (destruct s; now auto).
|
|
now contradict h.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition diff_sign (x:t) (y:t) : Prop :=
|
|
is_positive x /\ is_negative y \/ is_negative x /\ is_positive y.
|
|
|
|
Hint Unfold same_sign.
|
|
|
|
(* Why3 goal *)
|
|
Lemma feq_eq :
|
|
forall (x:t) (y:t), is_finite x -> is_finite y -> ~ is_zero x -> eq x y ->
|
|
(x = y).
|
|
Proof.
|
|
intros x y h1 h2 h3 h4.
|
|
destruct x, y; try easy.
|
|
|
|
destruct s, s0; try easy.
|
|
destruct s, s0; try easy.
|
|
|
|
revert h3 h4.
|
|
case (Bool.bool_dec s s0); intro h; [rewrite h;clear h|destruct s, s0; try easy; destruct h;reflexivity].
|
|
intros h3 h4. clear h1.
|
|
|
|
destruct (Z_dec e e1) as [He|He].
|
|
|
|
- unfold eq, Bcompare in h4; simpl in h4.
|
|
destruct He.
|
|
rewrite (Zcompare_Lt _ _ l) in h4.
|
|
destruct s, s0; try easy.
|
|
rewrite (Zcompare_Gt _ _ (Z.gt_lt _ _ g)) in h4.
|
|
destruct s, s0; try easy.
|
|
|
|
- destruct He.
|
|
case (Pos.eq_dec m m0); intro.
|
|
+ destruct e1.
|
|
assert (forall x y: bool, x = y \/ x <> y) by
|
|
(intros; case (Bool.bool_dec x y); auto).
|
|
destruct (Eqdep_dec.eq_proofs_unicity H e0 e2).
|
|
reflexivity.
|
|
|
|
+ unfold eq, Bcompare in h4; simpl in h4.
|
|
destruct s0.
|
|
* rewrite Z.compare_refl, Some_ext, Pos.compare_cont_antisym in h4.
|
|
rewrite (Pos.compare_eq _ _ h4) in n.
|
|
destruct n; reflexivity.
|
|
|
|
* rewrite Z.compare_refl, Some_ext in h4.
|
|
rewrite (Pos.compare_eq _ _ h4) in n.
|
|
destruct n; reflexivity.
|
|
Qed.
|
|
|
|
Lemma to_real_refl: forall {x:t} {y:t}, is_finite x -> is_finite y ->
|
|
to_real x = to_real y -> same_sign x y ->
|
|
x = y.
|
|
Proof.
|
|
intros x y h1 h2 h3 h4.
|
|
destruct x, y; try easy.
|
|
+ destruct s, s0, h4; easy.
|
|
+ symmetry in h3.
|
|
apply eq_0_F2R in h3.
|
|
destruct s0; contradict h3; easy.
|
|
+ apply eq_0_F2R in h3.
|
|
destruct s; contradict h3; easy.
|
|
+ apply feq_eq; auto.
|
|
rewrite eq_zero_iff; intro.
|
|
destruct H; easy.
|
|
apply to_real_eq; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_feq :
|
|
forall (x:t) (y:t), is_finite x -> is_finite y -> (x = y) -> eq x y.
|
|
Proof.
|
|
intros x y h1 h2 h3.
|
|
rewrite h3.
|
|
apply (eq_not_nan_refl (is_finite_not_nan h2)).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_refl : forall (x:t), is_finite x -> eq x x.
|
|
Proof.
|
|
intros x h1.
|
|
apply (eq_not_nan_refl (is_finite_not_nan h1)).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_sym : forall (x:t) (y:t), eq x y -> eq y x.
|
|
Proof.
|
|
intros x y.
|
|
unfold eq; intro h; rewrite Bcompare_swap, h; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_trans : forall (x:t) (y:t) (z:t), eq x y -> eq y z -> eq x z.
|
|
Proof.
|
|
intros x y z h1 h2.
|
|
destruct x, y, z; auto; try destruct s; try destruct s0; try destruct s1; auto; try easy;
|
|
apply to_real_eq in h1; try (split;easy);
|
|
apply to_real_eq in h2; try (split;easy);
|
|
apply to_real_eq; try (split;easy);
|
|
apply (eq_trans h1 h2).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_zero : eq zeroF (neg zeroF).
|
|
Proof.
|
|
easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_to_real_finite :
|
|
forall (x:t) (y:t), is_finite x /\ is_finite y ->
|
|
eq x y <-> ((to_real x) = (to_real y)).
|
|
Proof.
|
|
intros x y (h1,h2).
|
|
apply (to_real_eq h1 h2).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_special :
|
|
forall (x:t) (y:t), eq x y ->
|
|
is_not_nan x /\
|
|
is_not_nan y /\
|
|
(is_finite x /\ is_finite y \/
|
|
is_infinite x /\ is_infinite y /\ same_sign x y).
|
|
Proof.
|
|
intros x y h1.
|
|
rewrite is_not_nan1, is_not_nan1.
|
|
destruct (eq_not_nan h1) as (h2,h3).
|
|
split; [auto|split;auto].
|
|
destruct (not_nan _ h2); [left|right].
|
|
- split; [apply i|apply (eq_finite_dist h1 i)].
|
|
- split; [apply i|split;[apply (eq_infinite_dist h1 i)|]].
|
|
destruct x, y; try destruct s; try destruct s0; auto; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma lt_finite :
|
|
forall (x:t) (y:t), is_finite x /\ is_finite y ->
|
|
lt x y <-> ((to_real x) < (to_real y))%R.
|
|
Proof.
|
|
intros x y (h1,h2).
|
|
unfold lt.
|
|
rewrite (Bcompare_correct _ _ x y h1 h2), Some_ext.
|
|
split; intro H; [apply (Rcompare_Lt_inv _ _ H)|
|
|
apply (Rcompare_Lt _ _ H)].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma le_finite :
|
|
forall (x:t) (y:t), is_finite x /\ is_finite y ->
|
|
le x y <-> ((to_real x) <= (to_real y))%R.
|
|
Proof.
|
|
intros x y (h1,h2).
|
|
now apply le_to_real.
|
|
Qed.
|
|
|
|
Lemma lt_eq_trans : forall {x y z:t}, lt x y -> eq y z -> lt x z.
|
|
Proof.
|
|
intros x y z h1 h2.
|
|
destruct x, y, z; try easy; try (destruct s, s0, s1; easy).
|
|
set (x:=B754_finite s m e e0);
|
|
set (y:=B754_finite s0 m0 e1 e2);
|
|
set (z:=B754_finite s1 m1 e3 e4); fold x y z in h1, h2.
|
|
pose proof (Bcompare_correct sb emax x y).
|
|
pose proof (Bcompare_correct sb emax y z).
|
|
pose proof (Bcompare_correct sb emax x z).
|
|
unfold lt in h1.
|
|
rewrite H in h1 by easy; clear H.
|
|
unfold eq in h2.
|
|
rewrite H0 in h2 by easy; clear H0.
|
|
unfold lt.
|
|
rewrite H1 by easy; clear H1.
|
|
apply f_equal, Rcompare_Lt.
|
|
apply Rlt_le_trans with (B2R (B754_finite s0 m0 e1 e2)).
|
|
+ apply Rcompare_Lt_inv.
|
|
now injection h1.
|
|
+ apply Rcompare_not_Gt_inv.
|
|
inversion h1; inversion h2.
|
|
destruct Rcompare; try easy.
|
|
destruct Rcompare; try easy;
|
|
simpl; rewrite H1; discriminate.
|
|
Qed.
|
|
|
|
Lemma eq_lt_trans : forall {x y z:t}, eq x y -> lt y z -> lt x z.
|
|
Proof.
|
|
intros x y z h1 h2.
|
|
destruct x, y, z; try easy; try (destruct s, s0, s1; easy).
|
|
set (x:=B754_finite s m e e0);
|
|
set (y:=B754_finite s0 m0 e1 e2);
|
|
set (z:=B754_finite s1 m1 e3 e4); fold x y z in h1, h2.
|
|
pose proof (Bcompare_correct sb emax x y).
|
|
pose proof (Bcompare_correct sb emax y z).
|
|
pose proof (Bcompare_correct sb emax x z).
|
|
unfold eq in h1.
|
|
unfold lt in h2.
|
|
rewrite H in h1 by easy; clear H.
|
|
rewrite H0 in h2 by easy; clear H0.
|
|
unfold lt.
|
|
rewrite H1 by easy; clear H1.
|
|
apply f_equal, Rcompare_Lt.
|
|
apply Rle_lt_trans with (B2R (B754_finite s0 m0 e1 e2)).
|
|
+ apply Rcompare_not_Gt_inv.
|
|
inversion h1; inversion h2.
|
|
destruct Rcompare; try easy;
|
|
simpl; rewrite H0; discriminate.
|
|
+ apply Rcompare_Lt_inv.
|
|
now injection h2.
|
|
Qed.
|
|
|
|
Lemma lt_lt_trans : forall {x y z:t}, lt x y -> lt y z -> lt x z.
|
|
Proof.
|
|
intros x y z h1 h2.
|
|
destruct x, y, z; try easy; try (destruct s, s0, s1; easy).
|
|
set (x:=B754_finite s m e e0);
|
|
set (y:=B754_finite s0 m0 e1 e2);
|
|
set (z:=B754_finite s1 m1 e3 e4); fold x y z in h1, h2.
|
|
pose proof (Bcompare_correct sb emax x y).
|
|
pose proof (Bcompare_correct sb emax y z).
|
|
pose proof (Bcompare_correct sb emax x z).
|
|
unfold lt in h1, h2.
|
|
rewrite H in h1 by easy; clear H.
|
|
rewrite H0 in h2 by easy; clear H0.
|
|
unfold lt.
|
|
rewrite H1 by easy; clear H1.
|
|
apply f_equal, Rcompare_Lt.
|
|
apply Rlt_trans with (B2R (B754_finite s0 m0 e1 e2)).
|
|
+ apply Rcompare_Lt_inv.
|
|
now injection h1.
|
|
+ apply Rcompare_Lt_inv.
|
|
now injection h2.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma le_lt_trans : forall (x:t) (y:t) (z:t), le x y /\ lt y z -> lt x z.
|
|
Proof.
|
|
intros x y z (h,h1).
|
|
apply le_correct in h.
|
|
destruct h as [h|h].
|
|
apply (lt_lt_trans h h1).
|
|
apply (eq_lt_trans h h1).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma lt_le_trans : forall (x:t) (y:t) (z:t), lt x y /\ le y z -> lt x z.
|
|
Proof.
|
|
intros x y z (h1,h2).
|
|
apply le_correct in h2.
|
|
destruct h2 as [h2|h2].
|
|
apply (lt_lt_trans h1 h2).
|
|
apply (lt_eq_trans h1 h2).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma le_ge_asym : forall (x:t) (y:t), le x y /\ le y x -> eq x y.
|
|
Proof.
|
|
intros x y.
|
|
unfold le, eq.
|
|
destruct x, y; intros (h,h1); auto; try easy; try (destruct s,s0,h,h1; easy).
|
|
set (x:=B754_finite s m e e0);
|
|
set (y:=B754_finite s0 m0 e1 e2);
|
|
fold x y in h, h1.
|
|
pose proof (Bcompare_correct sb emax x y).
|
|
pose proof (Bcompare_correct sb emax y x).
|
|
rewrite H in h by easy.
|
|
rewrite H0 in h1 by easy.
|
|
rewrite H by easy.
|
|
f_equal.
|
|
apply Rcompare_Eq.
|
|
apply Rle_antisym.
|
|
+ apply Rcompare_not_Gt_inv.
|
|
now destruct Rcompare.
|
|
+ apply Rcompare_not_Gt_inv.
|
|
now destruct (Rcompare (B2R y) (B2R x)).
|
|
Qed.
|
|
|
|
Lemma Some_ext_op: forall {T} (a b:T), Some a <> Some b <-> a <> b.
|
|
Proof.
|
|
intros; split; intro H.
|
|
intro h.
|
|
apply (H (f_equal _ h)).
|
|
intro h; injection h; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma not_lt_ge :
|
|
forall (x:t) (y:t), ~ lt x y /\ is_not_nan x /\ is_not_nan y -> le y x.
|
|
Proof.
|
|
intros x y.
|
|
rewrite is_not_nan1; rewrite is_not_nan1.
|
|
unfold is_nan.
|
|
destruct x, y; intros (h,(h1,h2)); try (try destruct s; try destruct s0; try easy; elim h1; auto; easy).
|
|
revert h.
|
|
unfold le, lt.
|
|
rewrite Bcompare_swap.
|
|
rewrite Bcompare_correct by easy.
|
|
now destruct Rcompare as [| |].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma not_gt_le :
|
|
forall (x:t) (y:t), ~ lt y x /\ is_not_nan x /\ is_not_nan y -> le x y.
|
|
Proof.
|
|
intros x y.
|
|
rewrite is_not_nan1; rewrite is_not_nan1.
|
|
unfold is_nan.
|
|
destruct x, y; intros (h,(h1,h2)); auto; try (try destruct s; try destruct s0; try easy; elim h1; auto; easy).
|
|
revert h.
|
|
unfold le, lt.
|
|
rewrite Bcompare_swap.
|
|
rewrite Bcompare_correct by easy.
|
|
now destruct Rcompare as [| |].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma le_special :
|
|
forall (x:t) (y:t), le x y ->
|
|
is_finite x /\ is_finite y \/
|
|
is_minus_infinity x /\ is_not_nan y \/ is_not_nan x /\ is_plus_infinity y.
|
|
Proof.
|
|
intros x y h.
|
|
rewrite is_not_nan1; rewrite is_not_nan1.
|
|
unfold le in h.
|
|
unfold is_nan, is_finite.
|
|
destruct x, y; auto; try easy; try (destruct s, s0; auto; destruct h; auto; easy).
|
|
- right; right. destruct s0, h; split; easy.
|
|
- right; left. destruct s, h; split; easy.
|
|
- right. destruct s, s0, h; try easy.
|
|
+ left; split; easy.
|
|
+ left; split; easy.
|
|
+ right; split; easy.
|
|
- right; left. destruct s, h; split; easy.
|
|
- right; right. destruct s, s0, h; split; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma lt_special :
|
|
forall (x:t) (y:t), lt x y ->
|
|
is_finite x /\ is_finite y \/
|
|
is_minus_infinity x /\ is_not_nan y /\ ~ is_minus_infinity y \/
|
|
is_not_nan x /\ ~ is_plus_infinity x /\ is_plus_infinity y.
|
|
Proof.
|
|
intros x y h.
|
|
rewrite is_not_nan1; rewrite is_not_nan1.
|
|
unfold lt in h.
|
|
unfold is_nan, is_finite.
|
|
unfold is_plus_infinity, is_minus_infinity.
|
|
destruct x, y; auto; try easy; try (destruct s, s0; easy).
|
|
|
|
- right; right. destruct s0; split; try split; easy.
|
|
- right; left. destruct s; split; try split; easy.
|
|
- right; right. destruct s, s0; split; try split; easy.
|
|
- right; left. destruct s; split; try split; easy.
|
|
- right; right. destruct s, s0; split; try split; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma lt_lt_finite :
|
|
forall (x:t) (y:t) (z:t), lt x y -> lt y z -> is_finite y.
|
|
Proof.
|
|
intros x y z h1 h2.
|
|
destruct x, y, z; try easy; destruct s, s0, s1; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma positive_to_real :
|
|
forall (x:t), is_finite x -> is_positive x -> (0%R <= (to_real x))%R.
|
|
Proof.
|
|
intros x h1 h2.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
rewrite <-zeroF_to_real; apply (le_to_real _ _ zero_is_finite h1).
|
|
apply le_correct.
|
|
generalize (is_positive_correct x); intro H. destruct H, H; auto.
|
|
rewrite H; auto.
|
|
Qed.
|
|
|
|
Lemma non_zero_positive_to_real : forall {x:t},
|
|
is_finite x -> ~ is_zero x -> is_positive x ->
|
|
0 < to_real x.
|
|
Proof.
|
|
intros x h1 h2 h3.
|
|
rewrite <-zeroF_to_real; apply lt_finite.
|
|
split; easy.
|
|
destruct x; try easy.
|
|
contradict h2; easy.
|
|
simpl in h3.
|
|
destruct s; simpl; easy.
|
|
Qed.
|
|
|
|
Lemma is_positive_to_int: forall {x} {m:mode}, is_finite x -> is_positive x -> (0 <= to_int m x)%Z.
|
|
Proof.
|
|
intros x m h h1.
|
|
rewrite <-(to_int_zeroF m).
|
|
destruct (valid_rnd_round_mode m) as (h2,_).
|
|
destruct m; simpl in h2; apply h2; now apply positive_to_real.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma to_real_positive :
|
|
forall (x:t), is_finite x -> (0%R < (to_real x))%R -> is_positive x.
|
|
Proof.
|
|
intros x h1 h2.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
rewrite <-zeroF_to_real, <-(lt_finite _ _ (conj zero_is_finite h1)) in h2.
|
|
generalize (is_positive_correct x); intro H; destruct H; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma negative_to_real :
|
|
forall (x:t), is_finite x -> is_negative x -> ((to_real x) <= 0%R)%R.
|
|
Proof.
|
|
intros x h1 h2.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
rewrite <-zeroF_to_real; apply (le_to_real _ _ h1 zero_is_finite).
|
|
apply le_correct.
|
|
generalize (is_negative_correct x); intro H; destruct H, H; auto.
|
|
rewrite H; auto.
|
|
Qed.
|
|
|
|
Lemma non_zero_negative_to_real : forall {x:t},
|
|
is_finite x -> ~ is_zero x -> is_negative x ->
|
|
to_real x < 0.
|
|
Proof.
|
|
intros x h1 h2 h3.
|
|
rewrite <-zeroF_to_real; apply lt_finite.
|
|
split; easy.
|
|
destruct x; try easy.
|
|
contradict h2; easy.
|
|
simpl in h3.
|
|
destruct s; simpl; easy.
|
|
Qed.
|
|
|
|
Lemma is_negative_to_int: forall {x} {m:mode}, is_finite x -> is_negative x -> (to_int m x <= 0)%Z.
|
|
Proof.
|
|
intros x m h h1.
|
|
rewrite <-(to_int_zeroF m).
|
|
destruct (valid_rnd_round_mode m) as (h2,_).
|
|
destruct m; simpl in h2; apply h2; now apply negative_to_real.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma to_real_negative :
|
|
forall (x:t), is_finite x -> ((to_real x) < 0%R)%R -> is_negative x.
|
|
Proof.
|
|
intros x h1 h2.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
rewrite <-zeroF_to_real, <-(lt_finite _ _ (conj h1 zero_is_finite)) in h2.
|
|
generalize (is_negative_correct x); intro H; destruct H; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma negative_xor_positive :
|
|
forall (x:t), ~ (is_positive x /\ is_negative x).
|
|
Proof.
|
|
intros x.
|
|
destruct x; try destruct s; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma negative_or_positive :
|
|
forall (x:t), is_not_nan x -> is_positive x \/ is_negative x.
|
|
Proof.
|
|
intros x h1.
|
|
destruct x; try destruct s; simpl; auto; now elim h1.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma diff_sign_trans :
|
|
forall (x:t) (y:t) (z:t), diff_sign x y /\ diff_sign y z -> same_sign x z.
|
|
Proof.
|
|
unfold diff_sign, same_sign.
|
|
intros x y z (h1,h2).
|
|
pose proof (negative_xor_positive y) as H.
|
|
destruct h1 as [(h,h1)|(h,h1)], h2 as [(h2,h3)|(h2,h3)].
|
|
- contradict H; split; easy.
|
|
- left; split; easy.
|
|
- right; split; easy.
|
|
- contradict H; split; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma diff_sign_product :
|
|
forall (x:t) (y:t),
|
|
is_finite x /\ is_finite y /\ (((to_real x) * (to_real y))%R < 0%R)%R ->
|
|
diff_sign x y.
|
|
Proof.
|
|
intros x y (h1,(h2,h3)).
|
|
unfold diff_sign.
|
|
case (Rcase_abs (to_real y)); intro; [left|right].
|
|
- split; [apply to_real_positive; try easy|apply to_real_negative; easy].
|
|
apply Rmult_lt_reg_r with (r := (-to_real y)); lra.
|
|
- destruct r.
|
|
+ split; [apply to_real_negative; try easy|apply to_real_positive; easy].
|
|
apply Rmult_lt_reg_r with (r := (to_real y)); lra.
|
|
+ rewrite H in h3; lra.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma same_sign_product :
|
|
forall (x:t) (y:t), is_finite x /\ is_finite y /\ same_sign x y ->
|
|
(0%R <= ((to_real x) * (to_real y))%R)%R.
|
|
Proof.
|
|
intros x y (h1,(h2,h3)).
|
|
unfold same_sign in h3.
|
|
destruct h3 as [(h3,h4)|(h3,h4)].
|
|
- apply (positive_to_real _ h1) in h3.
|
|
apply (positive_to_real _ h2) in h4.
|
|
apply Rmult_le_pos; auto.
|
|
- apply (negative_to_real _ h1) in h3.
|
|
apply (negative_to_real _ h2) in h4.
|
|
rewrite <-Rmult_opp_opp.
|
|
apply Rmult_le_pos; lra.
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition product_sign (z:t) (x:t) (y:t) : Prop :=
|
|
(same_sign x y -> is_positive z) /\ (diff_sign x y -> is_negative z).
|
|
|
|
(* Why3 assumption *)
|
|
Definition overflow_value (m:ieee_float.RoundingMode.mode) (x:t) : Prop :=
|
|
match m with
|
|
| ieee_float.RoundingMode.RTN =>
|
|
(is_positive x -> is_finite x /\ ((to_real x) = max_real)) /\
|
|
(~ is_positive x -> is_infinite x)
|
|
| ieee_float.RoundingMode.RTP =>
|
|
(is_positive x -> is_infinite x) /\
|
|
(~ is_positive x -> is_finite x /\ ((to_real x) = (-max_real)%R))
|
|
| ieee_float.RoundingMode.RTZ =>
|
|
(is_positive x -> is_finite x /\ ((to_real x) = max_real)) /\
|
|
(~ is_positive x -> is_finite x /\ ((to_real x) = (-max_real)%R))
|
|
| ieee_float.RoundingMode.RNA|ieee_float.RoundingMode.RNE => is_infinite x
|
|
end.
|
|
|
|
(* Why3 assumption *)
|
|
Definition sign_zero_result (m:ieee_float.RoundingMode.mode) (x:t) : Prop :=
|
|
is_zero x ->
|
|
match m with
|
|
| ieee_float.RoundingMode.RTN => is_negative x
|
|
| _ => is_positive x
|
|
end.
|
|
|
|
(* Why3 goal *)
|
|
Lemma add_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
is_finite y -> no_overflow m ((to_real x) + (to_real y))%R ->
|
|
is_finite (add m x y) /\
|
|
((to_real (add m x y)) = (round m ((to_real x) + (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2 h3.
|
|
generalize (Bplus_correct sb emax Hsb'' Hemax' m x y h1 h2); rewrite Rlt_bool_true.
|
|
intro; split; easy.
|
|
apply (in_range_bpow_radix2_emax _ h3).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma add_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
is_finite (add m x y) -> is_finite x /\ is_finite y.
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct x, y; try easy; destruct s, s0; try easy;
|
|
simpl in h1; unfold is_finite in h1; now rewrite is_finite_build_nan in h1.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma add_finite_rev_n :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
ieee_float.RoundingMode.to_nearest m -> is_finite (add m x y) ->
|
|
no_overflow m ((to_real x) + (to_real y))%R /\
|
|
((to_real (add m x y)) = (round m ((to_real x) + (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2.
|
|
destruct (add_finite_rev m x y h2).
|
|
assert (no_overflow m (to_real x + to_real y)).
|
|
2: split; [easy|apply add_finite; easy].
|
|
pose proof max_real_ge_6.
|
|
destruct x, y; try easy; try (rewrite B754_zero_to_real).
|
|
apply Bounded_real_no_overflow; rewrite (@B754_zero_to_real s0); split; lra.
|
|
apply Bounded_real_no_overflow; rewrite Rplus_0_l; apply is_finite1; auto.
|
|
apply Bounded_real_no_overflow; rewrite Rplus_0_r; apply is_finite1; auto.
|
|
set (x := B754_finite s m0 e e0).
|
|
set (y := B754_finite s0 m1 e1 e2).
|
|
fold x y in h2, H, H0.
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x + to_real y))) (bpow radix2 emax)).
|
|
rewrite no_overflow_Rabs_round_emax; assumption.
|
|
pose proof (Bplus_correct sb emax Hsb'' Hemax' m x y H H0).
|
|
change (Bplus m) with (add m) in H2.
|
|
rewrite Rlt_bool_false in H2; auto.
|
|
destruct m, h1; try easy.
|
|
destruct (add RNE x y); easy.
|
|
destruct (add RNA x y); easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sub_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
is_finite y -> no_overflow m ((to_real x) - (to_real y))%R ->
|
|
is_finite (sub m x y) /\
|
|
((to_real (sub m x y)) = (round m ((to_real x) - (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2 h3.
|
|
generalize (Bminus_correct sb emax Hsb'' Hemax' m x y h1 h2); rewrite Rlt_bool_true.
|
|
intro; split; easy.
|
|
apply (in_range_bpow_radix2_emax _ h3).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sub_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
is_finite (sub m x y) -> is_finite x /\ is_finite y.
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct x, y; try easy; destruct s, s0; try easy;
|
|
simpl in h1; unfold is_finite in h1; now rewrite is_finite_build_nan in h1.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sub_finite_rev_n :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
ieee_float.RoundingMode.to_nearest m -> is_finite (sub m x y) ->
|
|
no_overflow m ((to_real x) - (to_real y))%R /\
|
|
((to_real (sub m x y)) = (round m ((to_real x) - (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2.
|
|
destruct (sub_finite_rev m x y h2).
|
|
assert (no_overflow m (to_real x - to_real y)).
|
|
2: split; [easy|apply sub_finite; easy].
|
|
pose proof max_real_ge_6.
|
|
destruct x, y; try easy; try (rewrite B754_zero_to_real).
|
|
apply Bounded_real_no_overflow; rewrite (@B754_zero_to_real s0); split; lra.
|
|
apply Bounded_real_no_overflow.
|
|
unfold to_real.
|
|
rewrite Rminus_0_l, <- B2R_Bopp.
|
|
apply is_finite1, is_finite_Bopp.
|
|
apply Bounded_real_no_overflow; rewrite Rminus_0_r; apply is_finite1; auto.
|
|
set (x := B754_finite s m0 e e0).
|
|
set (y := B754_finite s0 m1 e1 e2).
|
|
fold x y in h2, H, H0.
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x - to_real y))) (bpow radix2 emax)).
|
|
rewrite no_overflow_Rabs_round_emax; assumption.
|
|
pose proof (Bminus_correct sb emax Hsb'' Hemax' m x y H H0).
|
|
change (Bminus m) with (sub m) in H2.
|
|
rewrite Rlt_bool_false in H2; auto.
|
|
destruct m, h1; try easy.
|
|
destruct (sub RNE x y); easy.
|
|
destruct (sub RNA x y); easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma mul_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
is_finite y -> no_overflow m ((to_real x) * (to_real y))%R ->
|
|
is_finite (mul m x y) /\
|
|
((to_real (mul m x y)) = (round m ((to_real x) * (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2 h3.
|
|
generalize (Bmult_correct sb emax Hsb'' Hemax' m x y); rewrite Rlt_bool_true, h1, h2.
|
|
intro; split; easy.
|
|
apply (in_range_bpow_radix2_emax _ h3).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma mul_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
is_finite (mul m x y) -> is_finite x /\ is_finite y.
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct x, y; try easy; destruct s, s0; try easy;
|
|
simpl in h1; unfold is_finite in h1; now rewrite is_finite_build_nan in h1.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma mul_finite_rev_n :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
ieee_float.RoundingMode.to_nearest m -> is_finite (mul m x y) ->
|
|
no_overflow m ((to_real x) * (to_real y))%R /\
|
|
((to_real (mul m x y)) = (round m ((to_real x) * (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2.
|
|
destruct (mul_finite_rev m x y h2).
|
|
assert (no_overflow m (to_real x * to_real y)).
|
|
2: split; [easy|apply mul_finite; easy].
|
|
pose proof max_real_ge_6.
|
|
destruct x, y; try easy; try (rewrite B754_zero_to_real).
|
|
apply Bounded_real_no_overflow; rewrite (@B754_zero_to_real s0); split; lra.
|
|
unfold no_overflow; rewrite Rmult_0_l, <-zeroF_to_real, Round_to_real, zeroF_to_real; auto; split; lra.
|
|
unfold no_overflow; rewrite Rmult_0_r, <-zeroF_to_real, Round_to_real, zeroF_to_real; auto; split; lra.
|
|
set (x := B754_finite s m0 e e0).
|
|
set (y := B754_finite s0 m1 e1 e2).
|
|
fold x y in h2, H, H0.
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x * to_real y))) (bpow radix2 emax)).
|
|
rewrite no_overflow_Rabs_round_emax; assumption.
|
|
pose proof (Bmult_correct sb emax Hsb'' Hemax' m x y).
|
|
change (Bmult m) with (mul m) in H2.
|
|
rewrite Rlt_bool_false in H2; auto.
|
|
destruct m, h1; try easy.
|
|
destruct (mul RNE x y); easy.
|
|
destruct (mul RNA x y); easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma div_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
is_finite y -> ~ is_zero y ->
|
|
no_overflow m ((to_real x) / (to_real y))%R ->
|
|
is_finite (div m x y) /\
|
|
((to_real (div m x y)) = (round m ((to_real x) / (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2 h3 h4.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
rewrite (to_real_eq zero_is_finite h2) in h3.
|
|
apply not_eq_sym in h3.
|
|
generalize (Bdiv_correct sb emax Hsb'' Hemax' m x y h3); rewrite Rlt_bool_true, h1.
|
|
intro; split; easy.
|
|
apply (in_range_bpow_radix2_emax _ h4).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma div_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
is_finite (div m x y) ->
|
|
is_finite x /\ is_finite y /\ ~ is_zero y \/
|
|
is_finite x /\ is_infinite y /\ ((to_real (div m x y)) = 0%R).
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct x, y; try easy;
|
|
simpl in h1; unfold is_finite in h1; try now rewrite is_finite_build_nan in h1.
|
|
right; destruct s, s0; easy.
|
|
left; destruct s, s0; split; try split; easy.
|
|
right; destruct s, s0; split; try split; easy.
|
|
left; destruct s, s0; split; try split; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma div_finite_rev_n :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
ieee_float.RoundingMode.to_nearest m -> is_finite (div m x y) ->
|
|
is_finite y ->
|
|
no_overflow m ((to_real x) / (to_real y))%R /\
|
|
((to_real (div m x y)) = (round m ((to_real x) / (to_real y))%R)).
|
|
Proof.
|
|
intros m x y h1 h2 h3.
|
|
destruct (div_finite_rev m x y h2) as [(h4,(h5,h6))|(h4,(h5,h6))].
|
|
+ assert (no_overflow m (to_real x / to_real y)).
|
|
2: split; [easy|apply div_finite; easy].
|
|
pose proof max_real_ge_6.
|
|
destruct x, y; try easy; try (rewrite B754_zero_to_real).
|
|
rewrite Real.infix_sl'def, Rmult_0_l.
|
|
apply Bounded_real_no_overflow; split; lra.
|
|
set (x := B754_finite s m0 e e0).
|
|
set (y := B754_finite s0 m1 e1 e2).
|
|
fold x y in h2, h3,h4,h5,h6.
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x / to_real y))) (bpow radix2 emax)).
|
|
rewrite no_overflow_Rabs_round_emax; assumption.
|
|
assert (to_real y <> 0) by (rewrite zero_to_real in h6; auto).
|
|
pose proof (Bdiv_correct sb emax Hsb'' Hemax' m x y H0).
|
|
change (Bdiv m) with (div m) in H1.
|
|
rewrite Rlt_bool_false in H1; auto.
|
|
destruct m, h1; try easy.
|
|
destruct (div RNE x y); easy.
|
|
destruct (div RNA x y); easy.
|
|
+ destruct y; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma neg_finite :
|
|
forall (x:t), is_finite x ->
|
|
is_finite (neg x) /\ ((to_real (neg x)) = (-(to_real x))%R).
|
|
Proof.
|
|
intros x h1.
|
|
split.
|
|
unfold neg, is_finite.
|
|
rewrite is_finite_Bopp; apply h1.
|
|
apply B2R_Bopp.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma neg_finite_rev :
|
|
forall (x:t), is_finite (neg x) ->
|
|
is_finite x /\ ((to_real (neg x)) = (-(to_real x))%R).
|
|
Proof.
|
|
intros x h1.
|
|
assert (is_finite x) by now destruct x.
|
|
split; [easy| apply neg_finite; auto].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma abs_finite :
|
|
forall (x:t), is_finite x ->
|
|
is_finite (abs x) /\
|
|
((to_real (abs x)) = (Reals.Rbasic_fun.Rabs (to_real x))) /\
|
|
is_positive (abs x).
|
|
Proof.
|
|
intros x h1.
|
|
pose proof (is_finite_abs x h1).
|
|
split;[assumption|split].
|
|
apply B2R_Babs.
|
|
pose proof (is_finite_not_nan h1).
|
|
pose proof (Bsign_Babs sb emax x).
|
|
apply is_positive_Bsign.
|
|
apply (is_finite_not_nan H).
|
|
apply H1.
|
|
Qed.
|
|
|
|
(* add to theory ? *)
|
|
Lemma abs_le: forall {x y}, le (neg y) x /\ le x y -> le (abs x) y.
|
|
Proof.
|
|
intros x y.
|
|
destruct (Finite_Infinite_Nan_dec y) as [[hy|hy]|hy].
|
|
+ destruct (Finite_Infinite_Nan_dec x) as [[hx|hx]|hx].
|
|
|
|
* pose proof (is_finite_abs _ hx).
|
|
destruct (neg_finite _ hy).
|
|
rewrite (le_to_real (abs x) y) by auto.
|
|
rewrite (le_to_real (neg y) x) by auto.
|
|
rewrite le_to_real by auto.
|
|
rewrite H1 by auto.
|
|
destruct (abs_finite _ hx) as (_,(u,_)).
|
|
rewrite u.
|
|
apply Rabs_le.
|
|
|
|
* intros (a,b).
|
|
destruct (le_special _ _ b) as [H|[H|H]].
|
|
- destruct x; easy.
|
|
- pose proof (le_special _ _ a).
|
|
unfold is_minus_infinity, is_plus_infinity in H0.
|
|
destruct H0, H0, x, y; auto; try easy; destruct s, s0; auto.
|
|
- destruct y; unfold is_plus_infinity in H; easy.
|
|
|
|
* intros (a,b).
|
|
destruct (le_special _ _ b) as [H|[H|H]];
|
|
unfold is_minus_infinity in H;
|
|
destruct x; easy.
|
|
|
|
+ intros (a,b).
|
|
|
|
destruct (Finite_Infinite_Nan_dec x) as [[hx|hx]|hx].
|
|
* destruct (le_special _ _ b) as [H|[H|H]].
|
|
- destruct y; easy.
|
|
- unfold is_minus_infinity in H; destruct x; easy.
|
|
- destruct y, H as (H,(_,H')); try destruct s; try easy.
|
|
assert (~ is_nan x) by (rewrite <-is_not_nan1; assumption).
|
|
apply le_infinity.
|
|
destruct x; easy.
|
|
* destruct x, y; try easy.
|
|
destruct s; try easy.
|
|
now destruct s0.
|
|
* now destruct x.
|
|
|
|
+ intros (_,a).
|
|
destruct y; try easy.
|
|
now destruct x.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma abs_finite_rev :
|
|
forall (x:t), is_finite (abs x) ->
|
|
is_finite x /\ ((to_real (abs x)) = (Reals.Rbasic_fun.Rabs (to_real x))).
|
|
Proof.
|
|
intros x h1.
|
|
assert (is_finite x) by now destruct x.
|
|
split; [easy| apply abs_finite; auto].
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma abs_universal : forall (x:t), ~ is_negative (abs x).
|
|
Proof.
|
|
intros x.
|
|
now destruct x.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma fma_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t) (z:t), is_finite x ->
|
|
is_finite y -> is_finite z ->
|
|
no_overflow m (((to_real x) * (to_real y))%R + (to_real z))%R ->
|
|
is_finite (fma m x y z) /\
|
|
((to_real (fma m x y z)) =
|
|
(round m (((to_real x) * (to_real y))%R + (to_real z))%R)).
|
|
Proof.
|
|
intros m x y z h1 h2 h3 h4.
|
|
Admitted.
|
|
|
|
(* Why3 goal *)
|
|
Lemma fma_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t) (z:t),
|
|
is_finite (fma m x y z) -> is_finite x /\ is_finite y /\ is_finite z.
|
|
Proof.
|
|
intros m x y z h1.
|
|
Admitted.
|
|
|
|
(* Why3 goal *)
|
|
Lemma fma_finite_rev_n :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t) (z:t),
|
|
ieee_float.RoundingMode.to_nearest m -> is_finite (fma m x y z) ->
|
|
no_overflow m (((to_real x) * (to_real y))%R + (to_real z))%R /\
|
|
((to_real (fma m x y z)) =
|
|
(round m (((to_real x) * (to_real y))%R + (to_real z))%R)).
|
|
Proof.
|
|
intros m x y z h1 h2.
|
|
Admitted.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sqrt_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
(0%R <= (to_real x))%R ->
|
|
is_finite (sqrt m x) /\
|
|
((to_real (sqrt m x)) = (round m (Reals.R_sqrt.sqrt (to_real x)))).
|
|
Proof.
|
|
intros m x h1 h2.
|
|
destruct (Bsqrt_correct sb emax Hsb' Hemax' m x) as (g,(g1,g2)).
|
|
split; auto.
|
|
destruct x; try destruct s; try easy.
|
|
contradict h2.
|
|
apply Rlt_not_le, non_zero_negative_to_real; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sqrt_finite_rev :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite (sqrt m x) ->
|
|
is_finite x /\
|
|
(0%R <= (to_real x))%R /\
|
|
((to_real (sqrt m x)) = (round m (Reals.R_sqrt.sqrt (to_real x)))).
|
|
Proof.
|
|
intros m x h1.
|
|
assert (is_finite x).
|
|
destruct x; try destruct s ; try easy;
|
|
simpl in h1; unfold is_finite in h1;
|
|
now rewrite is_finite_build_nan in h1.
|
|
split; [easy|].
|
|
assert (0 <= to_real x).
|
|
{ destruct x ; try destruct s; try easy; try apply Rle_refl.
|
|
now apply F2R_ge_0. }
|
|
split; [easy| apply sqrt_finite; auto].
|
|
Qed.
|
|
|
|
(* Why3 assumption *)
|
|
Definition same_sign_real (x:t) (r:Reals.Rdefinitions.R) : Prop :=
|
|
is_positive x /\ (0%R < r)%R \/ is_negative x /\ (r < 0%R)%R.
|
|
|
|
Lemma sign_FF_overflow : forall m b,
|
|
sign_SF (binary_overflow sb emax m b) = b.
|
|
Proof.
|
|
intros m b.
|
|
unfold binary_overflow.
|
|
destruct (overflow_to_inf m b); auto.
|
|
Qed.
|
|
|
|
Lemma sign_FF_B2FF : forall x:t, sign_SF (B2SF x) = Bsign x.
|
|
Proof.
|
|
now destruct x.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma add_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
let r := add m x y in
|
|
(is_nan x \/ is_nan y -> is_nan r) /\
|
|
(is_finite x /\ is_infinite y -> is_infinite r /\ same_sign r y) /\
|
|
(is_infinite x /\ is_finite y -> is_infinite r /\ same_sign r x) /\
|
|
(is_infinite x /\ is_infinite y /\ same_sign x y ->
|
|
is_infinite r /\ same_sign r x) /\
|
|
(is_infinite x /\ is_infinite y /\ diff_sign x y -> is_nan r) /\
|
|
(is_finite x /\
|
|
is_finite y /\ ~ no_overflow m ((to_real x) + (to_real y))%R ->
|
|
same_sign_real r ((to_real x) + (to_real y))%R /\ overflow_value m r) /\
|
|
(is_finite x /\ is_finite y ->
|
|
(same_sign x y -> same_sign r x) /\
|
|
(~ same_sign x y -> sign_zero_result m r)).
|
|
Proof.
|
|
intros m x y r.
|
|
unfold same_sign, diff_sign, same_sign, same_sign_real.
|
|
split;[intro h|split;[intros (h,h1)|split;[intros (h,h1)|split;[intros (h,(h1,h2))|split;[intros (h,(h1,h2))|split;[intros (h,(h1,h2))|split;[intro h|intro h]]]]]]].
|
|
- destruct x, y; try easy; destruct s, s0, h; easy.
|
|
- destruct x, y; try easy; destruct s0; auto; easy.
|
|
- destruct x, y; try easy; destruct s; auto; easy.
|
|
- destruct x, y; try easy; destruct s, s0; destruct h2 as [(h2,h3)|(h2,h3)]; auto; easy.
|
|
- destruct x, y; try easy; destruct s, s0; destruct h2 as [(h2,h3)|(h2,h3)]; auto; easy.
|
|
- rewrite no_overflow_Rabs_round_max_real, Rabs_round_max_real_emax in h2.
|
|
apply Rnot_lt_le in h2.
|
|
pose proof (Bplus_correct sb emax Hsb' Hemax' m x y h h1).
|
|
rewrite Rlt_bool_false in H by auto.
|
|
destruct H.
|
|
split.
|
|
|
|
+ destruct x, y; try easy.
|
|
* destruct s, s0, m; simpl in H; easy.
|
|
* rewrite B754_zero_to_real at 1 2.
|
|
rewrite Rplus_0_l.
|
|
rewrite <-(@B754_zero_to_real false) at 1 2.
|
|
destruct s0;[right;split;[easy|]|left;split;[easy|]]; apply lt_finite; easy.
|
|
* rewrite B754_zero_to_real at 1 2.
|
|
rewrite Rplus_0_r.
|
|
rewrite <-(@B754_zero_to_real false) at 1 2.
|
|
destruct s;[right;split;[easy|]|left;split;[easy|]]; apply lt_finite; easy.
|
|
* change (Bplus m (B754_finite s m0 e e0) (B754_finite s0 m1 e1 e2)) with r in H.
|
|
pose proof (sign_FF_overflow m (Bsign (B754_finite s m0 e e0))).
|
|
rewrite <-H in H1.
|
|
rewrite sign_FF_B2FF in H1.
|
|
simpl Bsign at 2 in H1.
|
|
assert (~is_nan r).
|
|
{ simpl binary_overflow in H.
|
|
unfold binary_overflow in H.
|
|
destruct overflow_to_inf in H;
|
|
destruct r; try easy;
|
|
destruct n; easy. }
|
|
|
|
simpl in H0. {
|
|
destruct s;rewrite <-H0;[right|left]; split.
|
|
|
|
- rewrite <-is_negative_Bsign in H1; auto.
|
|
- assert (to_real (B754_finite true m0 e e0) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
assert (to_real (B754_finite true m1 e1 e2) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
lra.
|
|
- rewrite <-is_positive_Bsign in H1; auto.
|
|
- assert (0 < to_real (B754_finite false m0 e e0)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
assert (0 < to_real (B754_finite false m1 e1 e2)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
lra. }
|
|
|
|
+ change (Bplus m x y) with r in H.
|
|
assert (H':=H).
|
|
apply (f_equal sign_SF) in H'.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H'.
|
|
destruct m; simpl;
|
|
unfold binary_overflow in H;
|
|
simpl in H.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto). {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H'; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
destruct r; easy.
|
|
intro.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign in H2; auto; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto). {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
intro.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign in H2; auto. rewrite H' in H2; easy.
|
|
destruct r; try easy; destruct n; easy.
|
|
- split.
|
|
intro; split.
|
|
destruct r; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
+ assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto).
|
|
assert (~is_nan r) by
|
|
(destruct H1, r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign; auto. {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
rewrite H'; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
+ intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
* unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
* rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
+ easy. }
|
|
- destruct H.
|
|
pose proof (Bplus_correct sb emax Hsb' Hemax' m x y H H0).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x + to_real y))) (bpow radix2 emax)).
|
|
+ rewrite Rlt_bool_true in H1; auto.
|
|
destruct H1 as (h1,(h2,h3)).
|
|
change (Bplus m x y) with r in h1, h2, h3.
|
|
assert (~is_nan r) by (destruct r; easy).
|
|
destruct h as [(h,h')|(h,h')];[left|right];split;auto.
|
|
* rewrite is_positive_Bsign; auto.
|
|
destruct y; try destruct s; destruct x; try destruct s; try easy.
|
|
rewrite Rcompare_Gt in h3; auto.
|
|
assert (0 < B2R (B754_finite false m0 e e0)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
assert (0 < B2R (B754_finite false m1 e1 e2)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
lra.
|
|
* rewrite is_negative_Bsign; auto.
|
|
destruct y; try destruct s; destruct x; try destruct s; try easy.
|
|
rewrite Rcompare_Lt in h3; auto.
|
|
assert (B2R (B754_finite true m0 e e0) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
assert (B2R (B754_finite true m1 e1 e2) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
lra.
|
|
+ rewrite Rlt_bool_false in H1; auto.
|
|
destruct H1 as (h1,h2).
|
|
change (Bplus m x y) with r in h1.
|
|
destruct (is_nan_dec r).
|
|
destruct x; try destruct s; destruct y; try destruct s; try easy; destruct m;
|
|
unfold binary_overflow in h1; simpl in h1;
|
|
destruct r; try easy; destruct n; easy.
|
|
|
|
rewrite is_positive_Bsign; auto.
|
|
rewrite is_negative_Bsign; auto.
|
|
apply (f_equal sign_SF) in h1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in h1.
|
|
assert (~is_nan x) by (destruct x; easy).
|
|
rewrite is_positive_Bsign in h; auto.
|
|
rewrite is_negative_Bsign in h; auto.
|
|
destruct h as [(h,h')|(h,h')];rewrite h in h1, h2;[left|right];split;auto.
|
|
rewrite is_positive_Bsign; auto.
|
|
rewrite is_negative_Bsign; auto.
|
|
- intuition.
|
|
unfold sign_zero_result; intro.
|
|
unfold is_zero in H2.
|
|
rewrite eq_zero_iff in H2.
|
|
pose proof (Bplus_correct sb emax Hsb' Hemax' m x y H0 H1).
|
|
destruct (Rlt_dec (Rabs (round m (to_real x + to_real y))) (bpow radix2 emax)) as [r0|r0];
|
|
[rewrite Rlt_bool_true in H4; auto; clear r0|
|
|
rewrite Rlt_bool_false in H4].
|
|
+ destruct H4 as (h1,(h2,h)).
|
|
|
|
assert (to_real x + to_real y = 0).
|
|
{ cut (not (to_real x + to_real y <> 0)).
|
|
lra.
|
|
intros H9.
|
|
apply (round_plus_neq_0 radix2 fexp (round_mode m)) in H9.
|
|
apply H9.
|
|
destruct H2 as [H2|H2]; apply (f_equal to_real) in H2.
|
|
rewrite zeroF_to_real in H2.
|
|
rewrite <-H2; auto.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
destruct (neg_finite zeroF zero_is_finite).
|
|
rewrite H5, zeroF_to_real, Ropp_0 in H2.
|
|
rewrite <-H2; auto.
|
|
apply generic_format_B2R.
|
|
apply generic_format_B2R. }
|
|
|
|
rewrite Rcompare_Eq in h; auto.
|
|
replace (add m x y) with r in h by auto.
|
|
|
|
assert (~is_nan r) by (destruct H2, r; easy).
|
|
|
|
destruct x ; try destruct s; destruct y ; try destruct s;
|
|
try (simpl in H; contradict H; now auto);
|
|
try (destruct m; simpl in r; easy);
|
|
simpl in h;
|
|
destruct m; try (rewrite is_positive_Bsign; auto);
|
|
rewrite is_negative_Bsign; auto.
|
|
|
|
+ destruct H4.
|
|
unfold binary_overflow in H4.
|
|
change (Bplus m x y) with r in H4.
|
|
destruct H2 as [H2|H2]; rewrite H2 in H4; simpl in H4;
|
|
destruct overflow_to_inf in H4; easy.
|
|
|
|
+ apply Rnot_lt_le; assumption.
|
|
Qed.
|
|
|
|
Lemma no_overflow_or_not: forall m x, no_overflow m x \/ ~ no_overflow m x.
|
|
Proof.
|
|
intros m x.
|
|
rewrite no_overflow_Rabs_round_emax.
|
|
destruct (Rlt_dec (Rabs (round m x)) (bpow radix2 emax));[left|right]; assumption.
|
|
Qed.
|
|
|
|
Lemma add_finite_rev_n' : forall (m:mode) (x:t) (y:t),
|
|
is_finite (add m x y) ->
|
|
(no_overflow m ((to_real x) + (to_real y))%R
|
|
/\ to_real (add m x y) = round m ((to_real x) + (to_real y))%R)
|
|
\/ to_real (add m x y) = max_real \/ to_real (add m x y) =- max_real .
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct (add_finite_rev m x y h1).
|
|
|
|
destruct (no_overflow_or_not m (to_real x + to_real y));[left|right].
|
|
|
|
split; [auto|apply add_finite; easy].
|
|
destruct (add_special m x y) as (_,(_,(_,(_,(_,(h,_)))))).
|
|
assert (is_finite x /\ is_finite y /\ ~ no_overflow m (to_real x + to_real y)) by auto.
|
|
apply h in H2; clear h.
|
|
destruct H2.
|
|
destruct (add m x y); try destruct s; destruct m; simpl in *; try easy;
|
|
try (destruct H3; destruct H4; now auto);
|
|
destruct H3, H3; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sub_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
let r := sub m x y in
|
|
(is_nan x \/ is_nan y -> is_nan r) /\
|
|
(is_finite x /\ is_infinite y -> is_infinite r /\ diff_sign r y) /\
|
|
(is_infinite x /\ is_finite y -> is_infinite r /\ same_sign r x) /\
|
|
(is_infinite x /\ is_infinite y /\ same_sign x y -> is_nan r) /\
|
|
(is_infinite x /\ is_infinite y /\ diff_sign x y ->
|
|
is_infinite r /\ same_sign r x) /\
|
|
(is_finite x /\
|
|
is_finite y /\ ~ no_overflow m ((to_real x) - (to_real y))%R ->
|
|
same_sign_real r ((to_real x) - (to_real y))%R /\ overflow_value m r) /\
|
|
(is_finite x /\ is_finite y ->
|
|
(diff_sign x y -> same_sign r x) /\
|
|
(~ diff_sign x y -> sign_zero_result m r)).
|
|
Proof.
|
|
intros m x y r.
|
|
unfold same_sign, diff_sign, same_sign, same_sign_real.
|
|
split;[intro h|split;[intros (h,h1)|split;[intros (h,h1)|split;[intros (h,(h1,h2))|split;[intros (h,(h1,h2))|split;[intros (h,(h1,h2))|split;[intro h|intro h]]]]]]].
|
|
- destruct x, y; try easy; destruct s, s0; destruct h; easy.
|
|
- destruct x, y; try easy; destruct s, s0; auto; easy.
|
|
- destruct x, y; try easy; destruct s, s0; auto; easy.
|
|
- destruct x, y; try easy; destruct s, s0; destruct h2 as [(h2,h3)|(h2,h3)]; auto; easy.
|
|
- destruct x, y; try easy; destruct s, s0; destruct h2 as [(h2,h3)|(h2,h3)]; auto; easy.
|
|
- rewrite no_overflow_Rabs_round_max_real, Rabs_round_max_real_emax in h2.
|
|
apply Rnot_lt_le in h2.
|
|
pose proof (Bminus_correct sb emax Hsb' Hemax' m x y h h1).
|
|
rewrite Rlt_bool_false in H by auto.
|
|
destruct H.
|
|
split.
|
|
|
|
+ destruct x, y; try easy.
|
|
* destruct s, s0, m; simpl in H; easy.
|
|
* rewrite B754_zero_to_real at 1 2.
|
|
rewrite Rminus_0_l.
|
|
rewrite <-(@B754_zero_to_real false) at 1 2.
|
|
destruct (neg_finite (B754_finite s0 m0 e e0)) as (_,h3); auto.
|
|
rewrite <-h3.
|
|
destruct s0;[left;split;[easy|]|right;split;[easy|]]; apply lt_finite; easy.
|
|
* rewrite B754_zero_to_real at 1 2.
|
|
rewrite Rminus_0_r.
|
|
rewrite <-(@B754_zero_to_real false) at 1 2.
|
|
destruct s;[right;split;[easy|]|left;split;[easy|]]; apply lt_finite; easy.
|
|
* change (Bminus m (B754_finite s m0 e e0) (B754_finite s0 m1 e1 e2)) with r in H.
|
|
pose proof (sign_FF_overflow m (Bsign (B754_finite s m0 e e0))).
|
|
rewrite <-H in H1.
|
|
rewrite sign_FF_B2FF in H1.
|
|
simpl Bsign at 2 in H1.
|
|
assert (~is_nan r).
|
|
{ simpl binary_overflow in H.
|
|
unfold binary_overflow in H.
|
|
destruct overflow_to_inf in H;
|
|
destruct r; try easy;
|
|
destruct n; easy. }
|
|
|
|
simpl in H0.
|
|
apply Bool.negb_sym in H0. {
|
|
|
|
destruct s; simpl in H0;rewrite H0 in *;[right|left];split.
|
|
|
|
- rewrite <-is_negative_Bsign in H1; auto.
|
|
- assert (to_real (B754_finite true m0 e e0) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
assert (0 < to_real (B754_finite false m1 e1 e2)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
lra.
|
|
- rewrite <-is_positive_Bsign in H1; auto.
|
|
- assert (0 < to_real (B754_finite false m0 e e0)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
assert (to_real (B754_finite true m1 e1 e2) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
lra. }
|
|
|
|
+ change (Bminus m x y) with r in H.
|
|
assert (H':=H).
|
|
apply (f_equal sign_SF) in H'.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H'.
|
|
destruct m; simpl;
|
|
unfold binary_overflow in H;
|
|
simpl in H.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto). {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H'; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
destruct r; easy.
|
|
intro.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign in H2; auto; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto). {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
intro.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign in H2; auto. rewrite H' in H2; easy.
|
|
destruct r; try easy; destruct n; easy.
|
|
- split.
|
|
intro; split.
|
|
destruct r; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
+ assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto).
|
|
assert (~is_nan r) by
|
|
(destruct H1, r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign; auto. {
|
|
destruct H1; rewrite H1 in H', H0, H; simpl in H.
|
|
- split.
|
|
rewrite H'; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
+ intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H.
|
|
* unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H; auto.
|
|
* rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
+ easy. }
|
|
- destruct H.
|
|
pose proof (Bminus_correct sb emax Hsb' Hemax' m x y H H0).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x - to_real y))) (bpow radix2 emax)).
|
|
+ rewrite Rlt_bool_true in H1; auto.
|
|
destruct H1 as (h1,(h2,h3)).
|
|
change (Bminus m x y) with r in h1, h2, h3.
|
|
assert (~is_nan r) by (destruct r; easy).
|
|
destruct h as [(h,h')|(h,h')];[left|right];split;auto.
|
|
* rewrite is_positive_Bsign; auto.
|
|
destruct y; try destruct s; destruct x; try destruct s; try easy.
|
|
rewrite Rcompare_Gt in h3; auto.
|
|
assert (B2R (B754_finite true m0 e e0) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
assert (0 < B2R (B754_finite false m1 e1 e2)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
lra.
|
|
* rewrite is_negative_Bsign; auto.
|
|
destruct y; try destruct s; destruct x; try destruct s; try easy.
|
|
rewrite Rcompare_Lt in h3; auto.
|
|
assert (0 < B2R (B754_finite false m0 e e0)) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
assert (B2R (B754_finite true m1 e1 e2) < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
lra.
|
|
+ rewrite Rlt_bool_false in H1; auto.
|
|
destruct H1 as (h1,h2).
|
|
change (Bminus m x y) with r in h1.
|
|
destruct (is_nan_dec r).
|
|
destruct x; try destruct s; destruct y; try destruct s; try easy; destruct m;
|
|
unfold binary_overflow in h1; simpl in h1;
|
|
destruct r; try easy; destruct n; easy.
|
|
|
|
rewrite is_positive_Bsign; auto.
|
|
rewrite is_negative_Bsign; auto.
|
|
apply (f_equal sign_SF) in h1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in h1.
|
|
assert (~is_nan x) by (destruct x; easy).
|
|
assert (~is_nan y) by (destruct y; easy).
|
|
rewrite is_positive_Bsign in h,h; auto.
|
|
rewrite is_negative_Bsign in h,h; auto.
|
|
destruct h as [(h,h')|(h,h')];rewrite h in h1, h2;[left|right];split;auto.
|
|
rewrite is_positive_Bsign; auto.
|
|
rewrite is_negative_Bsign; auto.
|
|
- intuition.
|
|
unfold sign_zero_result; intro.
|
|
unfold is_zero in H2.
|
|
rewrite eq_zero_iff in H2.
|
|
pose proof (Bminus_correct sb emax Hsb' Hemax' m x y H0 H1).
|
|
destruct (Rlt_dec (Rabs (round m (to_real x - to_real y))) (bpow radix2 emax)) as [r0|r0];
|
|
[rewrite Rlt_bool_true in H4; auto; clear r0|
|
|
rewrite Rlt_bool_false in H4].
|
|
+ destruct H4 as (h1,(h2,h)).
|
|
|
|
assert (to_real x - to_real y = 0).
|
|
{ cut (not (to_real x - to_real y <> 0)).
|
|
lra.
|
|
intros H9.
|
|
apply (round_plus_neq_0 radix2 fexp (round_mode m)) in H9.
|
|
apply H9.
|
|
destruct H2 as [H2|H2]; apply (f_equal to_real) in H2.
|
|
rewrite zeroF_to_real in H2.
|
|
rewrite <-H2; auto.
|
|
assert (is_finite zeroF) as zero_is_finite by easy.
|
|
destruct (neg_finite zeroF zero_is_finite).
|
|
rewrite H5, zeroF_to_real, Ropp_0 in H2.
|
|
rewrite <-H2; auto.
|
|
apply generic_format_B2R.
|
|
destruct (neg_finite y) as (_,h3); auto; rewrite <-h3.
|
|
apply generic_format_B2R. }
|
|
|
|
rewrite Rcompare_Eq in h; auto.
|
|
change (Bminus m x y) with r in h.
|
|
|
|
assert (~is_nan r) by (destruct H2, r; easy).
|
|
|
|
destruct x ; try destruct s; destruct y ; try destruct s;
|
|
try (simpl in H; contradict H; now auto);
|
|
try (destruct m; simpl in r; easy);
|
|
simpl in h;
|
|
destruct m; try (rewrite is_positive_Bsign; auto);
|
|
rewrite is_negative_Bsign; auto.
|
|
|
|
+ destruct H4.
|
|
unfold binary_overflow in H4.
|
|
change (Bminus m x y) with r in H4.
|
|
destruct H2 as [H2|H2]; rewrite H2 in H4; simpl in H4;
|
|
destruct overflow_to_inf in H4; easy.
|
|
|
|
+ apply Rnot_lt_le; assumption.
|
|
Qed.
|
|
|
|
Lemma sub_finite_rev_n' : forall (m:mode) (x:t) (y:t),
|
|
is_finite (sub m x y) ->
|
|
(no_overflow m ((to_real x) - (to_real y))%R
|
|
/\ to_real (sub m x y) = round m ((to_real x) - (to_real y))%R)
|
|
\/ to_real (sub m x y) = max_real \/ to_real (sub m x y) =- max_real .
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct (sub_finite_rev m x y h1).
|
|
destruct (no_overflow_or_not m (to_real x - to_real y));[left|right].
|
|
split; [auto|apply sub_finite; easy].
|
|
destruct (sub_special m x y) as (_,(_,(_,(_,(_,(h,_)))))).
|
|
assert (is_finite x /\ is_finite y /\ ~ no_overflow m (to_real x - to_real y)) by auto.
|
|
apply h in H2; clear h.
|
|
destruct H2.
|
|
destruct (sub m x y); try destruct s; destruct m; simpl in *; try easy;
|
|
try (destruct H3; destruct H4; now auto);
|
|
destruct H3, H3; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma mul_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
let r := mul m x y in
|
|
(is_nan x \/ is_nan y -> is_nan r) /\
|
|
(is_zero x /\ is_infinite y -> is_nan r) /\
|
|
(is_finite x /\ is_infinite y /\ ~ is_zero x -> is_infinite r) /\
|
|
(is_infinite x /\ is_zero y -> is_nan r) /\
|
|
(is_infinite x /\ is_finite y /\ ~ is_zero y -> is_infinite r) /\
|
|
(is_infinite x /\ is_infinite y -> is_infinite r) /\
|
|
(is_finite x /\
|
|
is_finite y /\ ~ no_overflow m ((to_real x) * (to_real y))%R ->
|
|
overflow_value m r) /\
|
|
(~ is_nan r -> product_sign r x y).
|
|
Proof.
|
|
intros m x y r.
|
|
unfold product_sign, same_sign, diff_sign.
|
|
intuition.
|
|
- destruct x; easy.
|
|
- destruct x, y; easy.
|
|
- destruct x, y; try destruct s; easy.
|
|
- destruct x, y; try destruct s; try easy; contradict H2; easy.
|
|
- destruct x, y; try destruct s0; easy.
|
|
- destruct x, y; try destruct s0; try easy; contradict H2; easy.
|
|
- destruct x, y; easy.
|
|
- rewrite no_overflow_Rabs_round_max_real, Rabs_round_max_real_emax in H2.
|
|
apply Rnot_lt_le in H2.
|
|
pose proof (Bmult_correct sb emax Hsb' Hemax' m x y).
|
|
rewrite Rlt_bool_false in H1 by auto.
|
|
change (Bmult m x y) with r in H1.
|
|
assert (H1':=H1).
|
|
apply (f_equal sign_SF) in H1'.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H1'.
|
|
destruct m; simpl;
|
|
unfold binary_overflow in H1;
|
|
simpl in H1.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* destruct r; try easy; destruct n; easy.
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto).
|
|
assert (Bsign y = true \/ Bsign y = false) by
|
|
(destruct y; try destruct s; simpl; auto). {
|
|
destruct H3, H4; rewrite H3, H4 in H1', H1; simpl in H1, H1'.
|
|
- split.
|
|
destruct r; easy.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H1.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H1; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H1.
|
|
+ unfold to_real. rewrite <-min_real_is_F2R, <- SF2R_B2SF, H1; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- split.
|
|
destruct r; easy.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto).
|
|
assert (Bsign y = true \/ Bsign y = false) by
|
|
(destruct y; try destruct s; simpl; auto). {
|
|
destruct H3, H4; rewrite H3, H4 in H1', H1; simpl in H1, H1'.
|
|
- split.
|
|
{ intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H1.
|
|
+ unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H1; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1. }
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
destruct r; try easy; destruct n; easy.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
destruct r; try easy; destruct n; easy.
|
|
- split.
|
|
{ intro; split.
|
|
destruct r; try easy; destruct n; easy.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H1.
|
|
+ unfold to_real. rewrite <-max_real_is_F2R, <- SF2R_B2SF, H1; auto.
|
|
+ rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1. }
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy. }
|
|
* assert (Bsign x = true \/ Bsign x = false) by
|
|
(destruct x ; try destruct s; simpl; auto).
|
|
assert (Bsign y = true \/ Bsign y = false) by
|
|
(destruct y; try destruct s; simpl; auto).
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H1.
|
|
{ unfold to_real. rewrite <-min_real_is_F2R,<-max_real_is_F2R, <- SF2R_B2SF, H1; auto.
|
|
destruct H3, H4; rewrite H3, H4 in *; simpl in *.
|
|
- split.
|
|
intro; split; [destruct r; easy|auto].
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
intro; split; [destruct r; try easy; destruct n; easy|auto].
|
|
- split.
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy.
|
|
intro; split; [destruct r; try easy; destruct n; easy|auto].
|
|
- split.
|
|
intro; split; [destruct r; easy|auto].
|
|
assert (~is_nan r) by
|
|
(destruct r; try easy; destruct n; easy).
|
|
rewrite is_positive_Bsign, H1'; intro h; contradict h; easy. }
|
|
rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto.
|
|
now apply Pos.pow_gt_1.
|
|
- pose proof (Bmult_correct sb emax Hsb' Hemax' m x y).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x * to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H1; auto| rewrite Rlt_bool_false in H1; auto].
|
|
+ destruct H1 as (h1, (h2, h3)).
|
|
rewrite is_positive_Bsign; auto.
|
|
unfold r, mul, Hsb''.
|
|
rewrite h3.
|
|
destruct x; try destruct s; destruct y; try destruct s; easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H1.
|
|
rewrite is_positive_Bsign; auto.
|
|
destruct x; try destruct s; destruct y; try destruct s; easy.
|
|
- pose proof (Bmult_correct sb emax Hsb' Hemax' m x y).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x * to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H1; auto| rewrite Rlt_bool_false in H1; auto].
|
|
+ destruct H1 as (h1, (h2, h3)).
|
|
rewrite is_positive_Bsign; auto.
|
|
unfold r, mul, Hsb''.
|
|
rewrite h3.
|
|
destruct x; try destruct s; destruct y; try destruct s; easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H1.
|
|
rewrite is_positive_Bsign; auto.
|
|
destruct x; try destruct s; destruct y; try destruct s; easy.
|
|
- pose proof (Bmult_correct sb emax Hsb' Hemax' m x y).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x * to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H1; auto| rewrite Rlt_bool_false in H1; auto].
|
|
+ destruct H1 as (h1, (h2, h3)).
|
|
rewrite is_negative_Bsign; auto.
|
|
unfold r, mul, Hsb''.
|
|
rewrite h3.
|
|
destruct x; try destruct s; destruct y; try destruct s; auto.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H1.
|
|
rewrite is_negative_Bsign; auto.
|
|
destruct x; try destruct s; destruct y; try destruct s; auto.
|
|
- pose proof (Bmult_correct sb emax Hsb' Hemax' m x y).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x * to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H1; auto| rewrite Rlt_bool_false in H1; auto].
|
|
+ destruct H1 as (h1, (h2, h3)).
|
|
rewrite is_negative_Bsign; auto.
|
|
unfold r, mul, Hsb''.
|
|
rewrite h3.
|
|
destruct x; try destruct s; destruct y; try destruct s; auto.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H1.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H1.
|
|
rewrite is_negative_Bsign; auto.
|
|
destruct x; try destruct s; destruct y; try destruct s; auto.
|
|
Qed.
|
|
|
|
Lemma mul_finite_rev_n' : forall (m:mode) (x:t) (y:t),
|
|
is_finite (mul m x y) ->
|
|
(no_overflow m ((to_real x) * (to_real y))%R
|
|
/\ to_real (mul m x y) = round m ((to_real x) * (to_real y))%R)
|
|
\/ to_real (mul m x y) = max_real \/ to_real (mul m x y) =- max_real .
|
|
Proof.
|
|
intros m x y h1.
|
|
destruct (mul_finite_rev m x y h1).
|
|
destruct (no_overflow_or_not m (to_real x * to_real y));[left|right].
|
|
split; [auto|apply mul_finite; easy].
|
|
destruct (mul_special m x y) as (_,(_,(_,(_,(_,(_,(h,_))))))).
|
|
assert (is_finite x /\ is_finite y /\ ~ no_overflow m (to_real x * to_real y)) by auto.
|
|
apply h in H2; clear h.
|
|
destruct (mul m x y); try destruct s; destruct m; simpl in *; try easy;
|
|
try (destruct H2; destruct H3; now auto);
|
|
destruct H2, H2; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma div_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t),
|
|
let r := div m x y in
|
|
(is_nan x \/ is_nan y -> is_nan r) /\
|
|
(is_finite x /\ is_infinite y -> is_zero r) /\
|
|
(is_infinite x /\ is_finite y -> is_infinite r) /\
|
|
(is_infinite x /\ is_infinite y -> is_nan r) /\
|
|
(is_finite x /\
|
|
is_finite y /\
|
|
~ is_zero y /\ ~ no_overflow m ((to_real x) / (to_real y))%R ->
|
|
overflow_value m r) /\
|
|
(is_finite x /\ is_zero y /\ ~ is_zero x -> is_infinite r) /\
|
|
(is_zero x /\ is_zero y -> is_nan r) /\ (~ is_nan r -> product_sign r x y).
|
|
Proof.
|
|
intros m x y r.
|
|
unfold product_sign, same_sign, diff_sign.
|
|
intuition.
|
|
- destruct x; easy.
|
|
- destruct x, y; easy.
|
|
- destruct x, y; try destruct s; easy.
|
|
- destruct x, y; try destruct s; try easy; contradict H2; easy.
|
|
- destruct x, y; try destruct s0; easy.
|
|
- assert (to_real y <> 0) by (rewrite zero_to_real in H1; auto).
|
|
pose proof (Bdiv_correct sb emax Hsb' Hemax' m x y H2).
|
|
rewrite Rlt_bool_false in H4.
|
|
+ unfold binary_overflow in H4.
|
|
change (Bdiv m x y) with r in H4; auto.
|
|
destruct m; simpl in *.
|
|
* now destruct r.
|
|
* now destruct r.
|
|
* destruct (xorb (Bsign x) (Bsign y)); simpl in H4. {
|
|
split; intro.
|
|
- destruct r; try destruct s; easy.
|
|
- split; [destruct r; try easy; destruct b, n in H4; easy|].
|
|
apply (f_equal (SF2R radix2)) in H4.
|
|
rewrite SF2R_B2SF in H4.
|
|
simpl in H4.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H4 by
|
|
(rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto;
|
|
now apply Pos.pow_gt_1).
|
|
rewrite <-min_real_is_F2R; assumption. }
|
|
split; intro; [destruct r; easy|].
|
|
destruct r; try easy.
|
|
destruct s; try easy.
|
|
simpl in H5; contradict H5; auto.
|
|
* destruct (xorb (Bsign x) (Bsign y)); simpl in H4. {
|
|
split; intro.
|
|
- destruct r; try destruct s; easy.
|
|
- now destruct r. }
|
|
{ split; intro.
|
|
+ split;[destruct r; easy|].
|
|
apply (f_equal (SF2R radix2)) in H4.
|
|
rewrite SF2R_B2SF in H4.
|
|
simpl in H4.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H4 by
|
|
(rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto;
|
|
now apply Pos.pow_gt_1).
|
|
rewrite <-max_real_is_F2R; assumption.
|
|
+ destruct r; try easy; try (destruct n; easy).
|
|
destruct s; try easy.
|
|
simpl in H5; contradict H5; auto. }
|
|
* { destruct (xorb (Bsign x) (Bsign y)); simpl in H4;
|
|
split; intro.
|
|
- destruct r; try destruct s; easy.
|
|
- split;[destruct r; try destruct s; try easy; destruct n; easy|].
|
|
apply (f_equal (SF2R radix2)) in H4.
|
|
rewrite SF2R_B2SF in H4.
|
|
simpl in H4.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H4 by
|
|
(rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto;
|
|
now apply Pos.pow_gt_1).
|
|
rewrite <-min_real_is_F2R; assumption.
|
|
- split; [destruct r; try easy| ].
|
|
apply (f_equal (SF2R radix2)) in H4.
|
|
rewrite SF2R_B2SF in H4.
|
|
simpl in H4.
|
|
replace (Z.pow_pos 2 sb_pos - 1)%Z with (Z.pos (2 ^ sb_pos - 1)) in H4 by
|
|
(rewrite Pos2Z.inj_sub, Pos2Z.inj_pow_pos; auto;
|
|
now apply Pos.pow_gt_1).
|
|
rewrite <-max_real_is_F2R; assumption.
|
|
- contradict H5.
|
|
destruct r; try destruct s; easy. }
|
|
+ clear H4.
|
|
rewrite no_overflow_Rabs_round_emax in H3.
|
|
apply Rge_le, Rnot_lt_ge; assumption.
|
|
- destruct x, y; try easy.
|
|
rewrite is_zero_B754_zero in H2; destruct H2; exists s; reflexivity.
|
|
rewrite is_zero_B754_zero in H2; destruct H2; exists s; reflexivity.
|
|
rewrite is_zero_B754_zero in H; destruct H; inversion H.
|
|
rewrite is_zero_B754_zero in H; destruct H; inversion H.
|
|
- rewrite is_zero_B754_zero in H0; destruct H0.
|
|
rewrite is_zero_B754_zero in H1; destruct H1.
|
|
destruct x, y; easy.
|
|
- destruct x ; try destruct s; destruct y ; try destruct s; try easy.
|
|
now elim H.
|
|
now elim H.
|
|
set (x:=B754_finite false m0 e e0);
|
|
set (y:=B754_finite false m1 e1 e2); fold x y in r, H0, H2.
|
|
assert (to_real y <> 0).
|
|
{ assert (0 < to_real y) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
apply not_eq_sym, Rlt_not_eq; lra. }
|
|
pose proof (Bdiv_correct sb emax Hsb' Hemax' m x y H1).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x / to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H3|rewrite Rlt_bool_false in H3];auto.
|
|
+ destruct H3 as (_,(_,h)).
|
|
rewrite is_positive_Bsign; auto.
|
|
unfold r, div, Hsb''.
|
|
rewrite h.
|
|
easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H3.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H3.
|
|
rewrite is_positive_Bsign; auto.
|
|
- destruct x ; try destruct s; destruct y ; try destruct s; try easy.
|
|
now elim H.
|
|
now elim H.
|
|
set (x:=B754_finite true m0 e e0);
|
|
set (y:=B754_finite true m1 e1 e2); fold x y in r, H0, H2.
|
|
assert (to_real y <> 0).
|
|
{ assert (to_real y < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
apply Rlt_not_eq; lra. }
|
|
pose proof (Bdiv_correct sb emax Hsb' Hemax' m x y H1).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x / to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H3|rewrite Rlt_bool_false in H3];auto.
|
|
+ destruct H3 as (_,(_,h)).
|
|
rewrite is_positive_Bsign; auto.
|
|
unfold r, div, Hsb''.
|
|
rewrite h.
|
|
easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H3.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H3.
|
|
rewrite is_positive_Bsign; auto.
|
|
- destruct x ; try destruct s; destruct y ; try destruct s; try easy.
|
|
now elim H.
|
|
now elim H.
|
|
set (x:=B754_finite false m0 e e0);
|
|
set (y:=B754_finite true m1 e1 e2); fold x y in r, H0, H2.
|
|
assert (to_real y <> 0).
|
|
{ assert (to_real y < 0) by
|
|
(apply non_zero_negative_to_real; easy).
|
|
apply Rlt_not_eq; lra. }
|
|
pose proof (Bdiv_correct sb emax Hsb' Hemax' m x y H1).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x / to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H3|rewrite Rlt_bool_false in H3];auto.
|
|
+ destruct H3 as (_,(_,h)).
|
|
rewrite is_negative_Bsign; auto.
|
|
unfold r, div, Hsb''.
|
|
rewrite h.
|
|
easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H3.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H3.
|
|
rewrite is_negative_Bsign; auto.
|
|
- destruct x; try destruct s; destruct y; try destruct s; try easy.
|
|
now elim H.
|
|
now elim H.
|
|
set (x:=B754_finite true m0 e e0);
|
|
set (y:=B754_finite false m1 e1 e2); fold x y in r, H0, H2.
|
|
assert (to_real y <> 0).
|
|
{ assert (0 < to_real y) by
|
|
(apply non_zero_positive_to_real; easy).
|
|
apply not_eq_sym, Rlt_not_eq; lra. }
|
|
pose proof (Bdiv_correct sb emax Hsb' Hemax' m x y H1).
|
|
destruct (Rlt_le_dec (Rabs (round m (to_real x / to_real y))) (bpow radix2 emax));
|
|
[rewrite Rlt_bool_true in H3|rewrite Rlt_bool_false in H3];auto.
|
|
+ destruct H3 as (_,(_,h)).
|
|
rewrite is_negative_Bsign; auto.
|
|
unfold r, div, Hsb''.
|
|
rewrite h.
|
|
easy.
|
|
now apply Bool.not_true_is_false.
|
|
+ apply (f_equal sign_SF) in H3.
|
|
rewrite sign_FF_B2FF, sign_FF_overflow in H3.
|
|
rewrite is_negative_Bsign; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma neg_special :
|
|
forall (x:t),
|
|
(is_nan x -> is_nan (neg x)) /\
|
|
(is_infinite x -> is_infinite (neg x)) /\
|
|
(~ is_nan x -> diff_sign x (neg x)).
|
|
Proof.
|
|
intros x.
|
|
split; [|split]; intro.
|
|
- destruct x; easy.
|
|
- destruct x; easy.
|
|
- unfold diff_sign.
|
|
destruct x.
|
|
destruct s;[right|left]; easy.
|
|
destruct s;[right|left]; easy.
|
|
contradict H; easy.
|
|
destruct s;[right|left]; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma abs_special :
|
|
forall (x:t),
|
|
(is_nan x -> is_nan (abs x)) /\
|
|
(is_infinite x -> is_infinite (abs x)) /\
|
|
(~ is_nan x -> is_positive (abs x)).
|
|
Proof.
|
|
intros x.
|
|
split;[|split];intro.
|
|
- destruct x; easy.
|
|
- destruct x; easy.
|
|
- destruct x; try easy.
|
|
contradict H; easy.
|
|
Qed.
|
|
|
|
(* add to theory ? *)
|
|
Lemma abs_le_inv: forall {x y}, le (abs x) y -> le (neg y) x /\ le x y.
|
|
Proof.
|
|
intros x y.
|
|
destruct (Finite_Infinite_Nan_dec y) as [[hy|hy]|hy].
|
|
+ destruct (Finite_Infinite_Nan_dec x) as [[hx|hx]|hx].
|
|
|
|
* pose proof (is_finite_abs _ hx).
|
|
destruct (neg_finite _ hy).
|
|
rewrite (le_to_real (abs x) y) by auto.
|
|
rewrite (le_to_real (neg y) x) by auto.
|
|
rewrite le_to_real by auto.
|
|
rewrite H1 by auto.
|
|
destruct (abs_finite _ hx) as (_,(u,_)).
|
|
rewrite u.
|
|
apply Rabs_le_inv.
|
|
|
|
* intros a.
|
|
pose proof (abs_special x) as (_,(b,_)); pose proof (b hx); clear b.
|
|
destruct (le_special _ _ a) as [H1|[H1|H1]].
|
|
- destruct x; easy.
|
|
- unfold is_minus_infinity in H1.
|
|
destruct H1, H1, x, y; try easy; destruct b0, b1; easy.
|
|
- destruct y; unfold is_plus_infinity in H1; easy.
|
|
|
|
* intros a.
|
|
pose proof (abs_special x) as (b,_); pose proof (b hx); clear b.
|
|
destruct (le_special _ _ a) as [H1|[H1|H1]];
|
|
unfold is_minus_infinity, is_not_nan in H1;
|
|
destruct (abs x), H1; easy.
|
|
|
|
+ intros a.
|
|
|
|
destruct (Finite_Infinite_Nan_dec x) as [[hx|hx]|hx].
|
|
* pose proof (is_finite_abs _ hx).
|
|
destruct (le_special _ _ a) as [H1|[H1|H1]].
|
|
- destruct y; easy.
|
|
- unfold is_minus_infinity in H1; destruct x; easy.
|
|
- destruct y, H1; try easy.
|
|
unfold is_plus_infinity in H1; destruct s; try easy.
|
|
destruct x ; try destruct s; split; easy.
|
|
* unfold Bcompare.
|
|
destruct x, y; try easy; destruct s, s0; simpl; split; auto; easy.
|
|
* now destruct x.
|
|
+ intros a.
|
|
destruct y; unfold le, Bcompare in a; try easy.
|
|
destruct x; try destruct s0; split; easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma fma_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t) (z:t),
|
|
let r := fma m x y z in
|
|
(is_nan x \/ is_nan y \/ is_nan z -> is_nan r) /\
|
|
(is_zero x /\ is_infinite y -> is_nan r) /\
|
|
(is_infinite x /\ is_zero y -> is_nan r) /\
|
|
(is_finite x /\ ~ is_zero x /\ is_infinite y /\ is_finite z ->
|
|
is_infinite r /\ product_sign r x y) /\
|
|
(is_finite x /\ ~ is_zero x /\ is_infinite y /\ is_infinite z ->
|
|
(product_sign z x y -> is_infinite r /\ same_sign r z) /\
|
|
(~ product_sign z x y -> is_nan r)) /\
|
|
(is_infinite x /\ is_finite y /\ ~ is_zero y /\ is_finite z ->
|
|
is_infinite r /\ product_sign r x y) /\
|
|
(is_infinite x /\ is_finite y /\ ~ is_zero y /\ is_infinite z ->
|
|
(product_sign z x y -> is_infinite r /\ same_sign r z) /\
|
|
(~ product_sign z x y -> is_nan r)) /\
|
|
(is_infinite x /\ is_infinite y /\ is_finite z ->
|
|
is_infinite r /\ product_sign r x y) /\
|
|
(is_finite x /\ is_finite y /\ is_infinite z ->
|
|
is_infinite r /\ same_sign r z) /\
|
|
(is_infinite x /\ is_infinite y /\ is_infinite z ->
|
|
(product_sign z x y -> is_infinite r /\ same_sign r z) /\
|
|
(~ product_sign z x y -> is_nan r)) /\
|
|
(is_finite x /\
|
|
is_finite y /\
|
|
is_finite z /\
|
|
~ no_overflow m (((to_real x) * (to_real y))%R + (to_real z))%R ->
|
|
same_sign_real r (((to_real x) * (to_real y))%R + (to_real z))%R /\
|
|
overflow_value m r) /\
|
|
(is_finite x /\ is_finite y /\ is_finite z ->
|
|
(product_sign z x y -> same_sign r z) /\
|
|
(~ product_sign z x y ->
|
|
((((to_real x) * (to_real y))%R + (to_real z))%R = 0%R) ->
|
|
((m = ieee_float.RoundingMode.RTN) -> is_negative r) /\
|
|
(~ (m = ieee_float.RoundingMode.RTN) -> is_positive r))).
|
|
Proof.
|
|
intros m x y z r.
|
|
Admitted.
|
|
|
|
Lemma fma_finite_rev_n' : forall (m:mode) (x:t) (y:t) (z:t),
|
|
is_finite (fma m x y z) ->
|
|
(no_overflow m (to_real x * to_real y + to_real z)%R
|
|
/\ to_real (fma m x y z) = round m (to_real x * to_real y + to_real z)%R)
|
|
\/ to_real (fma m x y z) = max_real \/ to_real (fma m x y z) =- max_real .
|
|
Proof.
|
|
intros m x y z h1.
|
|
destruct (fma_finite_rev m x y z h1) as (H,(H0,H1)).
|
|
|
|
destruct (no_overflow_or_not m (to_real x * to_real y + to_real z));[left|right].
|
|
|
|
split; [auto|apply fma_finite; easy].
|
|
destruct (fma_special m x y z) as (_,(_,(_,(_,(_,(_,(_,(_,(_,(_,(h,_))))))))))).
|
|
assert (is_finite x /\ is_finite y /\ is_finite z /\ ~ no_overflow m (to_real x * to_real y + to_real z)) by auto.
|
|
apply h in H3; clear h.
|
|
destruct (fma m x y z); try destruct s; destruct m; simpl in *; try easy;
|
|
try (destruct H3; destruct H4; destruct H4; now auto);
|
|
destruct H3; destruct H4; destruct H5; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sqrt_special :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t),
|
|
let r := sqrt m x in
|
|
(is_nan x -> is_nan r) /\
|
|
(is_plus_infinity x -> is_plus_infinity r) /\
|
|
(is_minus_infinity x -> is_nan r) /\
|
|
(is_finite x /\ ((to_real x) < 0%R)%R -> is_nan r) /\
|
|
(is_zero x -> same_sign r x) /\
|
|
(is_finite x /\ (0%R < (to_real x))%R -> is_positive r).
|
|
Proof.
|
|
intros m x r.
|
|
unfold sqrt in r.
|
|
intuition.
|
|
- destruct x; easy.
|
|
- unfold is_plus_infinity in *.
|
|
destruct x ; try destruct s; easy.
|
|
- unfold is_minus_infinity in H.
|
|
destruct x ; try destruct s; easy.
|
|
- destruct x ; try destruct s; try easy.
|
|
rewrite B754_zero_to_real in H1; lra.
|
|
rewrite B754_zero_to_real in H1; lra.
|
|
apply (to_real_negative _ H0) in H1.
|
|
rewrite is_negative_Bsign in H1 by easy.
|
|
easy.
|
|
- unfold same_sign.
|
|
rewrite is_zero_B754_zero in H; destruct H.
|
|
destruct x; try easy.
|
|
destruct s;[right|left];split;auto.
|
|
simpl in r; unfold r; auto.
|
|
simpl in r; unfold r; auto.
|
|
- destruct (Bsqrt_correct sb emax Hsb' Hemax' m x) as (_,(h1,h2));
|
|
fold r in h1, h2.
|
|
destruct x; try easy.
|
|
rewrite B754_zero_to_real in H1 at 1; lra.
|
|
apply (to_real_positive _ H0) in H1.
|
|
rewrite is_positive_Bsign in H1 by easy.
|
|
simpl in H1.
|
|
destruct s; try easy.
|
|
assert (not (is_nan r)) by (destruct r; easy).
|
|
rewrite (is_positive_Bsign _ H).
|
|
apply h2.
|
|
now apply Bool.not_true_is_false.
|
|
Qed.
|
|
|
|
Lemma in_int_range_no_overflow : forall m {i}, in_int_range i -> no_overflow m (IZR i).
|
|
Proof.
|
|
intros m i h.
|
|
apply Bounded_real_no_overflow.
|
|
unfold in_int_range in h.
|
|
unfold in_range.
|
|
rewrite max_real_int, <- FromInt.Neg.
|
|
pose proof pow2sb_lt_max_int.
|
|
split; apply IZR_le; auto with zarith.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma of_int_add_exact :
|
|
forall (m:ieee_float.RoundingMode.mode) (n:ieee_float.RoundingMode.mode)
|
|
(i:Numbers.BinNums.Z) (j:Numbers.BinNums.Z),
|
|
in_safe_int_range i -> in_safe_int_range j ->
|
|
in_safe_int_range (i + j)%Z ->
|
|
eq (of_int m (i + j)%Z) (add n (of_int m i) (of_int m j)).
|
|
Proof.
|
|
intros m n i j h1 h2 h3.
|
|
assert (h1':= in_safe_int_range_no_overflow m h1).
|
|
assert (h2':= in_safe_int_range_no_overflow m h2).
|
|
assert (h3':= in_safe_int_range_no_overflow n h3).
|
|
assert (h3'':= in_safe_int_range_no_overflow m h3).
|
|
assert (is_finite (of_int m i)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m j)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int n (i+j)%Z)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m (i+j)%Z)) by (apply of_int_correct; assumption).
|
|
destruct (of_int_correct h1') as (f,_).
|
|
destruct (of_int_correct h2') as (g,_).
|
|
destruct (add_finite n (of_int m i) (of_int m j)); auto.
|
|
simpl; rewrite f, g, Exact_rounding_for_integers, Exact_rounding_for_integers; auto.
|
|
rewrite <-plus_IZR; assumption.
|
|
destruct (of_int_correct h3'') as (h,_).
|
|
rewrite to_real_eq, H4, f, g, h; auto.
|
|
repeat rewrite Exact_rounding_for_integers; auto.
|
|
rewrite <-plus_IZR, Exact_rounding_for_integers; auto; reflexivity.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma of_int_sub_exact :
|
|
forall (m:ieee_float.RoundingMode.mode) (n:ieee_float.RoundingMode.mode)
|
|
(i:Numbers.BinNums.Z) (j:Numbers.BinNums.Z),
|
|
in_safe_int_range i -> in_safe_int_range j ->
|
|
in_safe_int_range (i - j)%Z ->
|
|
eq (of_int m (i - j)%Z) (sub n (of_int m i) (of_int m j)).
|
|
Proof.
|
|
intros m n i j h1 h2 h3.
|
|
assert (h1':= in_safe_int_range_no_overflow m h1).
|
|
assert (h2':= in_safe_int_range_no_overflow m h2).
|
|
assert (h3':= in_safe_int_range_no_overflow n h3).
|
|
assert (h3'':= in_safe_int_range_no_overflow m h3).
|
|
assert (is_finite (of_int m i)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m j)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int n (i-j)%Z)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m (i-j)%Z)) by (apply of_int_correct; assumption).
|
|
destruct (of_int_correct h1') as (f,_).
|
|
destruct (of_int_correct h2') as (g,_).
|
|
destruct (sub_finite n (of_int m i) (of_int m j)); auto.
|
|
simpl; rewrite f, g, Exact_rounding_for_integers, Exact_rounding_for_integers; auto.
|
|
rewrite <-minus_IZR; assumption.
|
|
destruct (of_int_correct h3'') as (h,_).
|
|
rewrite to_real_eq, H4, f, g, h; auto.
|
|
repeat rewrite Exact_rounding_for_integers; auto.
|
|
rewrite <-minus_IZR, Exact_rounding_for_integers; auto; reflexivity.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma of_int_mul_exact :
|
|
forall (m:ieee_float.RoundingMode.mode) (n:ieee_float.RoundingMode.mode)
|
|
(i:Numbers.BinNums.Z) (j:Numbers.BinNums.Z),
|
|
in_safe_int_range i -> in_safe_int_range j ->
|
|
in_safe_int_range (i * j)%Z ->
|
|
eq (of_int m (i * j)%Z) (mul n (of_int m i) (of_int m j)).
|
|
Proof.
|
|
intros m n i j h1 h2 h3.
|
|
assert (h1':= in_safe_int_range_no_overflow m h1).
|
|
assert (h2':= in_safe_int_range_no_overflow m h2).
|
|
assert (h3':= in_safe_int_range_no_overflow n h3).
|
|
assert (h3'':= in_safe_int_range_no_overflow m h3).
|
|
assert (is_finite (of_int m i)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m j)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int n (i*j)%Z)) by (apply of_int_correct; assumption).
|
|
assert (is_finite (of_int m (i*j)%Z)) by (apply of_int_correct; assumption).
|
|
destruct (of_int_correct h1') as (f,_).
|
|
destruct (of_int_correct h2') as (g,_).
|
|
destruct (mul_finite n (of_int m i) (of_int m j)); auto.
|
|
simpl; rewrite f, g,
|
|
Exact_rounding_for_integers, Exact_rounding_for_integers; auto.
|
|
rewrite <-mult_IZR; assumption.
|
|
destruct (of_int_correct h3'') as (h,_).
|
|
rewrite to_real_eq, H4, f, g, h; auto.
|
|
repeat rewrite Exact_rounding_for_integers; auto.
|
|
rewrite <-mult_IZR, Exact_rounding_for_integers; auto; reflexivity.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Min_r : forall (x:t) (y:t), le y x -> eq (min x y) y.
|
|
Proof.
|
|
intros x y h1.
|
|
unfold min.
|
|
apply le_correct in h1.
|
|
destruct h1;
|
|
pose (Bcompare_swap _ _ y x);
|
|
rewrite H in e;
|
|
unfold min; rewrite e; simpl.
|
|
apply (eq_not_nan_refl (proj1 (lt_not_nan H))).
|
|
apply (eq_not_nan_refl (proj1 (eq_not_nan H))).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Min_l : forall (x:t) (y:t), le x y -> eq (min x y) x.
|
|
Proof.
|
|
intros x y h1.
|
|
apply le_correct in h1.
|
|
destruct h1; unfold min; rewrite H; simpl.
|
|
apply (eq_not_nan_refl (proj1 (lt_not_nan H))).
|
|
pose (Bcompare_swap _ _ x y); rewrite H in e; apply e.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Max_r : forall (x:t) (y:t), le y x -> eq (max x y) x.
|
|
Proof.
|
|
intros x y h1.
|
|
apply le_correct in h1.
|
|
destruct h1;
|
|
pose (Bcompare_swap _ _ y x);
|
|
rewrite H in e;
|
|
unfold max; rewrite e; simpl.
|
|
apply (eq_not_nan_refl (proj2 (lt_not_nan H))).
|
|
apply (eq_not_nan_refl (proj2 (eq_not_nan H))).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma Max_l : forall (x:t) (y:t), le x y -> eq (max x y) y.
|
|
Proof.
|
|
intros x y h1.
|
|
apply le_correct in h1.
|
|
destruct h1; unfold max; rewrite H; simpl.
|
|
apply (eq_not_nan_refl (proj2 (lt_not_nan H))).
|
|
apply H.
|
|
Qed.
|
|
|
|
Definition is_intR: R -> Prop.
|
|
Proof.
|
|
exact (fun x => x = IZR (Zfloor x)).
|
|
Defined.
|
|
|
|
Lemma is_intR_equiv: forall {x}, (exists i:int, x = IZR i) -> is_intR x.
|
|
Proof.
|
|
unfold is_intR.
|
|
intros x h; destruct h.
|
|
rewrite H, Zfloor_IZR; reflexivity.
|
|
Qed.
|
|
|
|
Lemma is_intR_IZR: forall i, is_intR (IZR i).
|
|
Proof.
|
|
intro i; apply is_intR_equiv; exists i; reflexivity.
|
|
Qed.
|
|
|
|
Lemma is_intR_FIX_format: forall {x}, is_intR x <-> FIX_format radix2 0%Z x.
|
|
Proof.
|
|
intro x; split; intro.
|
|
exists ({| Fnum := Zfloor x; Fexp := 0 |}); simpl; auto.
|
|
unfold F2R, Fnum, Fexp; simpl.
|
|
rewrite Rmult_1_r; assumption.
|
|
destruct H.
|
|
unfold F2R in H.
|
|
rewrite H0 in H; simpl in H.
|
|
rewrite Rmult_1_r in H.
|
|
apply is_intR_equiv.
|
|
exists (Fnum f); assumption.
|
|
Qed.
|
|
|
|
Lemma is_intR_round: forall {x m}, is_intR x -> is_intR (round m x).
|
|
Proof.
|
|
intros x m h.
|
|
rewrite is_intR_FIX_format.
|
|
apply FIX_format_generic.
|
|
apply generic_round_generic.
|
|
apply FIX_exp_valid.
|
|
apply fexp_Valid.
|
|
apply valid_rnd_round_mode.
|
|
apply generic_format_FIX.
|
|
rewrite <-is_intR_FIX_format; assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Definition is_int : t -> Prop.
|
|
Proof.
|
|
exact (fun x => is_finite x /\ is_intR (to_real x)).
|
|
Defined.
|
|
|
|
Hint Unfold is_int.
|
|
|
|
Lemma is_int_or_not: forall (x:t), is_int x \/ ~ is_int x.
|
|
Proof.
|
|
intro x.
|
|
destruct x.
|
|
- left.
|
|
split.
|
|
easy.
|
|
rewrite B754_zero_to_real.
|
|
unfold is_intR.
|
|
rewrite Zfloor_IZR; auto.
|
|
- right; intro h; destruct h; easy.
|
|
- right; intro h; destruct h; easy.
|
|
- set (x := (B754_finite s m e e0)).
|
|
unfold is_int, is_intR.
|
|
destruct (Req_dec (to_real x) (IZR (floor (to_real x)))).
|
|
left.
|
|
rewrite H, Zfloor_IZR; easy.
|
|
right.
|
|
intro h; destruct h; auto.
|
|
Qed.
|
|
|
|
Lemma Bmax_rep_int_is_int: is_int Bmax_rep_int.
|
|
Proof.
|
|
split. easy.
|
|
rewrite Bmax_rep_int_to_real.
|
|
apply is_intR_IZR.
|
|
Qed.
|
|
|
|
Lemma B754_zero_is_int : forall {b}, (is_int (B754_zero b)).
|
|
Proof.
|
|
split. easy.
|
|
rewrite B754_zero_to_real.
|
|
unfold is_intR.
|
|
now rewrite Zfloor_IZR.
|
|
Qed.
|
|
|
|
Lemma max_value_is_int : is_int max_value.
|
|
Proof.
|
|
split. easy.
|
|
unfold is_intR.
|
|
rewrite max_value_to_real, max_real_int.
|
|
rewrite Floor_int.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
(* TODO: add to theory *)
|
|
Lemma neg_is_int : forall {x}, is_int x -> is_int (neg x).
|
|
Proof.
|
|
intros x (h,g).
|
|
destruct (neg_finite _ h).
|
|
split; auto.
|
|
rewrite H0.
|
|
rewrite g.
|
|
unfold is_intR.
|
|
rewrite <- opp_IZR at 2.
|
|
rewrite Zfloor_IZR.
|
|
symmetry; apply opp_IZR.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma zeroF_is_int : is_int zeroF.
|
|
Proof.
|
|
apply B754_zero_is_int.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma of_int_is_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:Numbers.BinNums.Z),
|
|
in_int_range x -> is_int (of_int m x).
|
|
Proof.
|
|
intros m x (h1,h2).
|
|
assert (no_overflow m (IZR x)) as h3.
|
|
apply Bounded_real_no_overflow.
|
|
unfold in_range.
|
|
rewrite max_real_int.
|
|
rewrite <-opp_IZR.
|
|
split; apply IZR_le; assumption.
|
|
destruct (of_int_correct h3) as (h4,(h5,_)).
|
|
split; auto.
|
|
rewrite h4.
|
|
apply is_intR_round.
|
|
apply is_intR_IZR.
|
|
Qed.
|
|
|
|
Lemma int_to_real_ : forall {m:mode} {x:t}, (is_int x) ->
|
|
((to_real x) = (BuiltIn.IZR (to_int m x))).
|
|
Proof.
|
|
intros m x h1.
|
|
destruct h1.
|
|
assert (is_intR (to_real x)) by assumption.
|
|
unfold is_intR in H0.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
case m;
|
|
[auto|
|
|
destruct valid_rnd_NA|
|
|
destruct valid_rnd_UP|
|
|
destruct valid_rnd_DN|
|
|
destruct valid_rnd_ZR]; rewrite H0;
|
|
rewrite Zrnd_IZR; try easy.
|
|
apply valid_rnd_N.
|
|
Qed.
|
|
|
|
(* TODO: add to theory? *)
|
|
Lemma neg_int_to_int : forall {x} {m:mode}, is_int x -> to_int m (neg x) = (- (to_int m x))%Z.
|
|
Proof.
|
|
intros x m h.
|
|
apply eq_IZR.
|
|
rewrite FromInt.Neg, <-(int_to_real_ h), <-(int_to_real_ (neg_is_int h)).
|
|
destruct h.
|
|
apply neg_finite; auto.
|
|
Qed.
|
|
|
|
Lemma Bmax_rep_int_to_int: forall {m}, to_int m Bmax_rep_int = pow2sb.
|
|
Proof.
|
|
intro m.
|
|
apply eq_IZR.
|
|
rewrite <-int_to_real_.
|
|
apply Bmax_rep_int_to_real.
|
|
apply Bmax_rep_int_is_int.
|
|
Qed.
|
|
|
|
Lemma pow2sb_finite : forall (m:mode), is_finite (of_int m pow2sb).
|
|
Proof.
|
|
intro.
|
|
apply of_int_correct.
|
|
apply Bounded_real_no_overflow.
|
|
apply rep_int_in_range.
|
|
split; auto with zarith.
|
|
unfold pow2sb.
|
|
assert (0 <= 2 ^ sb)%Z by (apply Z.pow_nonneg; auto with zarith).
|
|
auto with zarith.
|
|
Qed.
|
|
|
|
Lemma Bmax_rep_int_of_int: forall {m:mode}, Bmax_rep_int = of_int m pow2sb.
|
|
Proof.
|
|
intro m.
|
|
pose proof pow2sb_finite.
|
|
apply feq_eq; try easy.
|
|
rewrite to_real_eq; try easy.
|
|
|
|
assert (- pow2sb <= pow2sb <= pow2sb)%Z.
|
|
split; auto with zarith.
|
|
assert (0 < pow2sb)%Z.
|
|
apply (Z.pow_pos_nonneg 2 sb).
|
|
easy.
|
|
apply Z.lt_le_incl, Hsb'.
|
|
auto with zarith.
|
|
|
|
destruct (@of_int_correct m pow2sb) as (f,_); auto.
|
|
apply Bounded_real_no_overflow.
|
|
apply rep_int_in_range; auto.
|
|
|
|
rewrite f, Bmax_rep_int_to_real.
|
|
symmetry.
|
|
apply Exact_rounding_for_integers; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma big_float_is_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (i:t), is_finite i ->
|
|
le i (neg (of_int m pow2sb)) \/ le (of_int m pow2sb) i -> is_int i.
|
|
Proof.
|
|
intros m i h1 h2.
|
|
destruct i; try easy.
|
|
apply B754_zero_is_int.
|
|
split; auto.
|
|
rewrite <-Bmax_rep_int_of_int in h2.
|
|
unfold to_real, B2R, F2R,Fnum,Fexp.
|
|
|
|
assert (1 <= e)%Z.
|
|
{ unfold le, Bcompare in h2; simpl SpecFloat.SFcompare in h2.
|
|
destruct s.
|
|
destruct h2 as [h2|h2]. 2: easy.
|
|
destruct (Z_lt_le_dec e 1%Z); auto.
|
|
rewrite Zcompare_Lt in h2; auto.
|
|
easy.
|
|
destruct h2 as [h2|h2]. easy.
|
|
destruct e; try easy.
|
|
pose proof (Pos2Z.is_pos p).
|
|
auto with zarith. }
|
|
|
|
rewrite <- IZR_Zpower by auto with zarith.
|
|
rewrite <- mult_IZR.
|
|
apply is_intR_IZR.
|
|
Qed.
|
|
|
|
Lemma max_value_to_int : forall m, to_int m max_value = max_int.
|
|
Proof.
|
|
intro m.
|
|
apply eq_IZR.
|
|
rewrite <-max_real_int, <-int_to_real_, max_value_to_real.
|
|
reflexivity.
|
|
unfold is_int.
|
|
|
|
apply max_value_is_int.
|
|
Qed.
|
|
|
|
Lemma neg_to_int_max_value : forall {m}, (- to_int m max_value)%Z = to_int m (neg max_value).
|
|
Proof.
|
|
intro m.
|
|
destruct (valid_rnd_round_mode m).
|
|
pose proof max_value_is_int as H.
|
|
pose proof (neg_is_int H).
|
|
apply eq_IZR.
|
|
rewrite Ropp_Ropp_IZR.
|
|
rewrite <-int_to_real_, <-int_to_real_ by auto.
|
|
now destruct (neg_finite max_value) as (_,h).
|
|
Qed.
|
|
|
|
Lemma is_finite_range_to_int : forall {x} m, (is_finite x) -> (in_range (IZR (to_int m x))).
|
|
Proof.
|
|
intros x m h1.
|
|
apply Rabs_le_inv.
|
|
rewrite Abs.Abs_le, max_real_int, <-opp_IZR, <-(max_value_to_int m), neg_to_int_max_value.
|
|
|
|
pose proof (bounded_floats_le _ h1).
|
|
pose proof (abs_le_inv H) as (H1,H2).
|
|
now split; apply IZR_le; apply to_int_le.
|
|
Qed.
|
|
|
|
Lemma is_finite_to_int: forall {x} (m1 m2:mode), is_finite x -> no_overflow m1 (IZR (to_int m2 x)).
|
|
Proof.
|
|
intros x m1 m2 h;
|
|
apply (Bounded_real_no_overflow m1 _ (is_finite_range_to_int m2 h)).
|
|
Qed.
|
|
|
|
Lemma is_finite_to_int2: forall {x} m, is_finite x -> (- max_int <= to_int m x <= max_int)%Z.
|
|
Proof.
|
|
intros x m h.
|
|
rewrite <-(@max_value_to_int m).
|
|
rewrite (@neg_to_int_max_value m).
|
|
pose proof (bounded_floats_le _ h).
|
|
apply abs_le_inv in H.
|
|
destruct H.
|
|
now split; apply to_int_le.
|
|
Qed.
|
|
|
|
Lemma roundToIntegral_finite: forall m {x}, is_finite x -> is_finite (roundToIntegral m x).
|
|
Proof.
|
|
intros m x h; destruct x; auto.
|
|
unfold roundToIntegral.
|
|
destruct Z.eq_dec; auto.
|
|
apply of_int_correct.
|
|
apply (is_finite_to_int RTZ m h).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma roundToIntegral_is_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
is_int (roundToIntegral m x).
|
|
Proof.
|
|
intros m x h1.
|
|
destruct x; try easy.
|
|
+ apply zeroF_is_int.
|
|
+ simpl.
|
|
destruct Z.eq_dec.
|
|
split;[apply h1|].
|
|
simpl; unfold is_intR.
|
|
now rewrite Zfloor_IZR.
|
|
change (is_int (of_int RTZ (to_int m (B754_finite s m0 e e0)))).
|
|
apply of_int_is_int.
|
|
apply is_finite_to_int2.
|
|
assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_is_int : forall (x:t) (y:t), eq x y -> is_int x -> is_int y.
|
|
Proof.
|
|
intros x y h1 (h2,h3).
|
|
unfold is_int.
|
|
split; [apply (eq_finite_dist h1); auto|].
|
|
unfold is_intR in *.
|
|
apply to_real_eq_alt in h1.
|
|
rewrite h1 in *; assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma add_int :
|
|
forall (x:t) (y:t) (m:ieee_float.RoundingMode.mode), is_int x ->
|
|
is_int y -> is_finite (add m x y) -> is_int (add m x y).
|
|
Proof.
|
|
intros x y m (h1,h1') (h2,h2') h3.
|
|
destruct (add_finite_rev_n' m x y h3).
|
|
+ destruct H.
|
|
unfold is_int.
|
|
split; auto.
|
|
rewrite H0.
|
|
apply is_intR_round.
|
|
apply is_intR_equiv.
|
|
exists (floor (to_real x) + floor (to_real y))%Z.
|
|
unfold is_intR in h1', h2'; rewrite h1', h2' at 1.
|
|
symmetry; apply plus_IZR.
|
|
+ split; auto.
|
|
rewrite max_real_int in H.
|
|
destruct H; apply is_intR_equiv.
|
|
exists max_int; assumption.
|
|
exists (- max_int)%Z.
|
|
now rewrite opp_IZR.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma sub_int :
|
|
forall (x:t) (y:t) (m:ieee_float.RoundingMode.mode), is_int x ->
|
|
is_int y -> is_finite (sub m x y) -> is_int (sub m x y).
|
|
Proof.
|
|
intros x y m (h1,h1') (h2,h2') h3.
|
|
destruct (sub_finite_rev_n' m x y h3).
|
|
+ destruct H.
|
|
unfold is_int.
|
|
split; auto.
|
|
rewrite H0.
|
|
apply is_intR_round.
|
|
apply is_intR_equiv.
|
|
exists (floor (to_real x) - floor (to_real y))%Z.
|
|
unfold is_intR in h1', h2'; rewrite h1', h2' at 1.
|
|
symmetry; apply minus_IZR.
|
|
+ split; auto.
|
|
rewrite max_real_int in H.
|
|
destruct H; apply is_intR_equiv.
|
|
exists max_int; assumption.
|
|
exists (- max_int)%Z.
|
|
now rewrite opp_IZR.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma mul_int :
|
|
forall (x:t) (y:t) (m:ieee_float.RoundingMode.mode), is_int x ->
|
|
is_int y -> is_finite (mul m x y) -> is_int (mul m x y).
|
|
Proof.
|
|
intros x y m (h1,h1') (h2,h2') h3.
|
|
destruct (mul_finite_rev_n' m x y h3).
|
|
+ destruct H.
|
|
unfold is_int.
|
|
split; auto.
|
|
rewrite H0.
|
|
apply is_intR_round.
|
|
apply is_intR_equiv.
|
|
exists (floor (to_real x) * floor (to_real y))%Z.
|
|
unfold is_intR in h1', h2'; rewrite h1', h2' at 1.
|
|
symmetry; apply mult_IZR.
|
|
+ split; auto.
|
|
rewrite max_real_int in H.
|
|
destruct H; apply is_intR_equiv.
|
|
exists max_int; assumption.
|
|
exists (- max_int)%Z.
|
|
now rewrite opp_IZR.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma fma_int :
|
|
forall (x:t) (y:t) (z:t) (m:ieee_float.RoundingMode.mode), is_int x ->
|
|
is_int y -> is_int z -> is_finite (fma m x y z) -> is_int (fma m x y z).
|
|
Proof.
|
|
intros x y z m (h1,h1') (h2,h2') (h3,h3') h4.
|
|
destruct (fma_finite_rev_n' m x y z h4).
|
|
+ destruct H.
|
|
unfold is_int.
|
|
split; auto.
|
|
rewrite H0.
|
|
apply is_intR_round.
|
|
apply is_intR_equiv.
|
|
exists (floor (to_real x) * floor (to_real y) + floor (to_real z))%Z.
|
|
unfold is_intR in h1', h2', h3'; rewrite h1', h2', h3' at 1.
|
|
rewrite plus_IZR, mult_IZR; reflexivity.
|
|
+ split; auto.
|
|
rewrite max_real_int in H.
|
|
destruct H; apply is_intR_equiv.
|
|
exists max_int; assumption.
|
|
exists (- max_int)%Z.
|
|
rewrite opp_IZR; assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma neg_int : forall (x:t), is_int x -> is_int (neg x).
|
|
Proof.
|
|
intros x (h1,h2).
|
|
destruct (neg_finite x h1).
|
|
split; try easy.
|
|
unfold is_intR in *.
|
|
rewrite H0.
|
|
rewrite h2 at 2.
|
|
rewrite <- opp_IZR, Zfloor_IZR, opp_IZR.
|
|
apply f_equal, h2.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma abs_int : forall (x:t), is_int x -> is_int (abs x).
|
|
Proof.
|
|
intros x (h1,h2).
|
|
destruct (abs_finite x h1) as (h3,(h4,h5)).
|
|
split; try easy.
|
|
unfold is_intR in *.
|
|
rewrite h4.
|
|
rewrite h2 at 2.
|
|
rewrite <- abs_IZR, Zfloor_IZR, abs_IZR.
|
|
apply f_equal, h2.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_int_of_int :
|
|
forall (x:t) (m:ieee_float.RoundingMode.mode)
|
|
(m':ieee_float.RoundingMode.mode),
|
|
is_int x -> eq x (of_int m' (to_int m x)).
|
|
Proof.
|
|
intros x m m' h1.
|
|
assert (h1':=h1).
|
|
destruct h1 as (h1,h2).
|
|
assert (no_overflow m' (IZR (to_int m x))) by
|
|
(apply is_finite_to_int; auto).
|
|
destruct (of_int_correct H) as (h3,(h4,h5)); auto.
|
|
rewrite to_real_eq; auto.
|
|
rewrite h3, <-int_to_real_; auto.
|
|
symmetry; apply Round_to_real; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_int_to_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_int x ->
|
|
in_int_range (to_int m x).
|
|
Proof.
|
|
intros m x h1.
|
|
pose proof (@int_to_real_ m x h1).
|
|
unfold in_int_range.
|
|
destruct h1.
|
|
apply is_finite1 in H0.
|
|
unfold in_range in H0.
|
|
destruct H0.
|
|
split; apply le_IZR; try rewrite FromInt.Neg; rewrite <-max_real_int, <-H; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma is_int_is_finite : forall (x:t), is_int x -> is_finite x.
|
|
Proof.
|
|
intros x (h,_); assumption.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma int_to_real :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_int x ->
|
|
((to_real x) = (BuiltIn.IZR (to_int m x))).
|
|
Proof.
|
|
intros m x.
|
|
apply int_to_real_.
|
|
Qed.
|
|
|
|
Lemma of_int_to_real : forall (m:mode) (x:Z), (no_overflow m
|
|
(BuiltIn.IZR x)) -> ((to_real (of_int m x)) = (round m
|
|
(BuiltIn.IZR x))).
|
|
Proof.
|
|
intros m x h1.
|
|
apply (of_int_correct h1).
|
|
Qed.
|
|
|
|
(* TODO: add to theory ? *)
|
|
Lemma to_real_roundToIntegral: forall {x} m, is_finite x -> to_real (roundToIntegral m x) = IZR (to_int m x).
|
|
Proof.
|
|
intros x m h.
|
|
unfold roundToIntegral.
|
|
destruct Z.eq_dec.
|
|
|
|
destruct x; try easy.
|
|
rewrite B754_zero_to_real, e; auto.
|
|
rewrite B754_zero_to_real, e; auto.
|
|
|
|
destruct x; try easy.
|
|
contradict n.
|
|
apply to_int_B754_zero.
|
|
|
|
set (x:= B754_finite s m0 e e0); fold x in h, h.
|
|
change (to_real (of_int RTZ (to_int m x)) = IZR (to_int m x)).
|
|
|
|
assert (is_finite Bmax_rep_int) by auto.
|
|
destruct (neg_finite _ H) as (H0,_).
|
|
|
|
assert (((le (neg Bmax_rep_int) x) /\ (le x Bmax_rep_int))
|
|
\/ ((le x (neg Bmax_rep_int)) \/ (le Bmax_rep_int x))) as h1.
|
|
destruct (le_or_lt_or_nan x Bmax_rep_int) as [h1|[h1|[h1|h1]]].
|
|
+ destruct (le_or_lt_or_nan (neg Bmax_rep_int) x) as [h2|[h2|[h2|h2]]].
|
|
- left; split; easy.
|
|
- right; left; apply lt_le; auto.
|
|
- destruct (neg Bmax_rep_int); easy.
|
|
- destruct x; easy.
|
|
+ right; right; apply lt_le; auto.
|
|
+ destruct x; easy.
|
|
+ destruct Bmax_rep_int; easy.
|
|
|
|
+ destruct h1.
|
|
- destruct H1.
|
|
apply (@to_int_le _ _ m H0 h) in H1.
|
|
apply (@to_int_le _ _ m h H) in H2.
|
|
rewrite (neg_int_to_int Bmax_rep_int_is_int) in H1.
|
|
rewrite Bmax_rep_int_to_int in H1, H2.
|
|
rewrite of_int_to_real.
|
|
rewrite Exact_rounding_for_integers; auto.
|
|
unfold in_safe_int_range; auto.
|
|
apply Bounded_real_no_overflow.
|
|
apply rep_int_in_range; auto.
|
|
- rewrite (@Bmax_rep_int_of_int m) in H1.
|
|
pose proof (big_float_is_int m _ h H1).
|
|
rewrite of_int_to_real.
|
|
rewrite <-int_to_real; auto.
|
|
rewrite Round_to_real; auto.
|
|
apply Bounded_real_no_overflow.
|
|
apply is_finite_range_to_int; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma truncate_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (i:t), is_int i ->
|
|
eq (roundToIntegral m i) i.
|
|
Proof.
|
|
intros m i (h1,h2).
|
|
pose proof (roundToIntegral_finite m h1).
|
|
rewrite eq_to_real_finite; auto.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
symmetry.
|
|
apply int_to_real; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma truncate_neg :
|
|
forall (x:t), is_finite x -> is_negative x ->
|
|
((roundToIntegral ieee_float.RoundingMode.RTZ x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x)).
|
|
Proof.
|
|
intros x h1 h2.
|
|
destruct x; try easy.
|
|
simpl roundToIntegral.
|
|
pose proof (negative_to_real _ h1 h2).
|
|
pose proof (Ztrunc_ceil _ H).
|
|
simpl in H0.
|
|
rewrite H0.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma truncate_pos :
|
|
forall (x:t), is_finite x -> is_positive x ->
|
|
((roundToIntegral ieee_float.RoundingMode.RTZ x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x)).
|
|
Proof.
|
|
intros x h1 h2.
|
|
destruct x; try easy.
|
|
simpl roundToIntegral.
|
|
pose proof (positive_to_real _ h1 h2).
|
|
pose proof (Ztrunc_floor _ H).
|
|
simpl in H0.
|
|
rewrite H0.
|
|
reflexivity.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma ceil_le :
|
|
forall (x:t), is_finite x ->
|
|
le x (roundToIntegral ieee_float.RoundingMode.RTP x).
|
|
Proof.
|
|
intros x h1.
|
|
pose proof (roundToIntegral_finite RTP h1).
|
|
rewrite le_to_real; auto.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
simpl.
|
|
apply Zceil_ub.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma ceil_lest :
|
|
forall (x:t) (y:t), le x y /\ is_int y ->
|
|
le (roundToIntegral ieee_float.RoundingMode.RTP x) y.
|
|
Proof.
|
|
intros x y (h1,h2).
|
|
destruct (le_special _ _ h1) as [h|[h|h]]; try easy.
|
|
- destruct h.
|
|
pose proof (roundToIntegral_finite RTP H).
|
|
rewrite le_to_real; auto.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
simpl.
|
|
rewrite (int_to_real RTP _ h2).
|
|
apply IZR_le, Zceil_glb.
|
|
rewrite <- (int_to_real RTP _ h2).
|
|
apply le_to_real; auto.
|
|
- destruct h as (h,_).
|
|
unfold is_minus_infinity in h.
|
|
destruct x; easy.
|
|
- unfold is_plus_infinity in h.
|
|
destruct h, h2, y; try easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma ceil_to_real :
|
|
forall (x:t), is_finite x ->
|
|
((to_real (roundToIntegral ieee_float.RoundingMode.RTP x)) =
|
|
(BuiltIn.IZR (real.Truncate.ceil (to_real x)))).
|
|
Proof.
|
|
intros x h.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma ceil_to_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
((to_int m (roundToIntegral ieee_float.RoundingMode.RTP x)) =
|
|
(real.Truncate.ceil (to_real x))).
|
|
Proof.
|
|
intros m x h.
|
|
unfold to_int.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
destruct (valid_rnd_round_mode m) as (_,h').
|
|
destruct m; apply (h' (to_int RTP x)).
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma floor_le :
|
|
forall (x:t), is_finite x ->
|
|
le (roundToIntegral ieee_float.RoundingMode.RTN x) x.
|
|
Proof.
|
|
intros x h1.
|
|
pose proof (roundToIntegral_finite RTN h1).
|
|
rewrite le_to_real; auto.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
simpl.
|
|
apply Zfloor_lb.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma floor_lest :
|
|
forall (x:t) (y:t), le y x /\ is_int y ->
|
|
le y (roundToIntegral ieee_float.RoundingMode.RTN x).
|
|
Proof.
|
|
intros x y (h1,h2).
|
|
destruct (le_special _ _ h1) as [h|[h|h]]; try easy.
|
|
- destruct h.
|
|
pose proof (roundToIntegral_finite RTN H0).
|
|
rewrite le_to_real; auto.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
simpl.
|
|
rewrite (int_to_real RTN _ h2).
|
|
apply IZR_le, Zfloor_lub.
|
|
rewrite <- (int_to_real RTN _ h2).
|
|
apply le_to_real; auto.
|
|
- destruct h2 as (h2,_).
|
|
unfold is_minus_infinity in h.
|
|
destruct y; easy.
|
|
- unfold is_plus_infinity in h.
|
|
destruct h; destruct H; destruct H0, h2, x; try easy.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma floor_to_real :
|
|
forall (x:t), is_finite x ->
|
|
((to_real (roundToIntegral ieee_float.RoundingMode.RTN x)) =
|
|
(BuiltIn.IZR (real.Truncate.floor (to_real x)))).
|
|
Proof.
|
|
intros x h.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma floor_to_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
((to_int m (roundToIntegral ieee_float.RoundingMode.RTN x)) =
|
|
(real.Truncate.floor (to_real x))).
|
|
Proof.
|
|
intros m x h.
|
|
unfold to_int.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
destruct (valid_rnd_round_mode m) as (_,h').
|
|
destruct m; apply (h' (to_int RTN x)).
|
|
Qed.
|
|
|
|
Lemma same_sign_roundToIntegral:
|
|
forall {x} (m:mode), ~ is_nan x -> same_sign (roundToIntegral m x) x.
|
|
Proof.
|
|
intros x m h.
|
|
unfold same_sign.
|
|
destruct x; try (now elim h); try (destruct s; simpl; now auto); clear h.
|
|
set (x:=B754_finite s m0 e e0).
|
|
assert (no_overflow RTZ (IZR (to_int m x))) by
|
|
now apply is_finite_to_int.
|
|
destruct (of_int_correct H) as (_,(_,h1)); clear H.
|
|
assert (is_finite x) as h2 by easy.
|
|
pose proof (roundToIntegral_finite m h2).
|
|
destruct s; simpl;[right|left];split;auto.
|
|
+ apply is_negative_Bsign; auto.
|
|
change (~ is_nan (roundToIntegral m x)); destruct (roundToIntegral m x); easy.
|
|
assert (to_int m x <= 0)%Z.
|
|
apply is_negative_to_int; easy.
|
|
destruct (Z_le_lt_eq_dec _ _ H0).
|
|
- rewrite Zcompare_Lt in h1 by auto.
|
|
destruct Z.eq_dec; auto.
|
|
- destruct Z.eq_dec; auto.
|
|
+ apply is_positive_Bsign; auto.
|
|
change (~ is_nan (roundToIntegral m x)); destruct (roundToIntegral m x); easy.
|
|
assert (0 <= to_int m x)%Z.
|
|
apply is_positive_to_int; easy.
|
|
destruct (Z_le_lt_eq_dec _ _ H0).
|
|
- rewrite Zcompare_Gt in h1 by auto.
|
|
destruct Z.eq_dec; auto.
|
|
- symmetry in e1.
|
|
destruct Z.eq_dec; easy.
|
|
Qed.
|
|
|
|
Lemma same_sign_roundToIntegral2:
|
|
forall {x} {m m':mode}, ~ is_nan x -> same_sign (roundToIntegral m x) (roundToIntegral m' x).
|
|
Proof.
|
|
intros x m m' h.
|
|
pose proof (same_sign_roundToIntegral m h).
|
|
pose proof (same_sign_roundToIntegral m' h).
|
|
unfold same_sign in *.
|
|
pose proof (negative_xor_positive x).
|
|
destruct H as [(H,H')|(H,H')], H0 as [(H0,H0')|(H0,H0')]; auto.
|
|
contradict H1; auto.
|
|
contradict H1; auto.
|
|
Qed.
|
|
|
|
Lemma no_overflow_to_real_min_RTN:
|
|
forall x, is_finite x -> no_overflow RNE (to_real x - to_real (roundToIntegral RTN x)).
|
|
Proof.
|
|
intros x h.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
unfold to_int.
|
|
apply Bounded_real_no_overflow.
|
|
pose proof (Zfloor_ub (to_real x)).
|
|
pose proof (Zfloor_lb (to_real x)).
|
|
unfold in_range.
|
|
pose proof max_real_ge_6.
|
|
fold (to_real x).
|
|
split; lra.
|
|
Qed.
|
|
|
|
Lemma ceil_lb: forall x, ((IZR (ceil x) - 1) < x).
|
|
Proof.
|
|
intro.
|
|
case (Req_dec (IZR (Zfloor x)) x); intro.
|
|
rewrite <-H, Zceil_IZR, H; simpl; lra.
|
|
rewrite (Zceil_floor_neq _ H).
|
|
rewrite plus_IZR; simpl.
|
|
pose proof (Zfloor_lb x).
|
|
destruct (Rle_lt_or_eq_dec _ _ H0); try easy.
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma no_overflow_to_real_RTP_min:
|
|
forall x, is_finite x -> no_overflow RNE (to_real (roundToIntegral RTP x) - to_real x).
|
|
Proof.
|
|
intros x h.
|
|
rewrite to_real_roundToIntegral; auto.
|
|
unfold to_int.
|
|
apply Bounded_real_no_overflow.
|
|
pose proof (Zceil_ub (to_real x)).
|
|
pose proof (ceil_lb (to_real x)).
|
|
unfold in_range.
|
|
pose proof max_real_ge_6.
|
|
fold (to_real x).
|
|
split; lra.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma RNA_down :
|
|
forall (x:t),
|
|
lt
|
|
(sub ieee_float.RoundingMode.RNE x
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x))
|
|
(sub ieee_float.RoundingMode.RNE
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x) x) ->
|
|
((roundToIntegral ieee_float.RoundingMode.RNA x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x)).
|
|
Proof.
|
|
intros x h.
|
|
destruct x; try easy.
|
|
set (x:=(B754_finite s m e e0)); fold x in h.
|
|
assert (forall m', is_finite (roundToIntegral m' x)) as h1.
|
|
intro m'.
|
|
apply roundToIntegral_finite; try easy.
|
|
apply to_real_refl; try easy.
|
|
2: apply same_sign_roundToIntegral2; easy.
|
|
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral; try easy.
|
|
f_equal.
|
|
unfold to_int.
|
|
apply Znearest_imp.
|
|
rewrite Rabs_pos_eq.
|
|
2: pose proof (Zfloor_lb (to_real x)); fold (to_real x); lra.
|
|
|
|
assert (is_finite x) as x_fin by easy.
|
|
pose proof (no_overflow_to_real_min_RTN _ x_fin) as h2.
|
|
pose proof (no_overflow_to_real_RTP_min _ x_fin) as h3.
|
|
|
|
assert (is_finite (roundToIntegral RTN x)) as rtn_fin by auto.
|
|
assert (is_finite (roundToIntegral RTP x)) as rtp_fin by auto.
|
|
destruct (sub_finite _ _ _ x_fin rtn_fin h2) as (h4,h4').
|
|
destruct (sub_finite _ _ _ rtp_fin x_fin h3) as (h5,h5').
|
|
clear x_fin h2 h3 rtn_fin rtp_fin.
|
|
|
|
rewrite lt_finite in h; auto.
|
|
rewrite h4' in h; auto.
|
|
rewrite h5' in h; auto.
|
|
|
|
fold (to_real x).
|
|
case (Req_dec (IZR (Zfloor (to_real x))) (to_real x)); intro.
|
|
lra.
|
|
|
|
apply round_lt in h.
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral in h; try easy.
|
|
unfold to_int in h.
|
|
rewrite Zceil_floor_neq, plus_IZR in h; auto.
|
|
fold (to_real x) in h.
|
|
lra.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma RNA_up :
|
|
forall (x:t),
|
|
lt
|
|
(sub ieee_float.RoundingMode.RNE
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x) x)
|
|
(sub ieee_float.RoundingMode.RNE x
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x)) ->
|
|
((roundToIntegral ieee_float.RoundingMode.RNA x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x)).
|
|
Proof.
|
|
intros x h.
|
|
destruct x; try easy.
|
|
set (x:=(B754_finite s m e e0)); fold x in h.
|
|
assert (forall m', is_finite (roundToIntegral m' x)) as h1.
|
|
intro m'.
|
|
apply roundToIntegral_finite; try easy.
|
|
apply to_real_refl; try easy.
|
|
2: apply same_sign_roundToIntegral2; easy.
|
|
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral; try easy.
|
|
f_equal.
|
|
unfold to_int.
|
|
apply Znearest_imp.
|
|
rewrite Rabs_left1.
|
|
2: pose proof (Zceil_ub (to_real x)); fold (to_real x); lra.
|
|
rewrite Ropp_minus_distr.
|
|
|
|
assert (is_finite x) as x_fin by easy.
|
|
pose proof (no_overflow_to_real_min_RTN _ x_fin) as h2.
|
|
pose proof (no_overflow_to_real_RTP_min _ x_fin) as h3.
|
|
|
|
assert (is_finite (roundToIntegral RTN x)) as rtn_fin by auto.
|
|
assert (is_finite (roundToIntegral RTP x)) as rtp_fin by auto.
|
|
destruct (sub_finite _ _ _ x_fin rtn_fin h2) as (h4,h4').
|
|
destruct (sub_finite _ _ _ rtp_fin x_fin h3) as (h5,h5').
|
|
clear x_fin h2 h3 rtn_fin rtp_fin.
|
|
|
|
rewrite lt_finite in h; auto.
|
|
rewrite h4' in h; auto.
|
|
rewrite h5' in h; auto.
|
|
|
|
fold (to_real x).
|
|
case (Req_dec (IZR (Zceil (to_real x))) (to_real x)); intro.
|
|
lra.
|
|
|
|
apply round_lt in h.
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral in h; try easy.
|
|
unfold to_int in h.
|
|
assert (IZR (floor (to_real x)) <> to_real x).
|
|
intro.
|
|
rewrite <-H0 in H.
|
|
rewrite Zceil_IZR in H.
|
|
auto.
|
|
|
|
rewrite Zceil_floor_neq, plus_IZR in h; auto.
|
|
rewrite Zceil_floor_neq, plus_IZR; auto.
|
|
fold (to_real x) in h; lra.
|
|
Qed.
|
|
|
|
Lemma sterbenz_round: forall x y m,
|
|
to_real y / 2 <= to_real x <= 2 * to_real y ->
|
|
round m (to_real x - to_real y) = to_real x - to_real y.
|
|
Proof.
|
|
intros x y m h.
|
|
assert (generic_format radix2 fexp (to_real x - to_real y)).
|
|
{ apply Sterbenz.sterbenz.
|
|
apply fexp_Valid.
|
|
apply fexp_monotone.
|
|
apply generic_format_B2R.
|
|
apply generic_format_B2R.
|
|
exact h. }
|
|
apply round_generic; auto.
|
|
apply valid_rnd_round_mode.
|
|
Qed.
|
|
|
|
Lemma sterbenz_round_opp: forall x y m,
|
|
to_real y / 2 <= to_real x <= 2 * to_real y ->
|
|
round m (to_real y - to_real x) = to_real y - to_real x.
|
|
Proof.
|
|
intros x y m h.
|
|
assert (generic_format radix2 fexp (to_real y - to_real x)).
|
|
{ replace (to_real y - to_real x) with (- (to_real x - to_real y)) by ring.
|
|
apply generic_format_opp.
|
|
apply Sterbenz.sterbenz.
|
|
apply fexp_Valid.
|
|
apply fexp_monotone.
|
|
apply generic_format_B2R.
|
|
apply generic_format_B2R.
|
|
exact h. }
|
|
apply round_generic; auto.
|
|
apply valid_rnd_round_mode.
|
|
Qed.
|
|
|
|
Lemma sterbenz_round_2: forall x y m, is_finite y -> is_finite x ->
|
|
2 * to_real y <= to_real x <= to_real y / 2 ->
|
|
round m (to_real x - to_real y) = to_real x - to_real y.
|
|
Proof.
|
|
intros x y m h h' h2.
|
|
replace (to_real x - to_real y) with (-to_real y - (- to_real x)) by field.
|
|
destruct (neg_finite _ h) as (_,h1); rewrite <-h1;
|
|
destruct (neg_finite _ h') as (_,h1'); rewrite <-h1'.
|
|
apply sterbenz_round_opp.
|
|
rewrite h1, h1'.
|
|
destruct h2.
|
|
assert (forall x, -x = -1*x) as h2 by (intro; ring).
|
|
split.
|
|
- rewrite h2, (h2 (to_real x)).
|
|
rewrite Real.assoc_mul_div by (apply Rgt_not_eq; lra).
|
|
apply Rmult_le_compat_neg_l; lra.
|
|
- rewrite h2, (h2 (to_real y)).
|
|
replace (2 * (-1 * to_real y)) with (-1 * (2 * to_real y)) by field.
|
|
apply Rmult_le_compat_neg_l; lra.
|
|
Qed.
|
|
|
|
Lemma RTN_not_far: forall x,
|
|
is_finite x -> 1 <= to_real x ->
|
|
to_real (roundToIntegral RTN x) / 2 <= to_real x <= 2 * to_real (roundToIntegral RTN x).
|
|
Proof.
|
|
intros x h h1.
|
|
rewrite floor_to_real; auto.
|
|
pose proof (Zfloor_lb (to_real x));
|
|
pose proof (Zfloor_ub (to_real x)).
|
|
split. lra.
|
|
apply Rlt_le.
|
|
apply Rlt_le_trans with (r2 := IZR (floor (to_real x)) + 1); auto.
|
|
assert (1 <= IZR (floor (to_real x))).
|
|
{ pose proof (Rle_lt_trans _ _ _ h1 H0).
|
|
rewrite <- plus_IZR in H1.
|
|
apply lt_IZR in H1.
|
|
apply IZR_le.
|
|
auto with zarith. }
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma RTN_not_far_opp: forall x,
|
|
is_finite x -> to_real x <= -/2 ->
|
|
2 * to_real (roundToIntegral RTN x) <= to_real x <= to_real (roundToIntegral RTN x) / 2.
|
|
Proof.
|
|
intros x h h1.
|
|
rewrite floor_to_real; auto.
|
|
pose proof (Zfloor_lb (to_real x));
|
|
pose proof (Zfloor_ub (to_real x)).
|
|
split. lra.
|
|
destruct (Rle_lt_dec (to_real x) (-1)). lra.
|
|
assert (IZR (floor (to_real x)) = -1).
|
|
{ assert (IZR (floor(to_real x)) < 0) by lra.
|
|
assert (-2 < IZR (floor (to_real x))) by lra.
|
|
apply lt_IZR in H1; apply lt_IZR in H2.
|
|
now replace (floor (to_real x)) with (-1)%Z by lia. }
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma RTP_not_far: forall x,
|
|
is_finite x -> /2 <= to_real x ->
|
|
to_real x / 2 <= to_real (roundToIntegral RTP x) <= 2 * to_real x.
|
|
Proof.
|
|
intros x h h1.
|
|
rewrite ceil_to_real; auto.
|
|
pose proof (ceil_lb (to_real x));
|
|
pose proof (Zceil_ub (to_real x)).
|
|
split. lra.
|
|
destruct (Rle_lt_dec 1 (to_real x) ); try lra.
|
|
assert (IZR (ceil (to_real x)) = 1).
|
|
{ assert (0 < IZR (ceil( to_real x))) by lra.
|
|
assert (IZR (ceil(to_real x)) < 2) by lra.
|
|
apply lt_IZR in H1; apply lt_IZR in H2.
|
|
now replace (ceil (to_real x)) with 1%Z by lia. }
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma RTP_not_far_opp: forall x,
|
|
is_finite x -> to_real x <= -1 ->
|
|
2 * to_real x <= to_real (roundToIntegral RTP x) <= to_real x / 2.
|
|
Proof.
|
|
intros x h h1.
|
|
rewrite ceil_to_real; auto.
|
|
pose proof (ceil_lb (to_real x));
|
|
pose proof (Zceil_ub (to_real x)).
|
|
split. lra.
|
|
apply Rmult_le_reg_r with (r:=2); try lra.
|
|
replace (to_real x / 2 * 2) with (to_real x) by field.
|
|
apply Rlt_le.
|
|
apply Rle_lt_trans with (r2 := IZR (ceil (to_real x)) - 1); auto.
|
|
assert (IZR (ceil (to_real x)) <= -1).
|
|
{ pose proof (Rlt_le_trans _ _ _ H h1).
|
|
rewrite <- (minus_IZR _ 1) in H1.
|
|
apply (lt_IZR _ (-1)) in H1.
|
|
apply (IZR_le _ (-1)).
|
|
auto with zarith. }
|
|
lra.
|
|
Qed.
|
|
|
|
Lemma round_plus_weak: forall x y m,
|
|
Rabs (to_real x + to_real y) <= Rmin (Rabs (to_real x)) (Rabs (to_real y)) ->
|
|
round m (to_real x + to_real y) = to_real x + to_real y.
|
|
Proof.
|
|
intros x y m h.
|
|
assert (generic_format radix2 fexp (to_real x + to_real y)).
|
|
{ apply Sterbenz.generic_format_plus_weak.
|
|
apply fexp_Valid.
|
|
apply fexp_monotone.
|
|
apply generic_format_B2R.
|
|
apply generic_format_B2R.
|
|
exact h. }
|
|
apply round_generic; auto.
|
|
apply valid_rnd_round_mode.
|
|
Qed.
|
|
|
|
Lemma half_bounded: SpecFloat.bounded sb emax (shift_pos (sb_pos - 1) 1) (- sb) = true.
|
|
Proof.
|
|
unfold SpecFloat.bounded.
|
|
apply Bool.andb_true_iff; split.
|
|
unfold SpecFloat.canonical_mantissa.
|
|
apply Zeq_bool_true.
|
|
rewrite Digits.Zpos_digits2_pos, shift_pos_correct.
|
|
rewrite Zmult_1_r, Z.pow_pos_fold.
|
|
rewrite Digits.Zdigits_Zpower by easy.
|
|
rewrite Pos2Z.inj_sub by exact sb_gt_1.
|
|
fold sb.
|
|
unfold SpecFloat.fexp, FLT_exp, SpecFloat.emin.
|
|
replace (sb - 1 + 1 + - sb)%Z with 0%Z by ring.
|
|
apply Z.max_l.
|
|
pose sb_gt_1; pose Hemax'; lia.
|
|
apply Zle_bool_true.
|
|
pose Hemax'; pose sb_gt_1; lia.
|
|
Qed.
|
|
|
|
Definition half: t.
|
|
Proof.
|
|
exact (B754_finite false _ _ half_bounded).
|
|
Defined.
|
|
|
|
Lemma half_to_real : ((to_real half) = (05 / 10)%R).
|
|
Proof.
|
|
unfold B2R, half; simpl.
|
|
rewrite shift_pos_correct.
|
|
rewrite Z.pow_pos_fold.
|
|
unfold F2R.
|
|
unfold Fnum, Fexp.
|
|
rewrite Zmult_1_r.
|
|
change 2%Z with (radix_val radix2).
|
|
rewrite IZR_Zpower by easy.
|
|
rewrite <-bpow_plus.
|
|
rewrite Pos2Z.inj_sub by exact sb_gt_1.
|
|
rewrite <-Pos2Z.opp_pos.
|
|
replace (Z.pos sb_pos - 1 + - Z.pos sb_pos)%Z with (- 1)%Z by ring.
|
|
unfold bpow.
|
|
change (Z.pow_pos radix2 1)%Z with 2%Z.
|
|
field.
|
|
Qed.
|
|
|
|
Lemma eq_diff_floor_ceil: forall {x}, eq (sub RNE x (roundToIntegral RTN x)) (sub RNE (roundToIntegral RTP x) x) -> to_real x - IZR (floor (to_real x)) = IZR (ceil (to_real x)) - to_real x.
|
|
Proof.
|
|
intros x h.
|
|
destruct x; try easy.
|
|
- rewrite B754_zero_to_real.
|
|
rewrite Zfloor_IZR, Zceil_IZR; auto.
|
|
- simpl.
|
|
rewrite Zfloor_IZR, Zceil_IZR; auto.
|
|
- set (x:=(B754_finite s m e e0)); fold x in h.
|
|
assert (forall m', is_finite (roundToIntegral m' x)) as h1 by
|
|
(intro m'; apply roundToIntegral_finite; easy).
|
|
|
|
assert (is_finite x) as x_fin by easy.
|
|
pose proof (no_overflow_to_real_min_RTN _ x_fin) as h2.
|
|
pose proof (no_overflow_to_real_RTP_min _ x_fin) as h3.
|
|
|
|
assert (is_finite (roundToIntegral RTN x)) as rtn_fin by auto.
|
|
assert (is_finite (roundToIntegral RTP x)) as rtp_fin by auto.
|
|
destruct (sub_finite _ _ _ x_fin rtn_fin h2) as (h4,h4').
|
|
destruct (sub_finite _ _ _ rtp_fin x_fin h3) as (h5,h5').
|
|
clear h2 h3 rtn_fin rtp_fin.
|
|
|
|
assert (h':=h).
|
|
rewrite to_real_eq in h; auto.
|
|
rewrite h4' in h; auto.
|
|
rewrite h5' in h; auto.
|
|
clear h4' h5'.
|
|
|
|
destruct (Rle_lt_dec 1 (to_real x));[|destruct (Rle_lt_dec (to_real x) (-1))].
|
|
|
|
+ destruct (RTN_not_far x); auto.
|
|
destruct (RTP_not_far x); auto; try lra.
|
|
rewrite sterbenz_round, sterbenz_round in h by auto.
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral in h; auto.
|
|
|
|
+ destruct (RTN_not_far_opp x); auto; try lra.
|
|
destruct (RTP_not_far_opp x); auto.
|
|
rewrite sterbenz_round_2, sterbenz_round_2 in h by auto.
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral in h; auto.
|
|
|
|
+ destruct (Rle_lt_dec (to_real x) 0).
|
|
destruct r1.
|
|
* assert (floor (to_real x) = (-1)%Z).
|
|
(apply Zfloor_imp; simpl IZR; split; lra).
|
|
assert (ceil (to_real x) = 0%Z) by
|
|
(apply Zceil_imp; simpl IZR; split; lra).
|
|
|
|
revert h.
|
|
rewrite (to_real_roundToIntegral RTP) by easy.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H1.
|
|
rewrite Rminus_0_l.
|
|
rewrite <-(proj2 (neg_finite _ x_fin)).
|
|
rewrite (Round_to_real RNE) by easy.
|
|
rewrite (proj2 (neg_finite _ x_fin)).
|
|
|
|
{ destruct (Rle_lt_dec (to_real x) (-/2)).
|
|
- assert (
|
|
round RNE (to_real x - to_real (roundToIntegral RTN x)) =
|
|
to_real x - to_real (roundToIntegral RTN x)) as aux1.
|
|
{ rewrite Real.infix_mn'def, <-(proj2 (neg_finite _ (h1 RTN))).
|
|
apply round_plus_weak.
|
|
rewrite (proj2 (neg_finite _ (h1 RTN))).
|
|
rewrite to_real_roundToIntegral; auto.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H0.
|
|
rewrite <- opp_IZR; simpl IZR.
|
|
rewrite Rabs_pos_eq, Rabs_left, Rabs_pos_eq, Rmin_left ; lra. }
|
|
rewrite aux1.
|
|
now rewrite to_real_roundToIntegral.
|
|
|
|
- clear r r0.
|
|
rewrite to_real_roundToIntegral by easy.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H0.
|
|
replace (to_real x - -1) with (to_real x+1) by ring.
|
|
pose proof (Rplus_lt_compat_r 1 _ _ r1).
|
|
apply Rlt_le in H2.
|
|
replace (-/2+1) with (5/10) in H2 by field.
|
|
rewrite <-half_to_real in H2.
|
|
apply (Round_monotonic RNE) in H2.
|
|
rewrite Round_to_real in H2 by easy.
|
|
rewrite half_to_real in H2.
|
|
intros.
|
|
lra. }
|
|
* assert (floor (to_real x) = 0%Z) by
|
|
(apply Zfloor_imp; simpl IZR; split; lra).
|
|
assert (ceil (to_real x) = 0%Z) by
|
|
(apply Zceil_imp; simpl IZR; split; lra).
|
|
rewrite H0, H1, H; auto.
|
|
|
|
* assert (floor (to_real x) = 0%Z) by
|
|
(apply Zfloor_imp; simpl IZR; split; lra).
|
|
assert (ceil (to_real x) = 1%Z) by
|
|
(apply Zceil_imp; simpl IZR; split; lra).
|
|
|
|
revert h.
|
|
rewrite (to_real_roundToIntegral RTN) by easy.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H.
|
|
replace (to_real x - 0) with (to_real x) by (simpl IZR ; ring).
|
|
rewrite (Round_to_real RNE) by easy.
|
|
|
|
{ destruct (Rle_lt_dec (/2) (to_real x)).
|
|
- assert (
|
|
round RNE (to_real (roundToIntegral RTP x) - to_real x) =
|
|
to_real (roundToIntegral RTP x) - to_real x) as aux1.
|
|
{ rewrite Real.infix_mn'def, <-(proj2 (neg_finite _ x_fin)).
|
|
apply round_plus_weak.
|
|
rewrite (proj2 (neg_finite _ x_fin)).
|
|
rewrite to_real_roundToIntegral by easy.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H0.
|
|
rewrite Rabs_pos_eq, Rabs_pos_eq, Rabs_left, Rmin_right; lra. }
|
|
rewrite aux1.
|
|
now rewrite to_real_roundToIntegral.
|
|
|
|
- clear r r0.
|
|
rewrite to_real_roundToIntegral by easy.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
rewrite H0.
|
|
pose proof (Ropp_lt_contravar _ _ r2).
|
|
pose proof (Rplus_lt_compat_l 1 _ _ H1).
|
|
apply Rlt_le in H2.
|
|
replace (1+-/2) with (5/10) in H2 by field.
|
|
rewrite <-half_to_real in H2.
|
|
rewrite <-Real.infix_mn'def in H2.
|
|
apply (Round_monotonic RNE) in H2.
|
|
rewrite Round_to_real in H2 by easy.
|
|
rewrite half_to_real in H2.
|
|
intros.
|
|
lra. }
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma RNA_down_tie :
|
|
forall (x:t),
|
|
eq
|
|
(sub ieee_float.RoundingMode.RNE x
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x))
|
|
(sub ieee_float.RoundingMode.RNE
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x) x) ->
|
|
is_negative x ->
|
|
((roundToIntegral ieee_float.RoundingMode.RNA x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x)).
|
|
Proof.
|
|
intros x h h'.
|
|
destruct x; try easy.
|
|
set (x:=(B754_finite s m e e0)); fold x in h, h'.
|
|
assert (forall m', is_finite (roundToIntegral m' x)) as h1 by
|
|
(intro m'; apply roundToIntegral_finite; easy).
|
|
apply to_real_refl; auto.
|
|
2: apply same_sign_roundToIntegral2; easy.
|
|
apply eq_diff_floor_ceil in h.
|
|
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral; try easy.
|
|
f_equal.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
|
|
destruct (is_int_or_not x).
|
|
rewrite (int_to_real RTZ _ H).
|
|
destruct (valid_rnd_round_mode RNA) as (_,H').
|
|
simpl in H'.
|
|
rewrite H', Zfloor_IZR; reflexivity.
|
|
|
|
unfold Znearest.
|
|
rewrite Rcompare_Eq.
|
|
rewrite Zle_bool_false; auto.
|
|
apply lt_IZR.
|
|
apply Rle_lt_trans with (r2:=to_real x).
|
|
apply Zfloor_lb.
|
|
rewrite <-zeroF_to_real.
|
|
apply lt_finite; try easy.
|
|
rewrite is_negative_correct in h'.
|
|
destruct h'; easy.
|
|
|
|
rewrite Zceil_floor_neq in h.
|
|
rewrite plus_IZR in h.
|
|
lra.
|
|
|
|
unfold is_int in H.
|
|
apply Decidable.not_and in H.
|
|
destruct H.
|
|
now elim H.
|
|
now apply not_eq_sym.
|
|
now left.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma RNA_up_tie :
|
|
forall (x:t),
|
|
eq
|
|
(sub ieee_float.RoundingMode.RNE
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x) x)
|
|
(sub ieee_float.RoundingMode.RNE x
|
|
(roundToIntegral ieee_float.RoundingMode.RTN x)) ->
|
|
is_positive x ->
|
|
((roundToIntegral ieee_float.RoundingMode.RNA x) =
|
|
(roundToIntegral ieee_float.RoundingMode.RTP x)).
|
|
Proof.
|
|
intros x h h'.
|
|
destruct x; try easy.
|
|
set (x:=(B754_finite s m e e0)); fold x in h, h'.
|
|
assert (forall m', is_finite (roundToIntegral m' x)) as h1 by
|
|
(intro m'; apply roundToIntegral_finite; easy).
|
|
apply to_real_refl; auto.
|
|
2: apply same_sign_roundToIntegral2; easy.
|
|
apply eq_sym, eq_diff_floor_ceil in h.
|
|
|
|
rewrite to_real_roundToIntegral, to_real_roundToIntegral; try easy.
|
|
f_equal.
|
|
unfold to_int.
|
|
fold (to_real x).
|
|
|
|
destruct (is_int_or_not x).
|
|
rewrite (int_to_real RTZ _ H).
|
|
destruct (valid_rnd_round_mode RNA) as (_,H').
|
|
simpl in H'.
|
|
rewrite H', Zceil_IZR; reflexivity.
|
|
|
|
unfold Znearest.
|
|
rewrite Rcompare_Eq.
|
|
rewrite Zle_bool_true; auto.
|
|
apply non_zero_positive_to_real in h'; try easy.
|
|
apply Zfloor_lub.
|
|
lra.
|
|
unfold is_zero.
|
|
unfold eq. simpl.
|
|
now destruct s.
|
|
|
|
rewrite Zceil_floor_neq in h.
|
|
rewrite plus_IZR in h.
|
|
lra.
|
|
|
|
unfold is_int in H.
|
|
apply Decidable.not_and in H.
|
|
destruct H.
|
|
now elim H.
|
|
now apply not_eq_sym.
|
|
now left.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma to_int_roundToIntegral :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t),
|
|
((to_int m x) = (to_int m (roundToIntegral m x))).
|
|
Proof.
|
|
intros m x.
|
|
destruct x; try easy.
|
|
unfold to_int at 2.
|
|
rewrite to_real_roundToIntegral by easy.
|
|
destruct (valid_rnd_round_mode m) as (_,h).
|
|
pose proof (h (to_int m (B754_finite s m0 e e0))).
|
|
now destruct m.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma to_int_monotonic :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
is_finite y -> le x y -> ((to_int m x) <= (to_int m y))%Z.
|
|
Proof.
|
|
intros m x y h1 h2 h3.
|
|
now apply to_int_le.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma to_int_of_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (i:Numbers.BinNums.Z),
|
|
in_safe_int_range i -> ((to_int m (of_int m i)) = i).
|
|
Proof.
|
|
intros m i (h1,h2).
|
|
apply eq_IZR.
|
|
rewrite <-int_to_real.
|
|
rewrite of_int_to_real.
|
|
apply Exact_rounding_for_integers; auto.
|
|
unfold in_safe_int_range; auto.
|
|
apply Bounded_real_no_overflow, rep_int_in_range; auto.
|
|
apply of_int_is_int.
|
|
pose proof pow2sb_lt_max_int.
|
|
unfold in_int_range; auto with zarith.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma eq_to_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t) (y:t), is_finite x ->
|
|
eq x y -> ((to_int m x) = (to_int m y)).
|
|
Proof.
|
|
intros m x y h1 h2.
|
|
apply to_int_eq, h2.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma neg_to_int :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_int x ->
|
|
((to_int m (neg x)) = (-(to_int m x))%Z).
|
|
Proof.
|
|
intros m x h1.
|
|
apply neg_int_to_int; auto.
|
|
Qed.
|
|
|
|
(* Why3 goal *)
|
|
Lemma roundToIntegral_is_finite :
|
|
forall (m:ieee_float.RoundingMode.mode) (x:t), is_finite x ->
|
|
is_finite (roundToIntegral m x).
|
|
Proof.
|
|
intros m x h1.
|
|
apply roundToIntegral_finite, h1.
|
|
Qed.
|
|
|
|
End GenericFloat.
|