aboutsummaryrefslogtreecommitdiffstats
path: root/flocq/Prop/Plus_error.v
diff options
context:
space:
mode:
Diffstat (limited to 'flocq/Prop/Plus_error.v')
-rw-r--r--flocq/Prop/Plus_error.v606
1 files changed, 606 insertions, 0 deletions
diff --git a/flocq/Prop/Plus_error.v b/flocq/Prop/Plus_error.v
new file mode 100644
index 00000000..42f80093
--- /dev/null
+++ b/flocq/Prop/Plus_error.v
@@ -0,0 +1,606 @@
+(**
+This file is part of the Flocq formalization of floating-point
+arithmetic in Coq: http://flocq.gforge.inria.fr/
+
+Copyright (C) 2010-2018 Sylvie Boldo
+#<br />#
+Copyright (C) 2010-2018 Guillaume Melquiond
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+COPYING file for more details.
+*)
+
+(** * Error of the rounded-to-nearest addition is representable. *)
+
+Require Import Psatz.
+Require Import Raux Defs Float_prop Generic_fmt.
+Require Import FIX FLX FLT Ulp Operations.
+Require Import Relative.
+
+
+Section Fprop_plus_error.
+
+Variable beta : radix.
+Notation bpow e := (bpow beta e).
+
+Variable fexp : Z -> Z.
+Context { valid_exp : Valid_exp fexp }.
+
+Section round_repr_same_exp.
+
+Variable rnd : R -> Z.
+Context { valid_rnd : Valid_rnd rnd }.
+
+Lemma round_repr_same_exp :
+ forall m e,
+ exists m',
+ round beta fexp rnd (F2R (Float beta m e)) = F2R (Float beta m' e).
+Proof with auto with typeclass_instances.
+intros m e.
+set (e' := cexp beta fexp (F2R (Float beta m e))).
+unfold round, scaled_mantissa. fold e'.
+destruct (Zle_or_lt e' e) as [He|He].
+exists m.
+unfold F2R at 2. simpl.
+rewrite Rmult_assoc, <- bpow_plus.
+rewrite <- IZR_Zpower. 2: omega.
+rewrite <- mult_IZR, Zrnd_IZR...
+unfold F2R. simpl.
+rewrite mult_IZR.
+rewrite Rmult_assoc.
+rewrite IZR_Zpower. 2: omega.
+rewrite <- bpow_plus.
+apply (f_equal (fun v => IZR m * bpow v)%R).
+ring.
+exists ((rnd (IZR m * bpow (e - e'))) * Zpower beta (e' - e))%Z.
+unfold F2R. simpl.
+rewrite mult_IZR.
+rewrite IZR_Zpower. 2: omega.
+rewrite 2!Rmult_assoc.
+rewrite <- 2!bpow_plus.
+apply (f_equal (fun v => _ * bpow v)%R).
+ring.
+Qed.
+
+End round_repr_same_exp.
+
+Context { monotone_exp : Monotone_exp fexp }.
+Notation format := (generic_format beta fexp).
+
+Variable choice : Z -> bool.
+
+Lemma plus_error_aux :
+ forall x y,
+ (cexp beta fexp x <= cexp beta fexp y)%Z ->
+ format x -> format y ->
+ format (round beta fexp (Znearest choice) (x + y) - (x + y))%R.
+Proof.
+intros x y.
+set (ex := cexp beta fexp x).
+set (ey := cexp beta fexp y).
+intros He Hx Hy.
+destruct (Req_dec (round beta fexp (Znearest choice) (x + y) - (x + y)) R0) as [H0|H0].
+rewrite H0.
+apply generic_format_0.
+set (mx := Ztrunc (scaled_mantissa beta fexp x)).
+set (my := Ztrunc (scaled_mantissa beta fexp y)).
+(* *)
+assert (Hxy: (x + y)%R = F2R (Float beta (mx + my * beta ^ (ey - ex)) ex)).
+rewrite Hx, Hy.
+fold mx my ex ey.
+rewrite <- F2R_plus.
+unfold Fplus. simpl.
+now rewrite Zle_imp_le_bool with (1 := He).
+(* *)
+rewrite Hxy.
+destruct (round_repr_same_exp (Znearest choice) (mx + my * beta ^ (ey - ex)) ex) as (mxy, Hxy').
+rewrite Hxy'.
+assert (H: (F2R (Float beta mxy ex) - F2R (Float beta (mx + my * beta ^ (ey - ex)) ex))%R =
+ F2R (Float beta (mxy - (mx + my * beta ^ (ey - ex))) ex)).
+now rewrite <- F2R_minus, Fminus_same_exp.
+rewrite H.
+apply generic_format_F2R.
+intros _.
+apply monotone_exp.
+rewrite <- H, <- Hxy', <- Hxy.
+apply mag_le_abs.
+exact H0.
+pattern x at 3 ; replace x with (-(y - (x + y)))%R by ring.
+rewrite Rabs_Ropp.
+now apply (round_N_pt beta _ choice (x + y)).
+Qed.
+
+(** Error of the addition *)
+Theorem plus_error :
+ forall x y,
+ format x -> format y ->
+ format (round beta fexp (Znearest choice) (x + y) - (x + y))%R.
+Proof.
+intros x y Hx Hy.
+destruct (Zle_or_lt (cexp beta fexp x) (cexp beta fexp y)).
+now apply plus_error_aux.
+rewrite Rplus_comm.
+apply plus_error_aux ; try easy.
+now apply Zlt_le_weak.
+Qed.
+
+End Fprop_plus_error.
+
+Section Fprop_plus_zero.
+
+Variable beta : radix.
+Notation bpow e := (bpow beta e).
+
+Variable fexp : Z -> Z.
+Context { valid_exp : Valid_exp fexp }.
+Context { exp_not_FTZ : Exp_not_FTZ fexp }.
+Notation format := (generic_format beta fexp).
+
+Section round_plus_eq_zero_aux.
+
+Variable rnd : R -> Z.
+Context { valid_rnd : Valid_rnd rnd }.
+
+Lemma round_plus_neq_0_aux :
+ forall x y,
+ (cexp beta fexp x <= cexp beta fexp y)%Z ->
+ format x -> format y ->
+ (0 < x + y)%R ->
+ round beta fexp rnd (x + y) <> 0%R.
+Proof with auto with typeclass_instances.
+intros x y He Hx Hy Hxy.
+destruct (mag beta (x + y)) as (exy, Hexy).
+simpl.
+specialize (Hexy (Rgt_not_eq _ _ Hxy)).
+destruct (Zle_or_lt exy (fexp exy)) as [He'|He'].
+(* . *)
+assert (H: (x + y)%R = F2R (Float beta (Ztrunc (x * bpow (- fexp exy)) +
+ Ztrunc (y * bpow (- fexp exy))) (fexp exy))).
+rewrite (subnormal_exponent beta fexp exy x He' Hx) at 1.
+rewrite (subnormal_exponent beta fexp exy y He' Hy) at 1.
+now rewrite <- F2R_plus, Fplus_same_exp.
+rewrite H.
+rewrite round_generic...
+rewrite <- H.
+now apply Rgt_not_eq.
+apply generic_format_F2R.
+intros _.
+rewrite <- H.
+unfold cexp.
+rewrite mag_unique with (1 := Hexy).
+apply Z.le_refl.
+(* . *)
+intros H.
+elim Rle_not_lt with (1 := round_le beta _ rnd _ _ (proj1 Hexy)).
+rewrite (Rabs_pos_eq _ (Rlt_le _ _ Hxy)).
+rewrite H.
+rewrite round_generic...
+apply bpow_gt_0.
+apply generic_format_bpow.
+apply Zlt_succ_le.
+now rewrite (Zsucc_pred exy) in He'.
+Qed.
+
+End round_plus_eq_zero_aux.
+
+Variable rnd : R -> Z.
+Context { valid_rnd : Valid_rnd rnd }.
+
+(** rnd(x+y)=0 -> x+y = 0 provided this is not a FTZ format *)
+Theorem round_plus_neq_0 :
+ forall x y,
+ format x -> format y ->
+ (x + y <> 0)%R ->
+ round beta fexp rnd (x + y) <> 0%R.
+Proof with auto with typeclass_instances.
+intros x y Hx Hy Hxy.
+destruct (Rle_or_lt 0 (x + y)) as [H1|H1].
+(* . *)
+destruct (Zle_or_lt (cexp beta fexp x) (cexp beta fexp y)) as [H2|H2].
+apply round_plus_neq_0_aux...
+lra.
+rewrite Rplus_comm.
+apply round_plus_neq_0_aux ; try easy.
+now apply Zlt_le_weak.
+lra.
+(* . *)
+rewrite <- (Ropp_involutive (x + y)), Ropp_plus_distr.
+rewrite round_opp.
+apply Ropp_neq_0_compat.
+destruct (Zle_or_lt (cexp beta fexp (-x)) (cexp beta fexp (-y))) as [H2|H2].
+apply round_plus_neq_0_aux; try apply generic_format_opp...
+lra.
+rewrite Rplus_comm.
+apply round_plus_neq_0_aux; try apply generic_format_opp...
+now apply Zlt_le_weak.
+lra.
+Qed.
+
+Theorem round_plus_eq_0 :
+ forall x y,
+ format x -> format y ->
+ round beta fexp rnd (x + y) = 0%R ->
+ (x + y = 0)%R.
+Proof with auto with typeclass_instances.
+intros x y Fx Fy H.
+destruct (Req_dec (x + y) 0) as [H'|H'].
+exact H'.
+contradict H.
+now apply round_plus_neq_0.
+Qed.
+
+End Fprop_plus_zero.
+
+Section Fprop_plus_FLT.
+Variable beta : radix.
+
+Notation bpow e := (bpow beta e).
+
+Variable emin prec : Z.
+Context { prec_gt_0_ : Prec_gt_0 prec }.
+
+Theorem FLT_format_plus_small: forall x y,
+ generic_format beta (FLT_exp emin prec) x ->
+ generic_format beta (FLT_exp emin prec) y ->
+ (Rabs (x+y) <= bpow (prec+emin))%R ->
+ generic_format beta (FLT_exp emin prec) (x+y).
+Proof with auto with typeclass_instances.
+intros x y Fx Fy H.
+apply generic_format_FLT_FIX...
+rewrite Zplus_comm; assumption.
+apply generic_format_FIX_FLT, FIX_format_generic in Fx.
+apply generic_format_FIX_FLT, FIX_format_generic in Fy.
+destruct Fx as [nx H1x H2x].
+destruct Fy as [ny H1y H2y].
+apply generic_format_FIX.
+exists (Float beta (Fnum nx+Fnum ny)%Z emin).
+rewrite H1x,H1y; unfold F2R; simpl.
+rewrite H2x, H2y.
+rewrite plus_IZR; ring.
+easy.
+Qed.
+
+Variable choice : Z -> bool.
+
+Lemma FLT_plus_error_N_ex : forall x y,
+ generic_format beta (FLT_exp emin prec) x ->
+ generic_format beta (FLT_exp emin prec) y ->
+ exists eps,
+ (Rabs eps <= u_ro beta prec / (1 + u_ro beta prec))%R /\
+ round beta (FLT_exp emin prec) (Znearest choice) (x + y)
+ = ((x + y) * (1 + eps))%R.
+Proof.
+intros x y Fx Fy.
+assert (Pb := u_rod1pu_ro_pos beta prec).
+destruct (Rle_or_lt (bpow (emin + prec - 1)) (Rabs (x + y))) as [M|M].
+{ destruct (relative_error_N_FLX'_ex beta prec prec_gt_0_ choice (x + y))
+ as (d, (Bd, Hd)).
+ now exists d; split; [exact Bd|]; rewrite <- Hd; apply round_FLT_FLX. }
+exists 0%R; rewrite Rabs_R0; split; [exact Pb|]; rewrite Rplus_0_r, Rmult_1_r.
+apply round_generic; [apply valid_rnd_N|].
+apply FLT_format_plus_small; [exact Fx|exact Fy|].
+apply Rlt_le, (Rlt_le_trans _ _ _ M), bpow_le; lia.
+Qed.
+
+Lemma FLT_plus_error_N_round_ex : forall x y,
+ generic_format beta (FLT_exp emin prec) x ->
+ generic_format beta (FLT_exp emin prec) y ->
+ exists eps,
+ (Rabs eps <= u_ro beta prec)%R /\
+ (x + y
+ = round beta (FLT_exp emin prec) (Znearest choice) (x + y) * (1 + eps))%R.
+Proof.
+intros x y Fx Fy.
+now apply relative_error_N_round_ex_derive, FLT_plus_error_N_ex.
+Qed.
+
+End Fprop_plus_FLT.
+
+Section Fprop_plus_mult_ulp.
+
+Variable beta : radix.
+Notation bpow e := (bpow beta e).
+
+Variable fexp : Z -> Z.
+Context { valid_exp : Valid_exp fexp }.
+Context { monotone_exp : Monotone_exp fexp }.
+Variable rnd : R -> Z.
+Context { valid_rnd : Valid_rnd rnd }.
+
+Notation format := (generic_format beta fexp).
+Notation cexp := (cexp beta fexp).
+
+Lemma ex_shift :
+ forall x e, format x -> (e <= cexp x)%Z ->
+ exists m, (x = IZR m * bpow e)%R.
+Proof with auto with typeclass_instances.
+intros x e Fx He.
+exists (Ztrunc (scaled_mantissa beta fexp x)*Zpower beta (cexp x -e))%Z.
+rewrite Fx at 1; unfold F2R; simpl.
+rewrite mult_IZR, Rmult_assoc.
+f_equal.
+rewrite IZR_Zpower.
+2: omega.
+rewrite <- bpow_plus; f_equal; ring.
+Qed.
+
+Lemma mag_minus1 :
+ forall z, z <> 0%R ->
+ (mag beta z - 1)%Z = mag beta (z / IZR beta).
+Proof.
+intros z Hz.
+unfold Zminus.
+rewrite <- mag_mult_bpow by easy.
+now rewrite bpow_opp, bpow_1.
+Qed.
+
+Theorem round_plus_F2R :
+ forall x y, format x -> format y -> (x <> 0)%R ->
+ exists m,
+ round beta fexp rnd (x+y) = F2R (Float beta m (cexp (x / IZR beta))).
+Proof with auto with typeclass_instances.
+intros x y Fx Fy Zx.
+case (Zle_or_lt (mag beta (x/IZR beta)) (mag beta y)); intros H1.
+pose (e:=cexp (x / IZR beta)).
+destruct (ex_shift x e) as (nx, Hnx); try exact Fx.
+apply monotone_exp.
+rewrite <- (mag_minus1 x Zx); omega.
+destruct (ex_shift y e) as (ny, Hny); try assumption.
+apply monotone_exp...
+destruct (round_repr_same_exp beta fexp rnd (nx+ny) e) as (n,Hn).
+exists n.
+fold e.
+rewrite <- Hn; f_equal.
+rewrite Hnx, Hny; unfold F2R; simpl; rewrite plus_IZR; ring.
+unfold F2R; simpl.
+(* *)
+destruct (ex_shift (round beta fexp rnd (x + y)) (cexp (x/IZR beta))) as (n,Hn).
+apply generic_format_round...
+apply Z.le_trans with (cexp (x+y)).
+apply monotone_exp.
+rewrite <- mag_minus1 by easy.
+rewrite <- (mag_abs beta (x+y)).
+(* . *)
+assert (U: (Rabs (x+y) = Rabs x + Rabs y)%R \/ (y <> 0 /\ Rabs (x+y) = Rabs x - Rabs y)%R).
+assert (V: forall x y, (Rabs y <= Rabs x)%R ->
+ (Rabs (x+y) = Rabs x + Rabs y)%R \/ (y <> 0 /\ Rabs (x+y) = Rabs x - Rabs y)%R).
+clear; intros x y.
+case (Rle_or_lt 0 y); intros Hy.
+case Hy; intros Hy'.
+case (Rle_or_lt 0 x); intros Hx.
+intros _; rewrite (Rabs_pos_eq y) by easy.
+rewrite (Rabs_pos_eq x) by easy.
+left; apply Rabs_pos_eq.
+now apply Rplus_le_le_0_compat.
+rewrite (Rabs_pos_eq y) by easy.
+rewrite (Rabs_left x) by easy.
+intros H; right; split.
+now apply Rgt_not_eq.
+rewrite Rabs_left1.
+ring.
+apply Rplus_le_reg_l with (-x)%R; ring_simplify; assumption.
+intros _; left.
+now rewrite <- Hy', Rabs_R0, 2!Rplus_0_r.
+case (Rle_or_lt 0 x); intros Hx.
+rewrite (Rabs_left y) by easy.
+rewrite (Rabs_pos_eq x) by easy.
+intros H; right; split.
+now apply Rlt_not_eq.
+rewrite Rabs_pos_eq.
+ring.
+apply Rplus_le_reg_l with (-y)%R; ring_simplify; assumption.
+intros _; left.
+rewrite (Rabs_left y) by easy.
+rewrite (Rabs_left x) by easy.
+rewrite Rabs_left1.
+ring.
+lra.
+apply V; left.
+apply lt_mag with beta.
+now apply Rabs_pos_lt.
+rewrite <- mag_minus1 in H1; try assumption.
+rewrite 2!mag_abs; omega.
+(* . *)
+destruct U as [U|U].
+rewrite U; apply Z.le_trans with (mag beta x).
+omega.
+rewrite <- mag_abs.
+apply mag_le.
+now apply Rabs_pos_lt.
+apply Rplus_le_reg_l with (-Rabs x)%R; ring_simplify.
+apply Rabs_pos.
+destruct U as (U',U); rewrite U.
+rewrite <- mag_abs.
+apply mag_minus_lb.
+now apply Rabs_pos_lt.
+now apply Rabs_pos_lt.
+rewrite 2!mag_abs.
+assert (mag beta y < mag beta x - 1)%Z.
+now rewrite (mag_minus1 x Zx).
+omega.
+apply cexp_round_ge...
+apply round_plus_neq_0...
+contradict H1; apply Zle_not_lt.
+rewrite <- (mag_minus1 x Zx).
+replace y with (-x)%R.
+rewrite mag_opp; omega.
+lra.
+now exists n.
+Qed.
+
+Context {exp_not_FTZ : Exp_not_FTZ fexp}.
+
+Theorem round_plus_ge_ulp :
+ forall x y, format x -> format y ->
+ round beta fexp rnd (x+y) <> 0%R ->
+ (ulp beta fexp (x/IZR beta) <= Rabs (round beta fexp rnd (x+y)))%R.
+Proof with auto with typeclass_instances.
+intros x y Fx Fy KK.
+case (Req_dec x 0); intros Zx.
+(* *)
+rewrite Zx, Rplus_0_l.
+rewrite round_generic...
+unfold Rdiv; rewrite Rmult_0_l.
+rewrite Fy.
+unfold F2R; simpl; rewrite Rabs_mult.
+rewrite (Rabs_pos_eq (bpow _)) by apply bpow_ge_0.
+case (Z.eq_dec (Ztrunc (scaled_mantissa beta fexp y)) 0); intros Hm.
+contradict KK.
+rewrite Zx, Fy, Hm; unfold F2R; simpl.
+rewrite Rplus_0_l, Rmult_0_l.
+apply round_0...
+apply Rle_trans with (1*bpow (cexp y))%R.
+rewrite Rmult_1_l.
+rewrite <- ulp_neq_0.
+apply ulp_ge_ulp_0...
+intros K; apply Hm.
+rewrite K, scaled_mantissa_0.
+apply Ztrunc_IZR.
+apply Rmult_le_compat_r.
+apply bpow_ge_0.
+rewrite <- abs_IZR.
+apply IZR_le.
+apply (Zlt_le_succ 0).
+now apply Z.abs_pos.
+(* *)
+destruct (round_plus_F2R x y Fx Fy Zx) as (m,Hm).
+case (Z.eq_dec m 0); intros Zm.
+contradict KK.
+rewrite Hm, Zm.
+apply F2R_0.
+rewrite Hm, <- F2R_Zabs.
+rewrite ulp_neq_0.
+rewrite <- (Rmult_1_l (bpow _)).
+apply Rmult_le_compat_r.
+apply bpow_ge_0.
+apply IZR_le.
+apply (Zlt_le_succ 0).
+now apply Z.abs_pos.
+apply Rmult_integral_contrapositive_currified with (1 := Zx).
+apply Rinv_neq_0_compat.
+apply Rgt_not_eq, radix_pos.
+Qed.
+
+End Fprop_plus_mult_ulp.
+
+Section Fprop_plus_ge_ulp.
+
+Variable beta : radix.
+Notation bpow e := (bpow beta e).
+
+Variable rnd : R -> Z.
+Context { valid_rnd : Valid_rnd rnd }.
+Variable emin prec : Z.
+Context { prec_gt_0_ : Prec_gt_0 prec }.
+
+Theorem round_FLT_plus_ge :
+ forall x y e,
+ generic_format beta (FLT_exp emin prec) x -> generic_format beta (FLT_exp emin prec) y ->
+ (bpow (e + prec) <= Rabs x)%R ->
+ round beta (FLT_exp emin prec) rnd (x + y) <> 0%R ->
+ (bpow e <= Rabs (round beta (FLT_exp emin prec) rnd (x + y)))%R.
+Proof with auto with typeclass_instances.
+intros x y e Fx Fy He KK.
+assert (Zx: x <> 0%R).
+ contradict He.
+ apply Rlt_not_le; rewrite He, Rabs_R0.
+ apply bpow_gt_0.
+apply Rle_trans with (ulp beta (FLT_exp emin prec) (x/IZR beta)).
+2: apply round_plus_ge_ulp...
+rewrite ulp_neq_0.
+unfold cexp.
+rewrite <- mag_minus1; try assumption.
+unfold FLT_exp; apply bpow_le.
+apply Z.le_trans with (2:=Z.le_max_l _ _).
+destruct (mag beta x) as (n,Hn); simpl.
+assert (e + prec < n)%Z; try omega.
+apply lt_bpow with beta.
+apply Rle_lt_trans with (1:=He).
+now apply Hn.
+apply Rmult_integral_contrapositive_currified; try assumption.
+apply Rinv_neq_0_compat.
+apply Rgt_not_eq.
+apply radix_pos.
+Qed.
+
+Lemma round_FLT_plus_ge' :
+ forall x y e,
+ generic_format beta (FLT_exp emin prec) x -> generic_format beta (FLT_exp emin prec) y ->
+ (x <> 0%R -> (bpow (e+prec) <= Rabs x)%R) ->
+ (x = 0%R -> y <> 0%R -> (bpow e <= Rabs y)%R) ->
+ round beta (FLT_exp emin prec) rnd (x+y) <> 0%R ->
+ (bpow e <= Rabs (round beta (FLT_exp emin prec) rnd (x+y)))%R.
+Proof with auto with typeclass_instances.
+intros x y e Fx Fy H1 H2 H3.
+case (Req_dec x 0); intros H4.
+case (Req_dec y 0); intros H5.
+contradict H3.
+rewrite H4, H5, Rplus_0_l; apply round_0...
+rewrite H4, Rplus_0_l.
+rewrite round_generic...
+apply round_FLT_plus_ge; try easy.
+now apply H1.
+Qed.
+
+Theorem round_FLX_plus_ge :
+ forall x y e,
+ generic_format beta (FLX_exp prec) x -> generic_format beta (FLX_exp prec) y ->
+ (bpow (e+prec) <= Rabs x)%R ->
+ (round beta (FLX_exp prec) rnd (x+y) <> 0)%R ->
+ (bpow e <= Rabs (round beta (FLX_exp prec) rnd (x+y)))%R.
+Proof with auto with typeclass_instances.
+intros x y e Fx Fy He KK.
+assert (Zx: x <> 0%R).
+ contradict He.
+ apply Rlt_not_le; rewrite He, Rabs_R0.
+ apply bpow_gt_0.
+apply Rle_trans with (ulp beta (FLX_exp prec) (x/IZR beta)).
+2: apply round_plus_ge_ulp...
+rewrite ulp_neq_0.
+unfold cexp.
+rewrite <- mag_minus1 by easy.
+unfold FLX_exp; apply bpow_le.
+destruct (mag beta x) as (n,Hn); simpl.
+assert (e + prec < n)%Z; try omega.
+apply lt_bpow with beta.
+apply Rle_lt_trans with (1:=He).
+now apply Hn.
+apply Rmult_integral_contrapositive_currified; try assumption.
+apply Rinv_neq_0_compat.
+apply Rgt_not_eq.
+apply radix_pos.
+Qed.
+
+End Fprop_plus_ge_ulp.
+
+Section Fprop_plus_le_ops.
+
+Variable beta : radix.
+Variable fexp : Z -> Z.
+Context { valid_exp : Valid_exp fexp }.
+Variable choice : Z -> bool.
+
+Lemma plus_error_le_l :
+ forall x y,
+ generic_format beta fexp x -> generic_format beta fexp y ->
+ (Rabs (round beta fexp (Znearest choice) (x + y) - (x + y)) <= Rabs x)%R.
+Proof.
+intros x y Fx Fy.
+apply (Rle_trans _ (Rabs (y - (x + y)))); [now apply round_N_pt|].
+rewrite Rabs_minus_sym; right; f_equal; ring.
+Qed.
+
+Lemma plus_error_le_r :
+ forall x y,
+ generic_format beta fexp x -> generic_format beta fexp y ->
+ (Rabs (round beta fexp (Znearest choice) (x + y) - (x + y)) <= Rabs y)%R.
+Proof. now intros x y Fx Fy; rewrite Rplus_comm; apply plus_error_le_l. Qed.
+
+End Fprop_plus_le_ops.