Module FloatLib
Require Import Coqlib Utf8 Util Axioms ToString.
Require Import ZArith.
Require Import Integers.
Require Import Reals.
Require Export Fappli_IEEE.
Require Export Fappli_IEEE_bits.
Require Export Fappli_IEEE_extra.
Require Export Fappli_double_round.
Require Export Fcore_FLT.
Require Export Fcore_float_prop.
Require Export Fcore_defs.
Require Export Fcore_Raux.
Require Export Fcore_Zaux.
Require Export Fcore_generic_fmt.
Require Export Fcore_rnd_ne.
Require Export Fcore_digits.
Require Export Floats.
Open Scope R.
Arguments is_finite {
prec emax}
f.
Arguments is_finite_strict {
prec emax}
f.
Arguments is_nan {
prec emax}
f.
Arguments B2R {
prec emax}
f.
Arguments Bsign {
prec emax}
x.
Arguments ZofB {
prec emax}
f.
Arguments B2FF {
prec emax}
x.
Arguments B754_zero {
prec emax}
_.
Arguments B754_infinity {
prec emax}
_.
Arguments B754_nan {
prec emax}
_ _.
Arguments B754_finite {
prec emax}
_ m e _.
Identity Coercion f2b64 :
float >->
binary64.
Identity Coercion f2b32 :
float32 >->
binary32.
Identity Coercion b642bf :
binary64 >->
binary_float.
Identity Coercion b322bf :
binary32 >->
binary_float.
Coercion B2R :
binary_float >->
R.
Coercion Z2R :
Z >->
R.
Coercion B2FF :
binary_float >->
full_float.
Ltac Rlt_bool_case H :=
match type of H with
|
context [
Rlt_bool ?
x ?
y] =>
destruct (
Rlt_bool_spec x y)
end.
Ltac Rle_bool_case H :=
match type of H with
|
context [
Rle_bool ?
x ?
y] =>
destruct (
Rle_bool_spec x y)
end.
Ltac check_nodup H :=
let typ :=
type of H in
match goal with
| [
H':
typ |-
_] =>
match H'
with
|
H =>
fail 1
|
_ =>
fail 2
end
|
_ =>
idtac
end.
Ltac use_float_spec :=
let H :=
fresh in
match goal with
| [
_ :
context [
binary_normalize ?
prec ?
emax ?
Hprec ?
Hemax ?
mode ?
m ?
e ?
s] |-
_] =>
assert (
H:=
binary_normalize_correct prec emax Hprec Hemax mode m e s);
check_nodup H
| [|-
context [
binary_normalize ?
prec ?
emax ?
Hprec ?
Hemax ?
mode ?
m ?
e ?
s]] =>
assert (
H:=
binary_normalize_correct prec emax Hprec Hemax mode m e s);
check_nodup H
| [
_ :
context [
Bconv ?
prec1 ?
emax1 ?
prec2 ?
emax2 ?
Hprec2 ?
Hemax2 ?
pl ?
mode ?
x] |-
_] =>
assert (
H:=
Bconv_correct prec1 emax1 prec2 emax2 Hprec2 Hemax2 pl mode x);
check_nodup H
| [|-
context [
Bconv ?
prec1 ?
emax1 ?
prec2 ?
emax2 ?
Hprec2 ?
Hemax2 ?
pl ?
mode ?
x]] =>
assert (
H:=
Bconv_correct prec1 emax1 prec2 emax2 Hprec2 Hemax2 pl mode x);
check_nodup H
| [
_ :
context [
BofZ ?
prec ?
emax ?
Hprec ?
Hemax ?
x] |-
_] =>
assert (
H:=
BofZ_correct prec emax Hprec Hemax x);
check_nodup H
| [|-
context [
BofZ ?
prec ?
emax ?
Hprec ?
Hemax ?
x]] =>
assert (
H:=
BofZ_correct prec emax Hprec Hemax x);
check_nodup H
| [
_ :
context [
Bplus ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y] |-
_] =>
assert (
H:=
Bplus_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [|-
context [
Bplus ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y]] =>
assert (
H:=
Bplus_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [
_ :
context [
Bminus ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y] |-
_] =>
assert (
H:=
Bminus_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [|-
context [
Bminus ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y]] =>
assert (
H:=
Bminus_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [
_ :
context [
Bmult ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y] |-
_] =>
assert (
H:=
Bmult_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [|-
context [
Bmult ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y]] =>
assert (
H:=
Bmult_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [
_ :
context [
Bdiv ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y] |-
_] =>
assert (
H:=
Bdiv_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
| [|-
context [
Bdiv ?
prec ?
emax ?
Hprec ?
Hemax ?
pl ?
mode ?
x ?
y]] =>
assert (
H:=
Bdiv_correct prec emax Hprec Hemax pl mode x y);
check_nodup H
end.
Ltac use_float_specs :=
repeat use_float_spec.
Transparent Float32.add Float.add Float32.sub Float.sub Float32.mul Float.mul
Float32.div Float.div Float.to_single Float.of_single Float.to_int
Float32.to_int Float.to_intu Float32.to_intu Float.to_long
Float.to_longu Float32.to_long Float32.to_longu
Float.neg Float.cmp.
Transparent Float.transform_quiet_pl Float.reduce_pl Float.to_single_pl.
Transparent Archi.choose_binop_pl_32 Archi.choose_binop_pl_64
Archi.default_pl_32 Archi.default_pl_64
Archi.float_of_single_preserves_sNaN.
Lemma prec53_gt_0:
Fcore_FLX.Prec_gt_0 53.
Proof.
Hint Resolve fexp_correct valid_rnd_round_mode prec53_gt_0.
Lemma Bsign_false_ge_0:
∀
prec emax (
f:
binary_float prec emax),
Bsign f =
false -> 0 <=
f.
Proof.
destruct f as [[]|[]|[]|[]];
try discriminate;
intros _;
try apply Rle_refl.
apply F2R_ge_0_compat.
discriminate.
Qed.
Lemma Bsign_true_le_0:
∀
prec emax (
f:
binary_float prec emax),
Bsign f =
true ->
f <= 0.
Proof.
destruct f as [[]|[]|[]|[]];
try discriminate;
intros _;
try apply Rle_refl.
apply F2R_le_0_compat.
discriminate.
Qed.
Definition Fleb {
prec emax}
f1 f2 :=
match Bcompare prec emax f1 f2 with
|
Some (
Eq|
Lt) =>
true
|
Some Gt |
None =>
false
end.
Lemma Fleb_Rle:
∀
prec emax (
f1 f2:
binary_float prec emax),
is_finite f1 =
true ->
is_finite f2 =
true ->
Fleb f1 f2 =
Rle_bool f1 f2.
Proof.
Lemma Bcompare_nan:
∀
prec emax f1 f2,
is_nan f1 =
false ->
is_nan f2 =
false ->
Bcompare prec emax f1 f2 <>
None.
Proof.
intros.
intro.
destruct f1 as [|[]| |[]],
f2 as [|[]| |[]];
try discriminate.
-
simpl in H1.
destruct Zcompare;
discriminate.
-
simpl in H1.
destruct Zcompare;
discriminate.
Qed.
Lemma Fleb_total:
∀
prec emax (
f1 f2:
binary_float prec emax),
is_nan f1 =
false ->
is_nan f2 =
false ->
Fleb f1 f2 =
true \/
Fleb f2 f1 =
true.
Proof.
Lemma Bcompare_refl:
∀
prec emax f,
is_nan f =
false ->
Bcompare prec emax f f =
Some Eq.
Proof.
Lemma Fleb_refl:
∀
prec emax (
f:
binary_float prec emax),
is_nan f =
false ->
Fleb f f =
true.
Proof.
Hint Resolve Fleb_refl.
Lemma Bcompare_trans:
∀
prec emax f1 f2 f3 c,
is_nan f2 =
false ->
Bcompare prec emax f1 f2 =
c ->
Bcompare prec emax f2 f3 =
c ->
Bcompare prec emax f1 f3 =
c.
Proof.
Lemma Bcompare_Eq_trans:
∀
prec emax f1 f2 f3 c,
Bcompare prec emax f1 f2 =
Some Eq ->
Bcompare prec emax f2 f3 =
c ->
Bcompare prec emax f1 f3 =
c.
Proof.
Lemma Bcompare_trans_Eq:
∀
prec emax f1 f2 f3 c,
Bcompare prec emax f1 f2 =
c ->
Bcompare prec emax f2 f3 =
Some Eq ->
Bcompare prec emax f1 f3 =
c.
Proof.
Lemma Fleb_nan_l:
∀
prec emax (
f1 f2:
binary_float prec emax),
Fleb f1 f2 =
true ->
is_nan f1 =
false.
Proof.
intros.
unfold Fleb in H.
destruct f1,
f2;
simpl in *;
congruence.
Qed.
Hint Resolve Fleb_nan_l.
Lemma Fleb_nan_r:
∀
prec emax (
f1 f2:
binary_float prec emax),
Fleb f1 f2 =
true ->
is_nan f2 =
false.
Proof.
intros.
unfold Fleb in H.
destruct f1 as [|[]| |[]],
f2;
simpl in *;
congruence.
Qed.
Hint Resolve Fleb_nan_r.
Lemma Fleb_trans:
∀
prec emax (
f1 f2 f3:
binary_float prec emax),
Fleb f1 f2 =
true ->
Fleb f2 f3 =
true ->
Fleb f1 f3 =
true.
Proof.
Lemma fneg_decr:
forall a b,
Fleb (
Float.neg b) (
Float.neg a) =
Fleb a b.
Proof.
Lemma binary_normalize_is_nan:
forall prec emax H1 H2 m e s mode,
is_nan (
binary_normalize prec emax H1 H2 mode m e s) =
false.
Proof.
intros.
use_float_spec.
destruct Rlt_bool.
destruct H as [? []].
destruct binary_normalize;
try discriminate;
reflexivity.
destruct mode;
destruct binary_normalize;
try reflexivity;
destruct n;
try discriminate;
destruct Rlt_bool;
discriminate.
Qed.
Lemma floatofsingle_exact:
forall f, (
Float.of_single f:
R) =
f
/\ (
is_finite f =
true ->
is_finite (
Float.of_single f) =
true).
Proof.
Lemma floatofsingle_nan:
∀
f,
is_nan f =
false ->
is_nan (
Float.of_single f) =
false.
Proof.
Lemma zoffloat_incr:
forall prec emax (
f1 f2:
binary_float prec emax)
z1 z2,
Fleb f1 f2 =
true ->
ZofB f1 =
Some z1 ->
ZofB f2 =
Some z2 ->
(
z1 <=
z2)%
Z.
Proof.
Definition Zoffloat_DN (
f:
float):
option Z :=
match f with
|
B754_finite s m (
Zpos e)
_ =>
Some (
cond_Zopp s (
Zpos m) *
Zpower_pos radix2 e)%
Z
|
B754_finite s m 0
_ =>
Some (
cond_Zopp s (
Zpos m))
|
B754_finite s m (
Zneg e)
_ =>
Some (
cond_Zopp s (
Zpos m) /
Zpower_pos radix2 e)%
Z
|
B754_zero _ =>
Some 0%
Z
|
_ =>
None
end.
Lemma Zoffloat_DN_correct:
forall f :
float,
match Zoffloat_DN f with
|
Some n =>
is_finite f =
true /\ (
n:
R) =
round radix2 (
Fcore_FIX.FIX_exp 0) (
round_mode mode_DN)
f
|
None =>
is_finite f =
false
end.
Proof.
Lemma fadd_commut:
forall a b pl,
Bplus 53 1024 (@
eq_refl _ Lt) (@
eq_refl _ Lt)
pl mode_NE a b =
Bplus 53 1024 (@
eq_refl _ Lt) (@
eq_refl _ Lt) (
fun a b =>
pl b a)
mode_NE b a.
Proof.
intros.
destruct a as [[]|[]| |],
b as [[]|[]| |];
try reflexivity.
simpl.
rewrite Zplus_comm,
Zmin_comm.
reflexivity.
Qed.
Lemma Bconv_Bopp:
∀
prec emax
prec'
emax'
Hprec'
Hemax'
conv_pl opp_pl opp_pl'
x,
(∀
s pl, (
let '(
s,
pl) :=
opp_pl s pl in conv_pl s pl) =
(
let '(
s,
pl) :=
conv_pl s pl in opp_pl'
s pl)) ->
Bopp prec'
emax'
opp_pl' (
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl mode_NE x) =
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl mode_NE (
Bopp prec emax opp_pl x).
Proof.
Lemma Bconv_Babs:
∀
prec emax
prec'
emax'
Hprec'
Hemax'
conv_pl abs_pl abs_pl'
x,
(∀
s pl, (
let '(
s,
pl) :=
abs_pl s pl in conv_pl s pl) =
(
let '(
s,
pl) :=
conv_pl s pl in abs_pl'
s pl)) ->
Babs prec'
emax'
abs_pl' (
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl mode_NE x) =
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl mode_NE (
Babs prec emax abs_pl x).
Proof.
Lemma Bconv_Bplus:
∀
prec emax Hprec Hemax
prec'
emax'
Hprec'
Hemax'
conv_pl conv_pl'
plus_pl plus_pl'
x y,
(2*
prec + 1 <=
prec')%
Z -> (
emax <
emax')%
Z ->
is_nan x =
false ->
is_nan y =
false ->
(∀
x y,
is_nan x =
false ->
is_nan y =
false ->
∀
x'
y',
is_nan x' =
false ->
is_nan y' =
false ->
(
let '(
b,
pl) :=
plus_pl'
x'
y'
in conv_pl b pl) =
plus_pl x y) ->
Bplus prec emax Hprec Hemax plus_pl mode_NE x y =
Bconv prec'
emax'
prec emax Hprec Hemax conv_pl mode_NE
(
Bplus prec'
emax'
Hprec'
Hemax'
plus_pl'
mode_NE
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE x)
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE y)).
Proof.
intros *
prec_le emax_le NANx NANy NAN.
unfold Fcore_FLX.Prec_gt_0 in *.
destruct (
is_finite x)
eqn:
FINx;
[
assert (
Hx:=
FINx);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hx;
eauto;
try omega|];
(
destruct (
is_finite y)
eqn:
FINy;
[
assert (
Hy:=
FINy);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hy;
eauto;
try omega|]).
-
use_float_specs.
clear H H0.
destruct Hx as (? & ? & ?),
Hy as (? & ? & ?).
rewrite H,
H4,
H5,
H7,
Rlt_bool_true in H2.
+
destruct H2 as (? & ? & ?);
auto.
assert (
round radix2 (
FLT_exp (3-
emax-
prec)
prec) (
round_mode mode_NE)
(
round radix2 (
FLT_exp (3-
emax'-
prec')
prec')
(
round_mode mode_NE) (
x +
y)) =
round radix2 (
FLT_exp (3-
emax-
prec)
prec)
(
round_mode mode_NE) (
x +
y)).
{
apply double_round_plus_FLT;
auto.
omega.
apply FLT_format_B2R.
auto.
apply FLT_format_B2R.
auto. }
rewrite H2,
H10,
H9 in H1.
Rlt_bool_case H1.
*
destruct H1 as (? & ? & ?),
H3 as (? & ? & ?);
auto.
apply B2R_Bsign_inj;
auto;
congruence.
*
apply B2FF_inj.
destruct H3;
auto.
rewrite H1,
H3;
auto.
f_equal.
replace 0
with (0+0)
by ring.
destruct x,
y;
try discriminate;
simpl in H12;
subst b.
simpl.
rewrite Rcompare_Eq by auto.
destruct b0;
auto.
destruct b0; [
rewrite Rcompare_Lt|
rewrite Rcompare_Gt];
auto;
apply Rplus_lt_compat;
(
apply F2R_lt_0_compat ||
apply F2R_gt_0_compat);
reflexivity.
+
assert (∀ (
x:
binary_float prec emax),
Rabs x <=
Fcore_ulp.pred radix2 (
FLT_exp (3 -
emax -
prec)
prec) (
bpow radix2 emax)).
{
intros.
apply Fcore_ulp.le_pred_lt.
now auto.
apply generic_format_abs,
generic_format_B2R.
apply generic_format_bpow.
unfold FLT_exp.
zify;
omega.
apply abs_B2R_lt_emax. }
pose proof (
H8 x).
specialize (
H8 y).
eapply Rplus_le_compat in H8. 2:
apply H9.
clear H9.
eapply Rle_trans in H8. 2:
apply Rabs_triang.
rewrite <-
round_NE_abs by auto.
eapply Rle_lt_trans.
apply round_le,
H8.
auto.
apply (
valid_rnd_round_mode mode_NE).
rewrite <-
double.
unfold Fcore_ulp.pred,
Fcore_ulp.succ,
Fcore_ulp.pred_pos.
rewrite Rle_bool_false, !
Ropp_involutive by (
apply Ropp_lt_gt_0_contravar,
Rlt_gt,
bpow_gt_0).
rewrite ln_beta_bpow,
Z.add_simpl_r,
Req_bool_true,
Rmult_minus_distr_l by auto.
replace (
FLT_exp (3 -
emax -
prec)
prec emax)
with (
emax -
prec)%
Z
by (
unfold FLT_exp;
zify;
omega).
rewrite round_generic. 2:
apply (
valid_rnd_round_mode mode_NE).
*
assert (1+
emax <=
emax')%
Z by omega.
apply bpow_le with (
r:=
radix2)
in H9.
rewrite bpow_plus in H9.
simpl in H9.
pose proof (
bpow_gt_0 radix2 (
emax -
prec)).
Psatz.lra.
*
apply generic_format_FLT.
exists {|
Fnum :=
radix2^
prec - 1;
Fexp :=
emax -
prec + 1 |}.
{
split; [|
split].
-
unfold F2R,
Fnum,
Fexp.
rewrite Z2R_minus,
Z2R_Zpower,
bpow_plus,
Rmult_minus_distr_r, <-
Rmult_assoc, <-
bpow_plus,
Zplus_minus by omega.
simpl.
ring.
-
unfold Fnum.
assert (0 <
radix2 ^
prec)%
Z by (
apply Zpower_gt_0;
omega).
assert (
prec <=
prec')%
Z by omega.
apply Zpower_le with (
r:=
radix2)
in H10.
zify;
omega.
-
unfold Fexp.
omega. }
-
destruct Hx as (? & ? & ?).
destruct x,
y;
try discriminate.
+
auto.
+
destruct Bconv;
try discriminate;
auto.
-
destruct Hy as (? & ? & ?).
destruct x,
y;
try discriminate.
+
auto.
+
destruct Bconv;
try discriminate;
auto.
-
destruct x,
y;
try discriminate.
simpl.
destruct (
eqb b b0).
auto.
simpl.
specialize (
NAN (
B754_infinity b) (
B754_infinity b0)
eq_refl eq_refl
(
B754_infinity b) (
B754_infinity b0)
eq_refl eq_refl).
rewrite <-
NAN.
destruct plus_pl'.
simpl.
destruct conv_pl.
auto.
Qed.
Lemma Bconv_Bmult:
∀
prec emax Hprec Hemax
prec'
emax'
Hprec'
Hemax'
conv_pl conv_pl'
mult_pl mult_pl'
x y,
(2*
prec <=
prec')%
Z -> (2*
emax <=
emax')%
Z ->
is_nan x =
false ->
is_nan y =
false ->
(∀
x y,
is_nan x =
false ->
is_nan y =
false ->
∀
x'
y',
is_nan x' =
false ->
is_nan y' =
false ->
(
let '(
b,
pl) :=
mult_pl'
x'
y'
in conv_pl b pl) =
mult_pl x y) ->
Bmult prec emax Hprec Hemax mult_pl mode_NE x y =
Bconv prec'
emax'
prec emax Hprec Hemax conv_pl mode_NE
(
Bmult prec'
emax'
Hprec'
Hemax'
mult_pl'
mode_NE
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE x)
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE y)).
Proof.
intros *
prec_le emax_le NANx NANy NAN.
unfold Fcore_FLX.Prec_gt_0 in *.
destruct (
is_finite x)
eqn:
FINx;
[
assert (
Hx:=
FINx);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hx;
eauto;
try omega|];
(
destruct (
is_finite y)
eqn:
FINy;
[
assert (
Hy:=
FINy);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hy;
eauto;
try omega|]).
-
use_float_specs.
clear H H0.
destruct Hx as (? & ? & ?),
Hy as (? & ? & ?).
rewrite H,
H4,
H5,
H7,
Rlt_bool_true in H2.
+
destruct H2 as (? & ? & ?);
auto.
assert (
round radix2 (
FLT_exp (3-
emax-
prec)
prec) (
round_mode mode_NE)
(
round radix2 (
FLT_exp (3-
emax'-
prec')
prec') (
round_mode mode_NE) (
x *
y)) =
round radix2 (
FLT_exp (3-
emax-
prec)
prec) (
round_mode mode_NE) (
x *
y)).
{
apply double_round_mult_FLT;
auto.
omega.
apply FLT_format_B2R.
auto.
apply FLT_format_B2R.
auto. }
rewrite H2,
H10,
H9 in H1. 2:
apply is_finite_not_is_nan;
rewrite H8,
H0,
H6;
auto.
Rlt_bool_case H1.
*
destruct H1 as (? & ? & ?),
H3 as (? & ? & ?).
rewrite H8,
H0,
H6.
auto.
apply B2R_Bsign_inj.
rewrite H14,
FINx,
FINy.
auto.
apply H12.
congruence.
rewrite H15,
H13.
auto.
apply is_finite_not_is_nan.
rewrite H14,
FINx,
FINy.
auto.
*
apply B2FF_inj.
rewrite H1,
H3.
auto.
rewrite H8,
H0,
H6.
auto.
+
rewrite round_generic,
Rabs_mult.
eapply Rlt_le_trans.
apply Rmult_le_0_lt_compat.
apply Rabs_pos.
apply Rabs_pos.
apply abs_B2R_lt_emax.
apply abs_B2R_lt_emax.
rewrite <-
bpow_plus.
apply bpow_le.
omega.
apply (
valid_rnd_round_mode mode_NE).
eapply double_round_mult_aux;
try apply generic_format_B2R.
split;
intros;
unfold FLT_exp;
zify;
omega.
-
destruct Hx as (? & ? & ?).
destruct x,
y;
try discriminate.
+
specialize (
NAN (
B754_zero b) (
B754_infinity b0)
eq_refl eq_refl
(
B754_zero b) (
B754_infinity b0)
eq_refl eq_refl).
simpl.
destruct mult_pl',
mult_pl.
simpl.
rewrite NAN.
auto.
+
destruct Bconv;
try discriminate;
auto.
symmetry in H.
apply F2R_eq_0_reg in H.
destruct b;
discriminate.
simpl in H1.
subst b1.
auto.
-
destruct Hy as (? & ? & ?).
destruct x,
y;
try discriminate.
+
specialize (
NAN (
B754_infinity b) (
B754_zero b0)
eq_refl eq_refl
(
B754_infinity b) (
B754_zero b0)
eq_refl eq_refl).
simpl.
destruct mult_pl',
mult_pl.
simpl.
rewrite NAN.
auto.
+
destruct Bconv;
try discriminate;
auto.
symmetry in H.
apply F2R_eq_0_reg in H.
destruct b0;
discriminate.
simpl in H1.
subst b1.
auto.
-
destruct x,
y;
try discriminate.
auto.
Qed.
Lemma Bconv_Bdiv:
∀
prec emax Hprec Hemax
prec'
emax'
Hprec'
Hemax'
conv_pl conv_pl'
div_pl div_pl'
x y,
(2 *
prec <=
prec')%
Z -> (2 +
emax + 2 *
prec <=
emax' +
prec')%
Z ->
(-3 + 2 *
emax +
prec <=
emax')%
Z ->
is_nan x =
false ->
is_nan y =
false ->
(∀
x y,
is_nan x =
false ->
is_nan y =
false ->
∀
x'
y',
is_nan x' =
false ->
is_nan y' =
false ->
(
let '(
b,
pl) :=
div_pl'
x'
y'
in conv_pl b pl) =
div_pl x y) ->
Bdiv prec emax Hprec Hemax div_pl mode_NE x y =
Bconv prec'
emax'
prec emax Hprec Hemax conv_pl mode_NE
(
Bdiv prec'
emax'
Hprec'
Hemax'
div_pl'
mode_NE
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE x)
(
Bconv prec emax prec'
emax'
Hprec'
Hemax'
conv_pl'
mode_NE y)).
Proof.
intros *
prec_le le1 le2 NANx NANy NAN.
unfold Fcore_FLX.Prec_gt_0 in *.
destruct (
is_finite x)
eqn:
FINx;
[
assert (
Hx:=
FINx);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hx;
eauto;
try omega|];
(
destruct (
is_finite y)
eqn:
FINy;
[
assert (
Hy:=
FINy);
eapply (
Bconv_widen_exact prec emax prec'
emax'
Hprec Hprec'
Hemax')
with (
conv_nan:=
conv_pl') (
m:=
mode_NE)
in Hy;
eauto;
try omega|]).
destruct (
Req_EM_T y 0).
-
destruct y;
try discriminate.
+
destruct x;
try discriminate.
specialize (
NAN (
B754_zero b0) (
B754_zero b)
eq_refl eq_refl
(
B754_zero b0) (
B754_zero b)
eq_refl eq_refl).
simpl.
rewrite <-
NAN.
destruct div_pl'.
simpl.
destruct conv_pl.
auto.
destruct Hx as (? & ? & ?).
destruct Bconv;
try discriminate.
symmetry in H.
apply F2R_eq_0_reg in H.
destruct b0;
discriminate.
simpl in H1.
subst b1.
auto.
+
apply F2R_eq_0_reg in e.
destruct b;
discriminate.
-
use_float_specs.
clear H H0.
destruct Hx as (? & ? & ?),
Hy as (? & ? & ?).
rewrite H,
H4,
H5,
H7,
Rlt_bool_true in H2.
+
destruct H2 as (? & ? & ?);
auto.
assert (
round radix2 (
FLT_exp (3-
emax-
prec)
prec) (
round_mode mode_NE)
(
round radix2 (
FLT_exp (3-
emax'-
prec')
prec') (
round_mode mode_NE) (
x /
y)) =
round radix2 (
FLT_exp (3-
emax-
prec)
prec) (
round_mode mode_NE) (
x /
y)).
{
apply double_round_div_FLT;
auto.
exists 1%
Z.
auto.
omega.
apply FLT_format_B2R.
auto.
apply FLT_format_B2R.
auto. }
rewrite H2,
H10,
H9 in H1. 2:
apply is_finite_not_is_nan;
rewrite H8;
auto.
Rlt_bool_case H1.
*
destruct H1 as (? & ? & ?),
H3 as (? & ? & ?);
auto.
rewrite H8;
auto.
apply B2R_Bsign_inj.
rewrite H14;
auto.
apply H12.
congruence.
rewrite H15,
H13.
auto.
apply is_finite_not_is_nan.
rewrite H14;
auto.
*
apply B2FF_inj.
rewrite H1,
H3.
auto.
auto.
rewrite H8;
auto.
+
rewrite <-
round_NE_abs by auto.
unfold Rdiv.
rewrite Rabs_mult,
Rabs_Rinv by auto.
assert (
bpow radix2 (3-
emax-
prec) <=
Rabs y).
{
revert n.
edestruct FLT_format_B2R with (
x:=
y)
as ([] & -> & ? & ?).
auto.
rewrite <-
F2R_Zabs.
unfold F2R,
Fcore_defs.Fnum,
Fcore_defs.Fexp in *.
intro.
assert (
Fnum <> 0%
Z).
{
contradict n.
subst.
simpl.
ring. }
rewrite <-
Rmult_1_l at 1.
apply Rmult_le_compat.
Psatz.lra.
apply bpow_ge_0.
apply Z2R_le with (
m:=1%
Z).
zify;
omega.
apply bpow_le.
auto. }
apply Rinv_le in H8. 2:
apply bpow_gt_0.
rewrite <-
bpow_opp in H8.
assert (
Rabs x <=
Fcore_ulp.pred radix2 (
FLT_exp (3 -
emax -
prec)
prec) (
bpow radix2 emax)).
{
intros.
apply Fcore_ulp.le_pred_lt.
auto.
apply generic_format_abs,
generic_format_B2R.
apply generic_format_bpow.
unfold FLT_exp.
zify;
omega.
apply abs_B2R_lt_emax. }
eapply Rle_lt_trans.
apply round_le.
auto.
apply (
valid_rnd_round_mode mode_NE).
apply Rmult_le_compat.
apply Rabs_pos.
apply Rlt_le,
Rinv_0_lt_compat.
destruct (
Rabs_pos y).
auto.
apply Rabs_no_R0 in n.
destruct n.
auto.
apply H9.
apply H8.
unfold Fcore_ulp.pred,
Fcore_ulp.succ,
Fcore_ulp.pred_pos.
rewrite Rle_bool_false, !
Ropp_involutive by (
apply Ropp_lt_gt_0_contravar,
Rlt_gt,
bpow_gt_0).
rewrite ln_beta_bpow,
Z.add_simpl_r,
Req_bool_true,
Rmult_minus_distr_r,
<- !
bpow_plus by auto.
replace (
FLT_exp (3 -
emax -
prec)
prec emax)
with (
emax-
prec)%
Z
by (
unfold FLT_exp;
zify;
omega).
rewrite round_generic.
assert (0 <
bpow radix2 (
emax -
prec + - (3 -
emax -
prec)))
by apply bpow_gt_0.
assert (
emax + - (3 -
emax -
prec) <=
emax')%
Z by omega.
apply bpow_le with (
r:=
radix2)
in H11.
Psatz.lra.
apply (
valid_rnd_round_mode mode_NE).
apply generic_format_FLT.
exists {|
Fnum :=
radix2^
prec - 1;
Fexp :=
emax -
prec + - (3 -
emax -
prec) |}.
{
split; [|
split].
-
unfold F2R,
Fnum,
Fexp.
rewrite Z2R_minus,
Z2R_Zpower,
Rmult_minus_distr_r.
f_equal.
rewrite <-
bpow_plus.
f_equal.
ring.
unfold Z2R,
P2R.
ring.
omega.
-
unfold Fnum.
assert (0 <
radix2 ^
prec)%
Z by (
apply Zpower_gt_0;
omega).
assert (
prec <=
prec')%
Z by omega.
apply Zpower_le with (
r:=
radix2)
in H11.
zify;
omega.
-
unfold Fexp.
omega. }
-
destruct Hx as (? & ? & ?).
destruct x,
y;
try discriminate.
+
auto.
+
destruct Bconv;
try discriminate;
simpl in H1;
subst b1;
auto.
-
destruct Hy as (? & ? & ?).
destruct x,
y;
try discriminate.
+
auto.
+
destruct Bconv;
try discriminate;
simpl in H1;
subst b1;
auto.
-
destruct x,
y;
try discriminate.
simpl.
specialize (
NAN (
B754_infinity b) (
B754_infinity b0)
eq_refl eq_refl
(
B754_infinity b) (
B754_infinity b0)
eq_refl eq_refl).
rewrite <-
NAN.
destruct div_pl'.
simpl.
destruct conv_pl.
auto.
Qed.
Lemma transform_quiet_32_64:
∀
n,
Float32.transform_quiet_pl n =
Float.reduce_pl (
Float.transform_quiet_pl (
Float.expand_pl n)).
Proof.
Lemma plus_double_round:
∀ (
x y:
float32),
Float32.add x y =
Float.to_single (
Float.add (
Float.of_single x) (
Float.of_single y)).
Proof.
intros.
destruct (
is_nan x)
eqn:
NANx, (
is_nan y)
eqn:
NANy.
-
destruct x,
y;
try discriminate.
simpl.
rewrite 2!
Float.transform_quiet_pl_idempotent.
f_equal.
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANy).
destruct x;
try discriminate;
simpl;
destruct (
Float.of_single y),
y;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANx).
destruct y;
try discriminate;
simpl;
destruct (
Float.of_single x),
x;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
apply Bconv_Bplus.
omega.
omega.
auto.
auto.
intros.
assert ((
let '(
s,
pl) :=
Archi.default_pl_64 in Float.to_single_pl s pl) =
Archi.default_pl_32).
{
unfold Float.transform_quiet_pl,
Float.to_single_pl,
Archi.default_pl_32,
Float.reduce_pl.
simpl.
f_equal.
f_equal.
assert (∀ (
b:
bool) (
e:
b=
b),
e =
eq_refl).
{
destruct b;
intros;
exact (
match e with eq_refl =>
eq_refl end). }
apply H3. }
destruct x0,
y0,
x',
y';
try discriminate;
apply H3.
Qed.
Lemma sub_double_round:
∀ (
x y:
float32),
Float32.sub x y =
Float.to_single (
Float.sub (
Float.of_single x) (
Float.of_single y)).
Proof.
intros.
destruct (
is_nan x)
eqn:
NANx, (
is_nan y)
eqn:
NANy.
-
destruct x,
y;
try discriminate.
simpl.
rewrite 2!
Float.transform_quiet_pl_idempotent.
f_equal.
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANy).
destruct x;
try discriminate;
simpl;
destruct (
Float.of_single y),
y;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANx).
destruct y;
try discriminate;
simpl;
destruct (
Float.of_single x),
x;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
unfold Float32.sub,
Float.sub,
Bminus,
Float.of_single.
erewrite Bconv_Bopp.
apply Bconv_Bplus.
omega.
omega.
auto.
destruct y;
try discriminate;
reflexivity.
intros.
assert ((
let '(
s,
pl) :=
Archi.default_pl_64 in Float.to_single_pl s pl) =
Archi.default_pl_32).
{
unfold Float.transform_quiet_pl,
Float.to_single_pl,
Archi.default_pl_32,
Float.reduce_pl.
simpl.
f_equal.
f_equal.
assert (∀ (
b:
bool) (
e:
b=
b),
e =
eq_refl).
{
destruct b;
intros;
exact (
match e with eq_refl =>
eq_refl end). }
apply H3. }
destruct x0,
y0,
x',
y';
try discriminate;
apply H3.
auto.
Qed.
Lemma mult_double_round:
∀ (
x y:
float32),
Float32.mul x y =
Float.to_single (
Float.mul (
Float.of_single x) (
Float.of_single y)).
Proof.
intros.
destruct (
is_nan x)
eqn:
NANx, (
is_nan y)
eqn:
NANy.
-
destruct x,
y;
try discriminate.
simpl.
rewrite 2!
Float.transform_quiet_pl_idempotent.
f_equal.
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANy).
destruct x;
try discriminate;
simpl;
destruct (
Float.of_single y),
y;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANx).
destruct y;
try discriminate;
simpl;
destruct (
Float.of_single x),
x;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
apply Bconv_Bmult.
omega.
omega.
auto.
auto.
intros.
assert ((
let '(
s,
pl) :=
Archi.default_pl_64 in Float.to_single_pl s pl) =
Archi.default_pl_32).
{
unfold Float.transform_quiet_pl,
Float.to_single_pl,
Archi.default_pl_32,
Float.reduce_pl.
simpl.
f_equal.
f_equal.
assert (∀ (
b:
bool) (
e:
b=
b),
e =
eq_refl).
{
destruct b;
intros;
exact (
match e with eq_refl =>
eq_refl end). }
apply H3. }
destruct x0,
y0,
x',
y';
try discriminate;
apply H3.
Qed.
Lemma div_double_round:
∀ (
x y:
float32),
Float32.div x y =
Float.to_single (
Float.div (
Float.of_single x) (
Float.of_single y)).
Proof.
intros.
destruct (
is_nan x)
eqn:
NANx, (
is_nan y)
eqn:
NANy.
-
destruct x,
y;
try discriminate.
simpl.
rewrite 2!
Float.transform_quiet_pl_idempotent.
f_equal.
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANy).
destruct x;
try discriminate;
simpl;
destruct (
Float.of_single y),
y;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
pose proof (
floatofsingle_nan _ NANx).
destruct y;
try discriminate;
simpl;
destruct (
Float.of_single x),
x;
try discriminate;
simpl;
rewrite !
Float.transform_quiet_pl_idempotent;
f_equal;
apply transform_quiet_32_64.
-
apply Bconv_Bdiv.
omega.
omega.
omega.
auto.
auto.
intros.
assert ((
let '(
s,
pl) :=
Archi.default_pl_64 in Float.to_single_pl s pl) =
Archi.default_pl_32).
{
unfold Float.transform_quiet_pl,
Float.to_single_pl,
Archi.default_pl_32,
Float.reduce_pl.
simpl.
f_equal.
f_equal.
assert (∀ (
b:
bool) (
e:
b=
b),
e =
eq_refl).
{
destruct b;
intros;
exact (
match e with eq_refl =>
eq_refl end). }
apply H3. }
destruct x0,
y0,
x',
y';
try discriminate;
apply H3.
Qed.
Instance FloatToString :
ToString float :=
fun f =>
match f with
|
Fappli_IEEE.B754_zero sg =>
if sg then "-0.0"
else "+0.0"
|
Fappli_IEEE.B754_infinity sg =>
if sg then "-∞"
else "+∞"
|
Fappli_IEEE.B754_nan sg pl =>
(
if sg then "
NAN(-,"
else "
NAN(+,") ++ (
to_string (
proj1_sig pl)) ++ ")"
|
Fappli_IEEE.B754_finite sg m e _ =>
if Z.eqb e (-1074)
then
(
if sg then "-"
else "+") ++ (
to_string m) ++ ".
p" ++ (
to_string (
e))
else
(
if sg then "-."
else "+.") ++ (
to_string m) ++ "
p" ++ (
to_string (
e+56)%
Z)
end.
Instance Float32ToString :
ToString float32 :=
fun f =>
match f with
|
Fappli_IEEE.B754_zero sg =>
if sg then "-0.0"
else "+0.0"
|
Fappli_IEEE.B754_infinity sg =>
if sg then "-∞"
else "+∞"
|
Fappli_IEEE.B754_nan sg pl =>
(
if sg then "
NAN(-,"
else "
NAN(+,") ++ (
to_string (
proj1_sig pl)) ++ ")"
|
Fappli_IEEE.B754_finite sg m e _ =>
if Z.eqb e (-149)
then
(
if sg then "-"
else "+") ++ (
to_string m) ++ ".
p" ++ (
to_string e)
else
(
if sg then "-."
else "+.") ++ (
to_string m) ++ "
p" ++ (
to_string (
e+24)%
Z)
end.
Definition one :
float :=
BofZ 53 1024
eq_refl eq_refl 1.