Library Interval.Float.Specific_ops

This file is part of the Coq.Interval library for proving bounds of real-valued expressions in Coq: https://coqinterval.gitlabpages.inria.fr/
Copyright (C) 2007-2016, Inria
This library is governed by the CeCILL-C license under French law and abiding by the rules of distribution of free software. You can use, modify and/or redistribute the library under the terms of the CeCILL-C license as circulated by CEA, CNRS and Inria at the following URL: http://www.cecill.info/
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the library's author, the holder of the economic rights, and the successive licensors have only limited liability. See the COPYING file for more details.

From Coq Require Import ZArith Reals Lia Bool Psatz.
From Flocq Require Import Zaux Raux Digits Bracket.
From mathcomp.ssreflect Require Import ssrbool.

Require Import Xreal.
Require Import Basic.
Require Import Generic.
Require Import Generic_proof.
Require Import Sig.
Require Import Specific_sig.

Inductive s_float (smantissa_type exponent_type : Type) : Type :=
  | Fnan : s_float smantissa_type exponent_type
  | Float : smantissa_type exponent_type s_float smantissa_type exponent_type.

Arguments Fnan {smantissa_type exponent_type}.
Arguments Float {smantissa_type exponent_type} _ _.

Module SpecificFloat (Carrier : FloatCarrier) <: FloatOps.

Import Carrier.

Definition sensible_format := match radix_val radix with Zpos (xO _) ⇒ true | _false end.

Definition radix := radix.

Definition type := s_float smantissa_type exponent_type.

Definition toF (x : type) : float radix :=
  match x with
  | FnanBasic.Fnan
  | Float m e
    match mantissa_sign m with
    | MzeroBasic.Fzero
    | Mnumber s pBasic.Float s (MtoP p) (EtoZ e)
    end
  end.

Definition toX (x : type) := FtoX (toF x).
Definition toR (x : type) := proj_val (toX x).
Definition convert (x : type) := FtoX (toF x).

Definition fromF (f : Basic.float radix) :=
  match f with
  | Basic.FnanFnan
  | Basic.FzeroFloat mantissa_zero exponent_zero
  | Basic.Float false m eFloat (ZtoM (Zpos m)) (ZtoE e)
  | Basic.Float true m eFloat (ZtoM (Zneg m)) (ZtoE e)
  end.

Definition precision := exponent_type.
Definition sfactor := exponent_type.
Definition prec p := match EtoZ p with Zpos qq | _xH end.
Definition ZtoS := ZtoE.
Definition StoZ := EtoZ.
Definition PtoP n := ZtoE (Zpos n).
Definition incr_prec x y := exponent_add x (ZtoE (Zpos y)).

Definition sm1 := ZtoE (-1).

Definition zero := Float mantissa_zero exponent_zero.
Definition nan := @Fnan smantissa_type exponent_type.

Lemma zero_correct :
  toX zero = Xreal 0.

Definition mag (x : type) :=
  match x with
  | Fnanexponent_zero
  | Float m e
    match mantissa_sign m with
    | Mzeroe
    | Mnumber _ mexponent_add e (mantissa_digits m)
    end
  end.

Definition classify (f : type) :=
  match f with FnanSig.Fnan | _Sig.Freal end.

Definition nan_correct := refl_equal Sig.Fnan.

Definition real (f : type) := match f with Fnanfalse | _true end.

Definition is_nan (f : type) := match f with Fnantrue | _false end.

Lemma classify_correct :
   f, real f = match classify f with Frealtrue | _false end.

Lemma real_correct :
   f, real f = match toX f with Xnanfalse | _true end.

Lemma is_nan_correct :
   f, is_nan f = match classify f with Sig.Fnantrue | _false end.

Definition valid_ub (_ : type) := true.
Definition valid_lb (_ : type) := true.

Lemma valid_lb_correct :
   f, valid_lb f = match classify f with Fpinftyfalse | _true end.

Lemma valid_ub_correct :
   f, valid_ub f = match classify f with Fminftyfalse | _true end.

Definition fromZ n := Float (ZtoM n) exponent_zero.

Lemma fromZ_correct' :
   n, toX (fromZ n) = Xreal (IZR n).

Lemma fromZ_correct :
   n,
  (Z.abs n 256)%Z
  toX (fromZ n) = Xreal (IZR n).

Definition fromZ_DN (p : precision) := fromZ.

