Library Interval.Float.Specific_stdz

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 Psatz Bool.
From Flocq Require Import Zaux Raux.

Require Import Basic.
Require Import Generic.
Require Import Generic_proof.
Require Import Specific_sig.

Module StdZRadix2 <: FloatCarrier.

Definition radix := radix2.
Definition radix_correct := refl_equal Lt.
Definition smantissa_type := Z.
Definition mantissa_type := positive.
Definition exponent_type := Z.

Definition MtoP := fun (m : positive) ⇒ m.
Definition PtoM := fun (m : positive) ⇒ m.
Definition MtoZ := fun (m : Z) ⇒ m.
Definition ZtoM := fun (m : Z) ⇒ m.
Definition EtoZ := fun (e : Z) ⇒ e.
Definition ZtoE := fun (e : Z) ⇒ e.

Definition exponent_zero := Z0.
Definition exponent_one := Zpos xH.
Definition exponent_neg := Z.opp.
Definition exponent_add := Zplus.
Definition exponent_sub := Zminus.
Definition exponent_cmp := Z.compare.
Definition mantissa_zero := Z0.
Definition mantissa_one := xH.
Definition mantissa_add := Pplus.
Definition mantissa_sub := Pminus.
Definition mantissa_mul := Pmult.
Definition mantissa_cmp x y := Pcompare x y Eq.
Definition mantissa_pos := Zpos.
Definition mantissa_neg := Zneg.

Definition valid_mantissa := fun (m : positive) ⇒ True.

Definition mantissa_sign m :=
  match m with
  | Zneg pMnumber true p
  | Z0Mzero
  | Zpos pMnumber false p
  end.

Definition mantissa_even m :=
  match m with
  | xO _true
  | _false
  end.

Definition mantissa_shl m d :=
  match d with Zpos nbiter_pos (fun xxO x) nb m | _xH end.

Definition mantissa_scale2 (m : mantissa_type) (d : exponent_type) := (m, d).

Fixpoint digits_aux m nb { struct m } :=
  match m with
  | xHnb
  | xO pdigits_aux p (Pos.succ nb)
  | xI pdigits_aux p (Pos.succ nb)
  end.

Definition mantissa_digits m := Zpos (digits_aux m xH).

Definition mantissa_split_div m d pos :=
  match Zfast_div_eucl (Zpos m) (Zpos d) with
  | (Zpos q, r)(q, adjust_pos r d pos)
  | _(xH, pos_Eq)
  end.

Definition mantissa_shr_aux v :=
  match v with
  | (xO p, pos_Eq)(p, pos_Eq)
  | (xO p, _)(p, pos_Lo)
  | (xI p, pos_Eq)(p, pos_Mi)
  | (xI p, _)(p, pos_Up)
  | _(xH, pos_Eq)
  end.

Definition mantissa_shr m d pos :=
  match d with
  | Zpos nb
    iter_pos mantissa_shr_aux nb (m, pos)
  | _(xH, pos_Eq)
  end.

Fixpoint mantissa_shrp_aux m d :=
  match m with
  | xO m1
      if (d =? 1)%positive then pos_Up else mantissa_shrp_aux m1 (Pos.pred d)
  | xI m1pos_Up
  | xH
      if (d =? 1)%positive then pos_Mi else pos_Up
  end.

Lemma mantissa_shrp_aux_correct m d :
   mantissa_shrp_aux m (Pos.succ d) =
   match (m ?= shift radix 1 d)%positive with
        | Eqpos_Mi
        | _pos_Up
        end.

Definition mantissa_shrp m d pos :=
  match pos with
  | pos_Eqmantissa_shrp_aux m (Z.to_pos d)
  | _pos_Up
  end.

Definition mantissa_div := fun m dmantissa_split_div m d pos_Eq.

Definition exponent_div2_floor n :=
  match n with
  | Z0(Z0, false)
  | Zpos xH(Z0, true)
  | Zneg xH(Zneg xH, true)
  | Zpos (xO p) ⇒ (Zpos p, false)
  | Zneg (xO p) ⇒ (Zneg p, false)
  | Zpos (xI p) ⇒ (Zpos p, true)
  | Zneg (xI p) ⇒ (Zneg (Pos.succ p), true)
  end.

Definition mantissa_sqrt m :=
  match Z.sqrtrem (Zpos m) with
  | (Zpos s, r)
    let pos :=
      match r with
      | Z0pos_Eq
      | Zpos r
        match Pos.compare r s with
        | Gtpos_Up
        | _pos_Lo
        end
      | Zneg _pos_Eq
      end in
    (s, pos)
  | _(xH, pos_Eq)
  end.

Definition PtoM_correct := fun x : positiverefl_equal x.
Definition ZtoM_correct := fun x : Zrefl_equal x.
Definition ZtoE_correct := fun x : Zrefl_equal x.

