Library Flocq.Calc.Fcalc_round
This file is part of the Flocq formalization of floating-point
arithmetic in Coq: http://flocq.gforge.inria.fr/
Copyright (C) 2010-2011 Sylvie Boldo
Copyright (C) 2010-2011 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.
Copyright (C) 2010-2011 Sylvie Boldo
Copyright (C) 2010-2011 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.
Require Import Fcore.
Require Import Fcore_digits.
Require Import Fcalc_bracket.
Require Import Fcalc_digits.
Section Fcalc_round.
Variable beta : radix.
Notation bpow e := (bpow beta e).
Section Fcalc_round_fexp.
Variable fexp : Z -> Z.
Context { valid_exp : Valid_exp fexp }.
Notation format := (generic_format beta fexp).
Relates location and rounding.
Theorem inbetween_float_round :
forall rnd choice,
( forall x m l, inbetween_int m x l -> rnd x = choice m l ) ->
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp rnd x = F2R (Float beta (choice m l) e).
Definition cond_incr (b : bool) m := if b then (m + 1)%Z else m.
Theorem inbetween_float_round_sign :
forall rnd choice,
( forall x m l, inbetween_int m (Rabs x) l ->
rnd x = cond_Zopp (Rlt_bool x 0) (choice (Rlt_bool x 0) m l) ) ->
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e (Rabs x) l ->
round beta fexp rnd x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) (choice (Rlt_bool x 0) m l)) e).
Relates location and rounding down.
Theorem inbetween_int_DN :
forall x m l,
inbetween_int m x l ->
Zfloor x = m.
Theorem inbetween_float_DN :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp Zfloor x = F2R (Float beta m e).
Definition round_sign_DN s l :=
match l with
| loc_Exact => false
| _ => s
end.
Theorem inbetween_int_DN_sign :
forall x m l,
inbetween_int m (Rabs x) l ->
Zfloor x = cond_Zopp (Rlt_bool x 0) (cond_incr (round_sign_DN (Rlt_bool x 0) l) m).
Theorem inbetween_float_DN_sign :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e (Rabs x) l ->
round beta fexp Zfloor x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) (cond_incr (round_sign_DN (Rlt_bool x 0) l) m)) e).
Relates location and rounding up.
Definition round_UP l :=
match l with
| loc_Exact => false
| _ => true
end.
Theorem inbetween_int_UP :
forall x m l,
inbetween_int m x l ->
Zceil x = cond_incr (round_UP l) m.
Theorem inbetween_float_UP :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp Zceil x = F2R (Float beta (cond_incr (round_UP l) m) e).
Definition round_sign_UP s l :=
match l with
| loc_Exact => false
| _ => negb s
end.
Theorem inbetween_int_UP_sign :
forall x m l,
inbetween_int m (Rabs x) l ->
Zceil x = cond_Zopp (Rlt_bool x 0) (cond_incr (round_sign_UP (Rlt_bool x 0) l) m).
Theorem inbetween_float_UP_sign :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e (Rabs x) l ->
round beta fexp Zceil x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) (cond_incr (round_sign_UP (Rlt_bool x 0) l) m)) e).
Relates location and rounding toward zero.
Definition round_ZR (s : bool) l :=
match l with
| loc_Exact => false
| _ => s
end.
Theorem inbetween_int_ZR :
forall x m l,
inbetween_int m x l ->
Ztrunc x = cond_incr (round_ZR (Zlt_bool m 0) l) m.
Theorem inbetween_float_ZR :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp Ztrunc x = F2R (Float beta (cond_incr (round_ZR (Zlt_bool m 0) l) m) e).
Theorem inbetween_int_ZR_sign :
forall x m l,
inbetween_int m (Rabs x) l ->
Ztrunc x = cond_Zopp (Rlt_bool x 0) m.
Theorem inbetween_float_ZR_sign :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e (Rabs x) l ->
round beta fexp Ztrunc x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) m) e).
Relates location and rounding to nearest.
Definition round_N (p : bool) l :=
match l with
| loc_Exact => false
| loc_Inexact Lt => false
| loc_Inexact Eq => p
| loc_Inexact Gt => true
end.
Theorem inbetween_int_N :
forall choice x m l,
inbetween_int m x l ->
Znearest choice x = cond_incr (round_N (choice m) l) m.
Theorem inbetween_int_N_sign :
forall choice x m l,
inbetween_int m (Rabs x) l ->
Znearest choice x = cond_Zopp (Rlt_bool x 0) (cond_incr (round_N (if Rlt_bool x 0 then negb (choice (-(m + 1))%Z) else choice m) l) m).
Relates location and rounding to nearest even.
Theorem inbetween_int_NE :
forall x m l,
inbetween_int m x l ->
ZnearestE x = cond_incr (round_N (negb (Zeven m)) l) m.
Theorem inbetween_float_NE :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp ZnearestE x = F2R (Float beta (cond_incr (round_N (negb (Zeven m)) l) m) e).
Theorem inbetween_int_NE_sign :
forall x m l,
inbetween_int m (Rabs x) l ->
ZnearestE x = cond_Zopp (Rlt_bool x 0) (cond_incr (round_N (negb (Zeven m)) l) m).
Theorem inbetween_float_NE_sign :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e (Rabs x) l ->
round beta fexp ZnearestE x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) (cond_incr (round_N (negb (Zeven m)) l) m)) e).
Relates location and rounding to nearest away.
Theorem inbetween_int_NA :
forall x m l,
inbetween_int m x l ->
ZnearestA x = cond_incr (round_N (Zle_bool 0 m) l) m.
Theorem inbetween_float_NA :
forall x m l,
let e := canonic_exp beta fexp x in
inbetween_float beta m e x l ->
round beta fexp ZnearestA x = F2R (Float beta (cond_incr (round_N (Zle_bool 0 m) l) m) e).
Theorem inbetween_int_NA_sign :
forall x m l,
inbetween_int m (Rabs x) l ->
ZnearestA x = cond_Zopp (Rlt_bool x 0) (cond_incr (round_N true l) m).
Definition truncate_aux t k :=
let '(m, e, l) := t in
let p := Zpower beta k in
(Zdiv m p, (e + k)%Z, new_location p (Zmod m p) l).
Theorem truncate_aux_comp :
forall t k1 k2,
(0 < k1)%Z ->
(0 < k2)%Z ->
truncate_aux t (k1 + k2) = truncate_aux (truncate_aux t k1) k2.
Given a triple (mantissa, exponent, position), this function
computes a triple with a canonic exponent, assuming the
original triple had enough precision.
Definition truncate t :=
let '(m, e, l) := t in
let k := (fexp (Zdigits beta m + e) - e)%Z in
if Zlt_bool 0 k then truncate_aux t k
else t.
Theorem truncate_0 :
forall e l,
let '(m', e', l') := truncate (0, e, l)%Z in
m' = Z0.
Theorem generic_format_truncate :
forall m e l,
(0 <= m)%Z ->
let '(m', e', l') := truncate (m, e, l) in
format (F2R (Float beta m' e')).
Theorem truncate_correct_format :
forall m e,
m <> Z0 ->
let x := F2R (Float beta m e) in
generic_format beta fexp x ->
(e <= fexp (Zdigits beta m + e))%Z ->
let '(m', e', l') := truncate (m, e, loc_Exact) in
x = F2R (Float beta m' e') /\ e' = canonic_exp beta fexp x.
Theorem truncate_correct_partial :
forall x m e l,
(0 < x)%R ->
inbetween_float beta m e x l ->
(e <= fexp (Zdigits beta m + e))%Z ->
let '(m', e', l') := truncate (m, e, l) in
inbetween_float beta m' e' x l' /\ e' = canonic_exp beta fexp x.
Theorem truncate_correct :
forall x m e l,
(0 <= x)%R ->
inbetween_float beta m e x l ->
(e <= fexp (Zdigits beta m + e))%Z \/ l = loc_Exact ->
let '(m', e', l') := truncate (m, e, l) in
inbetween_float beta m' e' x l' /\
(e' = canonic_exp beta fexp x \/ (l' = loc_Exact /\ format x)).
Section round_dir.
Variable rnd : R -> Z.
Context { valid_rnd : Valid_rnd rnd }.
Variable choice : Z -> location -> Z.
Hypothesis inbetween_int_valid :
forall x m l,
inbetween_int m x l ->
rnd x = choice m l.
Theorem round_any_correct :
forall x m e l,
inbetween_float beta m e x l ->
(e = canonic_exp beta fexp x \/ (l = loc_Exact /\ format x)) ->
round beta fexp rnd x = F2R (Float beta (choice m l) e).
Truncating a triple is sufficient to round a real number.
Theorem round_trunc_any_correct :
forall x m e l,
(0 <= x)%R ->
inbetween_float beta m e x l ->
(e <= fexp (Zdigits beta m + e))%Z \/ l = loc_Exact ->
round beta fexp rnd x = let '(m', e', l') := truncate (m, e, l) in F2R (Float beta (choice m' l') e').
End round_dir.
Section round_dir_sign.
Variable rnd : R -> Z.
Context { valid_rnd : Valid_rnd rnd }.
Variable choice : bool -> Z -> location -> Z.
Hypothesis inbetween_int_valid :
forall x m l,
inbetween_int m (Rabs x) l ->
rnd x = cond_Zopp (Rlt_bool x 0) (choice (Rlt_bool x 0) m l).
Theorem round_sign_any_correct :
forall x m e l,
inbetween_float beta m e (Rabs x) l ->
(e = canonic_exp beta fexp x \/ (l = loc_Exact /\ format x)) ->
round beta fexp rnd x = F2R (Float beta (cond_Zopp (Rlt_bool x 0) (choice (Rlt_bool x 0) m l)) e).
Truncating a triple is sufficient to round a real number.
Theorem round_trunc_sign_any_correct :
forall x m e l,
inbetween_float beta m e (Rabs x) l ->
(e <= fexp (Zdigits beta m + e))%Z \/ l = loc_Exact ->
round beta fexp rnd x = let '(m', e', l') := truncate (m, e, l) in F2R (Float beta (cond_Zopp (Rlt_bool x 0) (choice (Rlt_bool x 0) m' l')) e').
End round_dir_sign.
Definition round_DN_correct :=
round_any_correct _ (fun m _ => m) inbetween_int_DN.
Definition round_trunc_DN_correct :=
round_trunc_any_correct _ (fun m _ => m) inbetween_int_DN.
Definition round_sign_DN_correct :=
round_sign_any_correct _ (fun s m l => cond_incr (round_sign_DN s l) m) inbetween_int_DN_sign.
Definition round_trunc_sign_DN_correct :=
round_trunc_sign_any_correct _ (fun s m l => cond_incr (round_sign_DN s l) m) inbetween_int_DN_sign.
Definition round_UP_correct :=
round_any_correct _ (fun m l => cond_incr (round_UP l) m) inbetween_int_UP.
Definition round_trunc_UP_correct :=
round_trunc_any_correct _ (fun m l => cond_incr (round_UP l) m) inbetween_int_UP.
Definition round_sign_UP_correct :=
round_sign_any_correct _ (fun s m l => cond_incr (round_sign_UP s l) m) inbetween_int_UP_sign.
Definition round_trunc_sign_UP_correct :=
round_trunc_sign_any_correct _ (fun s m l => cond_incr (round_sign_UP s l) m) inbetween_int_UP_sign.
Definition round_ZR_correct :=
round_any_correct _ (fun m l => cond_incr (round_ZR (Zlt_bool m 0) l) m) inbetween_int_ZR.
Definition round_trunc_ZR_correct :=
round_trunc_any_correct _ (fun m l => cond_incr (round_ZR (Zlt_bool m 0) l) m) inbetween_int_ZR.
Definition round_sign_ZR_correct :=
round_sign_any_correct _ (fun s m l => m) inbetween_int_ZR_sign.
Definition round_trunc_sign_ZR_correct :=
round_trunc_sign_any_correct _ (fun s m l => m) inbetween_int_ZR_sign.
Definition round_NE_correct :=
round_any_correct _ (fun m l => cond_incr (round_N (negb (Zeven m)) l) m) inbetween_int_NE.
Definition round_trunc_NE_correct :=
round_trunc_any_correct _ (fun m l => cond_incr (round_N (negb (Zeven m)) l) m) inbetween_int_NE.
Definition round_sign_NE_correct :=
round_sign_any_correct _ (fun s m l => cond_incr (round_N (negb (Zeven m)) l) m) inbetween_int_NE_sign.
Definition round_trunc_sign_NE_correct :=
round_trunc_sign_any_correct _ (fun s m l => cond_incr (round_N (negb (Zeven m)) l) m) inbetween_int_NE_sign.
Definition round_NA_correct :=
round_any_correct _ (fun m l => cond_incr (round_N (Zle_bool 0 m) l) m) inbetween_int_NA.
Definition round_trunc_NA_correct :=
round_trunc_any_correct _ (fun m l => cond_incr (round_N (Zle_bool 0 m) l) m) inbetween_int_NA.
Definition round_sign_NA_correct :=
round_sign_any_correct _ (fun s m l => cond_incr (round_N true l) m) inbetween_int_NA_sign.
Definition round_trunc_sign_NA_correct :=
round_trunc_sign_any_correct _ (fun s m l => cond_incr (round_N true l) m) inbetween_int_NA_sign.
End Fcalc_round_fexp.
Specialization of truncate for FIX formats.
Variable emin : Z.
Definition truncate_FIX t :=
let '(m, e, l) := t in
let k := (emin - e)%Z in
if Zlt_bool 0 k then
let p := Zpower beta k in
(Zdiv m p, (e + k)%Z, new_location p (Zmod m p) l)
else t.
Theorem truncate_FIX_correct :
forall x m e l,
inbetween_float beta m e x l ->
(e <= emin)%Z \/ l = loc_Exact ->
let '(m', e', l') := truncate_FIX (m, e, l) in
inbetween_float beta m' e' x l' /\
(e' = canonic_exp beta (FIX_exp emin) x \/ (l' = loc_Exact /\ generic_format beta (FIX_exp emin) x)).
End Fcalc_round.