Lemma fromZ_DN_correct :
   p n,
  valid_lb (fromZ_DN p n) = true le_lower (toX (fromZ_DN p n)) (Xreal (IZR n)).

Definition fromZ_UP (p : precision) := fromZ.

Lemma fromZ_UP_correct :
   p n,
  valid_ub (fromZ_UP p n) = true le_upper (Xreal (IZR n)) (toX (fromZ_UP p n)).

Lemma match_helper_1 :
   A B y2, f : A B,
   x y1,
  f (match mantissa_sign x with Mzeroy1 | Mnumber s py2 s p end) =
  match mantissa_sign x with Mzerof y1 | Mnumber s pf (y2 s p) end.

Definition float_aux s m e : type :=
  Float ((if s : bool then mantissa_neg else mantissa_pos) m) e.

Lemma toF_float :
   s p e, valid_mantissa p
  toF (float_aux s p e) = Basic.Float s (MtoP p) (EtoZ e).

Lemma toX_Float :
   m e, toX (Float m e) = Xreal (toR (Float m e)).


Definition neg (f : type) :=
  match f with
  | Float m e
    match mantissa_sign m with
    | Mzerof
    | Mnumber s pFloat ((if s then mantissa_pos else mantissa_neg) p) e
    end
  | _f
  end.

Lemma neg_correct :
   x,
  match classify x with
  | FrealtoX (neg x) = Xneg (toX x)
  | Sig.Fnanclassify (neg x) = Sig.Fnan
  | Fminftyclassify (neg x) = Fpinfty
  | Fpinftyclassify (neg x) = Fminfty
  end.


Definition abs (f : type) :=
  match f with
  | Float m e
    match mantissa_sign m with
    | Mzerof
    | Mnumber _ pFloat (mantissa_pos p) e
    end
  | _f
  end.

Lemma abs_correct :
   x, toX (abs x) = Xabs (toX x) (valid_ub (abs x) = true).


Definition scale (f : type) d :=
  match f with
  | Float m eFloat m (exponent_add e d)
  | _f
  end.


Definition scale2 (f : type) d :=
  match f with
  | Float m e
    match mantissa_sign m with
    | Mzerof
    | Mnumber s p
      match mantissa_scale2 p d with
      | (p2, d2)float_aux s p2 (exponent_add e d2)
      end
    end
  | _f
  end.

Lemma scale2_correct :
   x d, sensible_format = true
  toX (scale2 x d) = Xmul (toX x) (Xreal (bpow radix2 (StoZ d))).


Definition pow2_UP (p : precision) e :=
  if sensible_format then scale2 (Float (mantissa_pos mantissa_one) exponent_zero) e else Fnan.

Lemma pow2_UP_correct :
   p s, (valid_ub (pow2_UP p s) = true
              le_upper (Xscale radix2 (Xreal 1) (StoZ s)) (toX (pow2_UP p s))).

Lemma ZtoS_correct:
   p z,
  (z StoZ (ZtoS z))%Z toX (pow2_UP p (ZtoS z)) = Xnan.


Lemma mag_correct :
   f, (Rabs (toR f) < bpow radix (StoZ (mag f)))%R.


Definition div2 (f : type) := scale2 f sm1.

Lemma div2_correct :
   x, sensible_format = true
  (1 / 256 Rabs (toR x))%R
  toX (div2 x) = Xdiv (toX x) (Xreal 2).


Definition cmp_aux1 m1 m2 :=
  match mantissa_cmp m1 m2 with
  | EqXeq
  | LtXlt
  | GtXgt
  end.

Definition cmp_aux2 m1 e1 m2 e2 :=
  let d1 := mantissa_digits m1 in
  let d2 := mantissa_digits m2 in
  match exponent_cmp (exponent_add e1 d1) (exponent_add e2 d2) with
  | LtXlt
  | GtXgt
  | Eq
    let nb := exponent_sub e1 e2 in
    match exponent_cmp nb exponent_zero with
    | Gtcmp_aux1 (mantissa_shl m1 nb) m2
    | Ltcmp_aux1 m1 (mantissa_shl m2 (exponent_neg nb))
    | Eqcmp_aux1 m1 m2
    end
  end.

Lemma cmp_aux2_correct :
   m1 e1 m2 e2,
  valid_mantissa m1 valid_mantissa m2
  cmp_aux2 m1 e1 m2 e2 = Fcmp_aux2 radix (MtoP m1) (EtoZ e1) (MtoP m2) (EtoZ e2).