Definition exponent_zero_correct := refl_equal Z0.
Definition exponent_one_correct := refl_equal 1%Z.
Definition exponent_neg_correct := fun xrefl_equal (- EtoZ x)%Z.
Definition exponent_add_correct := fun x yrefl_equal (EtoZ x + EtoZ y)%Z.
Definition exponent_sub_correct := fun x yrefl_equal (EtoZ x - EtoZ y)%Z.
Definition exponent_cmp_correct := fun x yrefl_equal (EtoZ x ?= EtoZ y)%Z.

Lemma exponent_div2_floor_correct :
   e, let (e',b) := exponent_div2_floor e in
  EtoZ e = (2 × EtoZ e' + if b then 1 else 0)%Z.

Definition mantissa_zero_correct := refl_equal Z0.
Definition mantissa_pos_correct :=
  fun (x : positive) (_ : True) ⇒ refl_equal (Zpos x).
Definition mantissa_neg_correct :=
  fun (x : positive) (_ : True) ⇒ refl_equal (Zneg x).
Definition mantissa_one_correct := conj (refl_equal xH) I.
Definition mantissa_add_correct :=
  fun x y (_ _ : True) ⇒ conj (refl_equal (MtoP x + MtoP y)%positive) I.
Definition mantissa_sub_correct :=
  fun x y (_ _ : True) (_ : (MtoP y < MtoP x)%positive) ⇒ conj (refl_equal (MtoP x - MtoP y)%positive) I.
Definition mantissa_mul_correct :=
  fun x y (Hx Hy : True) ⇒ conj (refl_equal (MtoP x × MtoP y)%positive) I.
Definition mantissa_cmp_correct :=
  fun x y (Hx Hy : True) ⇒ refl_equal (Zpos (MtoP x) ?= Zpos (MtoP y))%Z.
Definition mantissa_even_correct :=
  fun x (_ : True) ⇒ refl_equal (Z.even (Zpos x)).

Lemma mantissa_sign_correct :
   x,
  match mantissa_sign x with
  | MzeroMtoZ x = Z0
  | Mnumber s pMtoZ x = (if s then Zneg else Zpos) (MtoP p) valid_mantissa p
  end.

Lemma mantissa_digits_correct :
   x, valid_mantissa x
  EtoZ (mantissa_digits x) = Zpos (count_digits radix (MtoP x)).

Lemma mantissa_scale2_correct :
   x d, valid_mantissa x
  let (x',d') := mantissa_scale2 x d in
  (IZR (Zpos (MtoP x')) × bpow radix (EtoZ d') = IZR (Zpos (MtoP x)) × bpow radix2 (EtoZ d))%R
  valid_mantissa x'.

Lemma mantissa_shl_correct :
   x y z, valid_mantissa y
  z = Zpos x
  MtoP (mantissa_shl y z) = shift radix (MtoP y) x
  valid_mantissa (mantissa_shl y z).

Lemma mantissa_shr_correct :
   x y z k, valid_mantissa y EtoZ z = Zpos x
  (Zpos (shift radix 1 x) Zpos (MtoP y))%Z
  let (sq,l) := mantissa_shr y z k in
  let (q,r) := Z.div_eucl (Zpos (MtoP y)) (Zpos (shift radix 1 x)) in
  Zpos (MtoP sq) = q
  l = adjust_pos r (shift radix 1 x) k
  valid_mantissa sq.

Lemma mantissa_shrp_correct :
   x y z k, valid_mantissa y EtoZ z = Zpos x
  (Zpower radix (Zpos x - 1) Zpos (MtoP y) < Zpos (shift radix 1 x))%Z
  let l := mantissa_shrp y z k in
  l = adjust_pos (Zpos (MtoP y)) (shift radix 1 x) k.

Lemma mantissa_div_correct :
   x y, valid_mantissa x valid_mantissa y
  (Zpos (MtoP y) Zpos (MtoP x))%Z
  let (q,l) := mantissa_div x y in
  Zpos (MtoP q) = (Zpos (MtoP x) / Zpos (MtoP y))%Z
  Bracket.inbetween_int (Zpos (MtoP q)) (IZR (Zpos (MtoP x)) / IZR (Zpos (MtoP y)))%R (convert_location_inv l)
  valid_mantissa q.

Lemma mantissa_sqrt_correct :
   x, valid_mantissa x
  let (q,l) := mantissa_sqrt x in
  let (s,r) := Z.sqrtrem (Zpos (MtoP x)) in
  Zpos (MtoP q) = s
  match l with pos_Eqr = Z0 | pos_Lo ⇒ (0 < r s)%Z | pos_MiFalse | pos_Up ⇒ (s < r)%Z end
  valid_mantissa q.

End StdZRadix2.