(* This program 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 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program 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      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
(********************************************************)
(* Une  axiomatisation en coq de la norme IEEE 754 	*)
(* Module Diadic.v 				   	*)
(* un plan d'ensemble se trouve dans le fichier README 	*)
(* Patrick Loiseleur, avril 1997			*)
(********************************************************)
Section definitions.
(* The type diadic represents the set of numbers who can be written:  	*)
(* x = n*2^p with  n and p in Z. (diadic numbers)			*)
(* n = Dnum and p = Dexp 						*)
Record diadic : Set := Diadic {Dnum : Z; Dexp : Z}.
Definition Dshift (n : Z) (x : diadic) := Diadic (Dnum x) (Dexp x + n).
Definition Dzero (x : Z) := Diadic 0 x.
Definition is_Dzero (x : diadic) := Dnum x = 0%Z.
(** Fixpoint Dnormalize[x:diadic] : diadic := Cases (Dnum x) of (POS (xO y)) => (Dnormalize (Diadic (POS y) `(Dexp x)+1`)) | (NEG (xO y)) => (Dnormalize (Diadic (NEG y) `(Dexp x)+1`)) | _ => x end. **)
Inductive rounding_mode : Set :=
| Rounding_sup : rounding_mode
| Rounding_inf : rounding_mode
| Rounding_nearest : rounding_mode
| Rounding_zero : rounding_mode.
Definition Rounding_mode_opp (m : rounding_mode) :=
match m with
| Rounding_sup => Rounding_inf
| Rounding_inf => Rounding_sup
| Rounding_nearest => Rounding_nearest
| Rounding_zero => Rounding_zero
end.
(* This inductive set, equal to {-infty}+Z+Z (disjoint union) is the set of results of function DLog. *)
(**** Inductive DLog_result : Set := M_infty : DLog_result | Log_of_pos : Z -> DLog_result | Log_of_neg : Z -> DLog_result. ****)
End definitions.
Section comparisons.
(* Fist a function Qcompare is defined, who takes two diadic numbers	*)
(* and answers SUPERIEUR, EGAL or INFERIEUR.				*)
(* Qcompare is similary to Zcompare from the omega library		*)
(* Then the usual predicates "less or equal", "less than", "greater	*)
(* or equal" and "greater than" are defined. Since these predicates	*)
(* are deterministic, the boolean equivalents are also defined	*)
(* Be careful ! Two diadic numbers x, y are equal iff the predicate	*)
(* (Deq x y) is true, that is (Dcompare x y)=EGAL			*)
(* That's not equivalent to : (eq D x y)				*)
Definition Dcompare (x y : diadic) : Datatypes.comparison :=
let nx := Dnum x in
let ny := Dnum y in
let ex := Dexp x in
let ey := Dexp y in
(two_p (ex - Zmin ex ey) * nx ?= two_p (ey - Zmin ex ey) * ny)%Z.
(* Inductive relation := EGAL | INFERIEUR | SUPERIEUR *)
Definition Deq (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => True
| Datatypes.Lt => False
| Datatypes.Gt => False
end.
Definition Dneq (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => False
| Datatypes.Lt => True
| Datatypes.Gt => True
end.
Definition Dle (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => True
| Datatypes.Lt => True
| Datatypes.Gt => False
end.
Definition Dlt (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => False
| Datatypes.Lt => True
| Datatypes.Gt => False
end.
Definition Dge (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => True
| Datatypes.Lt => False
| Datatypes.Gt => True
end.
Definition Dgt (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => False
| Datatypes.Lt => False
| Datatypes.Gt => True
end.
Definition Deq_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => true
| Datatypes.Lt => false
| Datatypes.Gt => false
end.
Definition Dneq_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => false
| Datatypes.Lt => true
| Datatypes.Gt => true
end.
Definition Dle_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => true
| Datatypes.Lt => true
| Datatypes.Gt => false
end.
Definition Dlt_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => false
| Datatypes.Lt => true
| Datatypes.Gt => false
end.
Definition Dge_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => true
| Datatypes.Lt => false
| Datatypes.Gt => true
end.
Definition Dgt_bool (x y : diadic) :=
match Dcompare x y with
| Datatypes.Eq => false
| Datatypes.Lt => false
| Datatypes.Gt => true
end.

Lemma Dcompare_shift :
forall (x y : diadic) (n : Z),
Dcompare (Dshift n x) (Dshift n y) = Dcompare x y.