Definition cmp (f1 f2 : type) :=
  match f1, f2 with
  | Fnan, _Xund
  | _, FnanXund
  | Float m1 e1, Float m2 e2
    match mantissa_sign m1, mantissa_sign m2 with
    | Mzero, MzeroXeq
    | Mzero, Mnumber true _Xgt
    | Mzero, Mnumber false _Xlt
    | Mnumber true _, MzeroXlt
    | Mnumber false _, MzeroXgt
    | Mnumber true _, Mnumber false _Xlt
    | Mnumber false _, Mnumber true _Xgt
    | Mnumber true p1, Mnumber true p2cmp_aux2 p2 e2 p1 e1
    | Mnumber false p1, Mnumber false p2cmp_aux2 p1 e1 p2 e2
    end
  end.

Lemma cmp_correct :
   x y,
  cmp x y =
  match classify x, classify y with
  | Sig.Fnan, _ | _, Sig.FnanXund
  | Fminfty, FminftyXeq
  | Fminfty, _Xlt
  | _, FminftyXgt
  | Fpinfty, FpinftyXeq
  | _, FpinftyXlt
  | Fpinfty, _Xgt
  | Freal, FrealXcmp (toX x) (toX y)
  end.


Definition min x y :=
  match cmp x y with
  | Xltx
  | Xeqx
  | Xgty
  | Xundnan
  end.

Lemma min_correct :
   x y,
  match classify x, classify y with
  | Sig.Fnan, _ | _, Sig.Fnanclassify (min x y) = Sig.Fnan
  | Fminfty, _ | _, Fminftyclassify (min x y) = Fminfty
  | Fpinfty, _min x y = y
  | _, Fpinftymin x y = x
  | Freal, FrealtoX (min x y) = Xmin (toX x) (toX y)
  end.


Definition max x y :=
  match cmp x y with
  | Xlty
  | Xeqy
  | Xgtx
  | Xundnan
  end.

Lemma max_correct :
   x y,
  match classify x, classify y with
  | Sig.Fnan, _ | _, Sig.Fnanclassify (max x y) = Sig.Fnan
  | Fpinfty, _ | _, Fpinftyclassify (max x y) = Fpinfty
  | Fminfty, _max x y = y
  | _, Fminftymax x y = x
  | Freal, FrealtoX (max x y) = Xmax (toX x) (toX y)
  end.


Definition adjust_mantissa mode m pos sign :=
  if need_change mode (mantissa_even m) pos sign then mantissa_add m mantissa_one else m.

Lemma adjust_mantissa_correct :
   mode m pos sign,
  valid_mantissa m
  MtoP (adjust_mantissa mode m pos sign) = Generic.adjust_mantissa mode (MtoP m) pos sign
  valid_mantissa (adjust_mantissa mode m pos sign).

Definition round_aux mode prec sign m1 e1 pos :=
  let prec := match exponent_cmp prec exponent_zero with Gtprec | _exponent_one end in
  let nb := exponent_sub (mantissa_digits m1) prec in
  let e2 := exponent_add e1 nb in
  match exponent_cmp nb exponent_zero with
  | Gt
    let (m2, pos2) := mantissa_shr m1 nb pos in
    float_aux sign (adjust_mantissa mode m2 pos2 sign) e2
  | Eqfloat_aux sign (adjust_mantissa mode m1 pos sign) e1
  | Ltfloat_aux sign m1 e1
  end.

Lemma round_aux_correct :
   mode p sign m1 e1 pos,
  valid_mantissa m1
  FtoX (toF (round_aux mode p sign m1 e1 pos)) =
  FtoX (Fround_at_prec mode (prec p) (@Generic.Ufloat radix sign (MtoP m1) (EtoZ e1) pos)).

Definition round_at_exp_aux mode e2 sign m1 e1 pos :=
  let nb := exponent_sub e2 e1 in
  match exponent_cmp nb exponent_zero with
  | Gt
    match exponent_cmp (mantissa_digits m1) nb with
    | Gt
      let (m2, pos2) := mantissa_shr m1 nb pos in
      float_aux sign (adjust_mantissa mode m2 pos2 sign) e2
    | Eq
      let pos2 := mantissa_shrp m1 nb pos in
      if need_change_zero mode pos2 sign then
        float_aux sign mantissa_one e2
      else zero
    | Lt
      let pos2 := match pos with pos_Eqpos_Eq | _pos_Lo end in
      if need_change_zero mode pos_Lo sign then
        float_aux sign mantissa_one e2
      else zero
    end
  | Eqfloat_aux sign (adjust_mantissa mode m1 pos sign) e1
  | Lt
    float_aux sign m1 e1
  end.

