Module Float32.
(** ** NaN payload manipulations *)
Definition transform_quiet_nan s p H : {x : float32 | is_nan _ _ x = true} :=
exist _ (B754_nan 24 128 s _ (transform_quiet_nan_proof p H)) (eq_refl true).
Definition neg_nan (f : float32) : { x : float32 | is_nan _ _ x = true } :=
match f with
| B754_nan s p H => exist _ (B754_nan 24 128 (negb s) p H) (eq_refl true)
| _ => Archi.default_nan_32
end.
Definition abs_nan (f : float32) : { x : float32 | is_nan _ _ x = true } :=
match f with
| B754_nan s p H => exist _ (B754_nan 24 128 false p H) (eq_refl true)
| _ => Archi.default_nan_32
end.
Definition binop_nan (x y : float32) : {x : float32 | is_nan _ _ x = true} :=
if Archi.fpu_returns_default_qNaN then Archi.default_nan_32 else
match x, y with
| B754_nan s1 pl1 H1, B754_nan s2 pl2 H2 =>
if Archi.choose_binop_pl_32 pl1 pl2
then transform_quiet_nan s2 pl2 H2
else transform_quiet_nan s1 pl1 H1
| B754_nan s1 pl1 H1, _ => transform_quiet_nan s1 pl1 H1
| _, B754_nan s2 pl2 H2 => transform_quiet_nan s2 pl2 H2
| _, _ => Archi.default_nan_32
end.
(** ** Operations over single-precision floats *)
Definition zero: float32 := B754_zero _ _ false. (**r the float [+0.0] *)
Definition eq_dec: forall (f1 f2: float32), {f1 = f2} + {f1 <> f2} := Beq_dec _ _.
(** Arithmetic operations *)
Definition neg: float32 -> float32 := Bopp _ _ neg_nan. (**r opposite (change sign) *)
Definition abs: float32 -> float32 := Babs _ _ abs_nan. (**r absolute value (set sign to [+]) *)
Definition add: float32 -> float32 -> float32 :=
Bplus 24 128 __ __ binop_nan mode_NE. (**r addition *)
Definition sub: float32 -> float32 -> float32 :=
Bminus 24 128 __ __ binop_nan mode_NE. (**r subtraction *)
Definition mul: float32 -> float32 -> float32 :=
Bmult 24 128 __ __ binop_nan mode_NE. (**r multiplication *)
Definition div: float32 -> float32 -> float32 :=
Bdiv 24 128 __ __ binop_nan mode_NE. (**r division *)
Definition compare (f1 f2: float32) : option Datatypes.comparison := (**r general comparison *)
Bcompare 24 128 f1 f2.
Definition cmp (c:comparison) (f1 f2: float32) : bool := (**r comparison *)
cmp_of_comparison c (compare f1 f2).
Definition ordered (f1 f2: float32) : bool :=
ordered_of_comparison (compare f1 f2).
(** Conversions *)
Definition of_double : float -> float32 := Float.to_single.
Definition to_double : float32 -> float := Float.of_single.
Definition to_int (f:float32): option int := (**r conversion to signed 32-bit int *)
option_map Int.repr (ZofB_range _ _ f Int.min_signed Int.max_signed).
Definition to_intu (f:float32): option int := (**r conversion to unsigned 32-bit int *)
option_map Int.repr (ZofB_range _ _ f 0 Int.max_unsigned).
Definition to_long (f:float32): option int64 := (**r conversion to signed 64-bit int *)
option_map Int64.repr (ZofB_range _ _ f Int64.min_signed Int64.max_signed).
Definition to_longu (f:float32): option int64 := (**r conversion to unsigned 64-bit int *)
option_map Int64.repr (ZofB_range _ _ f 0 Int64.max_unsigned).
Definition of_int (n:int): float32 := (**r conversion from signed 32-bit int to single-precision float *)
BofZ 24 128 __ __ (Int.signed n).
Definition of_intu (n:int): float32 := (**r conversion from unsigned 32-bit int to single-precision float *)
BofZ 24 128 __ __ (Int.unsigned n).
Definition of_long (n:int64): float32 := (**r conversion from signed 64-bit int to single-precision float *)
BofZ 24 128 __ __ (Int64.signed n).
Definition of_longu (n:int64): float32 := (**r conversion from unsigned 64-bit int to single-precision float *)
BofZ 24 128 __ __ (Int64.unsigned n).
Definition from_parsed (base:positive) (intPart:positive) (expPart:Z) : float32 :=
Bparse 24 128 __ __ base intPart expPart.
(** Conversions between floats and their concrete in-memory representation as a sequence of 32 bits. *)
Definition to_bits (f: float32) : int := Int.repr (bits_of_b32 f).
Definition of_bits (b: int): float32 := b32_of_bits (Int.unsigned b).
(** ** Properties *)
(** Commutativity properties of addition and multiplication. *)
(** Multiplication by 2 is diagonal addition. *)
(** Divisions that can be turned into multiplication by an inverse. *)
Definition exact_inverse : float32 -> option float32 := Bexact_inverse 24 128 __ __.
(** Properties of comparisons. *)
(** Properties of conversions to/from in-memory representation. The conversions are bijective (one-to-one). *)
(** Conversions from 32-bit integers to single-precision floats can be decomposed into a conversion to a double-precision float, followed by a [Float32.of_double] conversion.  No double rounding occurs. *)
(** Conversion of single-precision floats to integers can be decomposed into a [Float32.to_double] extension, followed by a double-precision-to-int conversion. *)
(** Conversions from 64-bit integers to single-precision floats can be expressed as conversion to a double-precision float followed by a [Float32.of_double] conversion. To avoid double rounding when the integer is large (above [2^53]), a round to odd must be performed on the integer before conversion to double-precision float. *)

Lemma of_long_round_odd:
forall n conv_nan,
2^36 <= Z.abs n < 2^64 ->
BofZ 24 128 __ __ n = Bconv _ _ 24 128 __ __ conv_nan mode_NE (BofZ 53 1024 __ __ (Z.land (Z.lor n ((Z.land n 2047) + 2047)) (-2048))).