Lemma toF_zero : toF zero = Fzero.

Lemma round_at_exp_aux_correct :
   mode e2 sign m1 e1 pos,
  valid_mantissa m1
  FtoX (toF (round_at_exp_aux mode e2 sign m1 e1 pos)) =
  FtoX (Fround_at_exp mode (EtoZ e2) (@Generic.Ufloat radix sign (MtoP m1) (EtoZ e1) pos)).


Definition mul mode prec (x y : type) :=
  match x, y with
  | Fnan, _x
  | _, Fnany
  | Float mx ex, Float my ey
    match mantissa_sign mx, mantissa_sign my with
    | Mzero, _x
    | _, Mzeroy
    | Mnumber sx mx, Mnumber sy my
      round_aux mode prec (xorb sx sy) (mantissa_mul mx my) (exponent_add ex ey) pos_Eq
    end
  end.

Lemma mul_correct :
   mode p x y,
  toX (mul mode p x y) = Xround radix mode (prec p) (Xmul (toX x) (toX y)).

Definition mul_UP := mul rnd_UP.

Definition is_non_neg x :=
  valid_ub x = true
   match toX x with XnanTrue | Xreal r ⇒ (0 r)%R end.

Definition is_non_neg' x :=
  match toX x with Xnanvalid_ub x = true | Xreal r ⇒ (0 r)%R end.

Definition is_pos x :=
  valid_ub x = true
   match toX x with XnanTrue | Xreal r ⇒ (0 < r)%R end.

Definition is_non_pos x :=
  valid_lb x = true
   match toX x with XnanTrue | Xreal r ⇒ (r 0)%R end.

Definition is_non_pos' x :=
  match toX x with Xnanvalid_lb x = true | Xreal r ⇒ (r 0)%R end.

Definition is_neg x :=
  valid_lb x = true
   match toX x with XnanTrue | Xreal r ⇒ (r < 0)%R end.

Definition is_non_neg_real x :=
  match toX x with XnanFalse | Xreal r ⇒ (0 r)%R end.

Definition is_pos_real x :=
  match toX x with XnanFalse | Xreal r ⇒ (0 < r)%R end.

Definition is_non_pos_real x :=
  match toX x with XnanFalse | Xreal r ⇒ (r 0)%R end.

Definition is_neg_real x :=
  match toX x with XnanFalse | Xreal r ⇒ (r < 0)%R end.

Lemma mul_UP_correct :
   p x y,
  ((is_non_neg' x is_non_neg' y)
   (is_non_pos' x is_non_pos' y)
   (is_non_pos_real x is_non_neg_real y)
   (is_non_neg_real x is_non_pos_real y))
  valid_ub (mul_UP p x y) = true
  le_upper (Xmul (toX x) (toX y)) (toX (mul_UP p x y)).

Definition mul_DN := mul rnd_DN.

Lemma mul_DN_correct :
   p x y,
  ((is_non_neg_real x is_non_neg_real y)
   (is_non_pos_real x is_non_pos_real y)
   (is_non_neg' x is_non_pos' y)
   (is_non_pos' x is_non_neg' y))
  (valid_lb (mul_DN p x y) = true
  le_lower (toX (mul_DN p x y)) (Xmul (toX x) (toX y))).


Definition add_exact_aux1 sx sy mx my e :=
  if eqb sx sy then
    float_aux sx (mantissa_add mx my) e
  else
    match mantissa_cmp mx my with
    | Eqzero
    | Gtfloat_aux sx (mantissa_sub mx my) e
    | Ltfloat_aux sy (mantissa_sub my mx) e
    end.

Definition add_exact_aux2 sx sy mx my ex ey :=
  let nb := exponent_sub ex ey in
  match exponent_cmp nb exponent_zero with
  | Gtadd_exact_aux1 sx sy (mantissa_shl mx nb) my ey
  | Ltadd_exact_aux1 sx sy mx (mantissa_shl my (exponent_neg nb)) ex
  | Eqadd_exact_aux1 sx sy mx my ex
  end.

Definition add_exact (x y : type) :=
  match x, y with
  | Fnan, _x
  | _, Fnany
  | Float mx ex, Float my ey
    match mantissa_sign mx, mantissa_sign my with
    | Mzero, _y
    | _, Mzerox
    | Mnumber sx mx, Mnumber sy my
      add_exact_aux2 sx sy mx my ex ey
    end
  end.

Lemma add_exact_aux_correct :
   sx mx ex sy my ey,
  valid_mantissa mx valid_mantissa my
  FtoX (toF (add_exact_aux2 sx sy mx my ex ey)) =
  FtoX (Fround_none (Fadd_slow_aux2 radix sx sy (MtoP mx) (MtoP my) (EtoZ ex) (EtoZ ey) pos_Eq)).

Lemma add_exact_correct :
   x y, toX (add_exact x y) = Xadd (toX x) (toX y).


Definition add_slow_aux1 mode prec sx sy mx my e :=
  if eqb sx sy then
    round_aux mode prec sx (mantissa_add mx my) e pos_Eq
  else
    match mantissa_cmp mx my with
    | Eqzero
    | Gtround_aux mode prec sx (mantissa_sub mx my) e pos_Eq
    | Ltround_aux mode prec sy (mantissa_sub my mx) e pos_Eq
    end.

Lemma add_slow_aux1_correct :
   mode p sx sy mx my e,
  valid_mantissa mx
  valid_mantissa my
  FtoX (toF (add_slow_aux1 mode p sx sy mx my e)) =
  FtoX (Fround_at_prec mode (prec p) (Fadd_slow_aux1 radix sx sy (MtoP mx) (MtoP my) (EtoZ e) pos_Eq)).

Definition add_slow_aux2 mode prec sx sy mx my ex ey :=
  let nb := exponent_sub ex ey in
  match exponent_cmp nb exponent_zero with
  | Gtadd_slow_aux1 mode prec sx sy (mantissa_shl mx nb) my ey
  | Ltadd_slow_aux1 mode prec sx sy mx (mantissa_shl my (exponent_neg nb)) ex
  | Eqadd_slow_aux1 mode prec sx sy mx my ex
  end.

Lemma add_slow_aux2_correct :
   mode p sx sy mx my ex ey,
  valid_mantissa mx
  valid_mantissa my
  FtoX (toF (add_slow_aux2 mode p sx sy mx my ex ey)) =
  FtoX (Fround_at_prec mode (prec p) (Fadd_slow_aux2 radix sx sy (MtoP mx) (MtoP my) (EtoZ ex) (EtoZ ey) pos_Eq)).

Definition add_slow mode prec (x y : type) :=
  match x, y with
  | Fnan, _x
  | _, Fnany
  | Float mx ex, Float my ey
    match mantissa_sign mx, mantissa_sign my with
    | Mzero, Mzerox
    | Mzero, Mnumber sy pyround_aux mode prec sy py ey pos_Eq
    | Mnumber sx px, Mzeroround_aux mode prec sx px ex pos_Eq
    | Mnumber sx px, Mnumber sy py
      add_slow_aux2 mode prec sx sy px py ex ey
    end
  end.

Lemma add_slow_correct :
   mode p x y,
  toX (add_slow mode p x y) = Xround radix mode (prec p) (Xadd (toX x) (toX y)).

Definition add_UP := add_slow rnd_UP.

Lemma add_UP_correct :
   p x y, valid_ub x = true valid_ub y = true
     (valid_ub (add_UP p x y) = true
        le_upper (Xadd (toX x) (toX y)) (toX (add_UP p x y))).

Definition add_DN := add_slow rnd_DN.

Lemma add_DN_correct :
   p x y, valid_lb x = true valid_lb y = true
     (valid_lb (add_DN p x y) = true
        le_lower (toX (add_DN p x y)) (Xadd (toX x) (toX y))).


Definition sub_UP prec (x y : type) := add_UP prec x (neg y).

Lemma sub_UP_correct :
   p x y, valid_ub x = true valid_lb y = true
     (valid_ub (sub_UP p x y) = true
        le_upper (Xsub (toX x) (toX y)) (toX (sub_UP p x y))).

Definition sub_DN prec (x y : type) := add_DN prec x (neg y).

Lemma sub_DN_correct :
   p x y, valid_lb x = true valid_ub y = true
     (valid_lb (sub_DN p x y) = true
        le_lower (toX (sub_DN p x y)) (Xsub (toX x) (toX y))).


Definition div_aux mode prec s mx my e :=
  let (q, pos) := mantissa_div mx my in
  round_aux mode prec s q e pos.

Definition div mode prec (x y : type) :=
  match x, y with
  | Fnan, _x
  | _, Fnany
  | Float mx ex, Float my ey
    let prec := match exponent_cmp prec exponent_zero with Gtprec | _exponent_one end in
    match mantissa_sign mx, mantissa_sign my with
    | _, MzeroFnan
    | Mzero, _x
    | Mnumber sx px, Mnumber sy py
      let dx := mantissa_digits px in
      let dy := mantissa_digits py in
      let e := exponent_sub ex ey in
      let nb := exponent_sub (exponent_add dy prec) dx in
      match exponent_cmp nb exponent_zero with
      | Gt
        div_aux mode prec (xorb sx sy) (mantissa_shl px nb) py (exponent_sub e nb)
      | _div_aux mode prec (xorb sx sy) px py e
      end
    end
  end.

Theorem div_correct :
   mode p x y,
  toX (div mode p x y) = Xround radix mode (prec p) (Xdiv (toX x) (toX y)).

Definition div_UP := div rnd_UP.

Definition is_real_ub x :=
  match toX x with Xnanvalid_ub x = true | _True end.

Definition is_real_lb x :=
  match toX x with Xnanvalid_lb x = true | _True end.

Lemma div_UP_correct :
   p x y,
  ((is_real_ub x is_pos_real y)
   (is_real_lb x is_neg_real y))
  valid_ub (div_UP p x y) = true
  le_upper (Xdiv (toX x) (toX y)) (toX (div_UP p x y)).

Definition div_DN := div rnd_DN.

Lemma div_DN_correct :
   p x y,
  ((is_real_ub x is_neg_real y)
   (is_real_lb x is_pos_real y))
  valid_lb (div_DN p x y) = true
  le_lower (toX (div_DN p x y)) (Xdiv (toX x) (toX y)).


Definition sqrt mode prec (f : type) :=
  match f with
  | Fnanf
  | Float m e
    match mantissa_sign m with
    | Mzerof
    | Mnumber true _Fnan
    | Mnumber false p
      let d := mantissa_digits p in
      let prec := match exponent_cmp prec exponent_zero with Gtprec | _exponent_one end in
      let s := exponent_sub (exponent_add prec prec) d in
      let s := match exponent_cmp s exponent_zero with Gts | _exponent_zero end in
      let (e', r) := exponent_div2_floor (exponent_sub e s) in
      let s := if r then exponent_add s exponent_one else s in
      let m := match exponent_cmp s exponent_zero with Gtmantissa_shl p s | _p end in
      let (m', pos) := mantissa_sqrt m in
      round_aux mode prec false m' e' pos
    end
  end.

Lemma sqrt_correct :
   mode p x,
  toX (sqrt mode p x) = Xround radix mode (prec p) (Xsqrt_nan (toX x)).

Definition sqrt_UP := sqrt rnd_UP.

Lemma sqrt_UP_correct :
   p x,
  valid_ub (sqrt_UP p x) = true
   le_upper (Xsqrt (toX x)) (toX (sqrt_UP p x)).

Definition sqrt_DN := sqrt rnd_DN.

Lemma sqrt_DN_correct :
   p x,
    valid_lb x = true
     (valid_lb (sqrt_DN p x) = true
         le_lower (toX (sqrt_DN p x)) (Xsqrt (toX x))).


Definition nearbyint mode (f : type) :=
  match f with
  | Fnanf
  | Float m e
    match mantissa_sign m with
    | Mnumber s mround_at_exp_aux mode exponent_zero s m e pos_Eq
    | Mzerozero
    end
  end.

Definition nearbyint_UP := nearbyint.

Definition nearbyint_DN := nearbyint.

Lemma nearbyint_correct :
   mode x,
  toX (nearbyint mode x) = Xnearbyint mode (toX x).

Lemma nearbyint_UP_correct :
   mode x,
  valid_ub (nearbyint_UP mode x) = true
   le_upper (Xnearbyint mode (toX x)) (toX (nearbyint_UP mode x)).

Lemma nearbyint_DN_correct :
   mode x,
  valid_lb (nearbyint_DN mode x) = true
   le_lower (toX (nearbyint_DN mode x)) (Xnearbyint mode (toX x)).


Definition midpoint (x y : type) := scale2 (add_exact x y) sm1.

Lemma midpoint_correct :
   x y,
  sensible_format = true
  real x = true real y = true (toR x toR y)%R
   real (midpoint x y) = true (toR x toR (midpoint x y) toR y)%R.

End SpecificFloat.