(** A variant of [ZofB] that bounds the range of representable integers. *)

Definition ZofB_range (f: binary_float) (zmin zmax: Z): option Z :=
  match ZofB f with
  | None => None
  | Some z => if Z.leb zmin z && Z.leb z zmax then Some z else None
  end.

(* Specifications: *)
Theorem ZofB_range_correct: forall f min max, let n := Ztrunc (B2R _ _ f) in ZofB_range f min max = if is_finite _ _ f && Z.leb min n && Z.leb n max then Some n else None.
Lemma ZofB_range_inversion: forall f min max n, ZofB_range f min max = Some n -> min <= n /\ n <= max /\ ZofB f = Some n.
Theorem ZofB_range_minus: forall minus_nan m f p q, ZofB_range f 0 (2 * q - 1) = Some p -> q <= 2^prec -> (Z2R q <= B2R _ _ f)%R -> ZofB_range (Bminus _ _ _ Hmax minus_nan m f (BofZ q)) (-q) (q - 1) = Some (p - q).
Theorem Bplus_commut: forall plus_nan mode (x y: binary_float), plus_nan x y = plus_nan y x -> Bplus _ _ _ Hmax plus_nan mode x y = Bplus _ _ _ Hmax plus_nan mode y x.
Theorem Bmult_commut: forall mult_nan mode (x y: binary_float), mult_nan x y = mult_nan y x -> Bmult _ _ _ Hmax mult_nan mode x y = Bmult _ _ _ Hmax mult_nan mode y x.
Theorem Bmult2_Bplus: forall plus_nan mult_nan mode (f: binary_float), (forall (x y: binary_float), is_nan _ _ x = true -> is_finite _ _ y = true -> plus_nan x x = mult_nan x y) -> Bplus _ _ _ Hmax plus_nan mode f f = Bmult _ _ _ Hmax mult_nan mode f (BofZ 2%Z).
Theorem ZofB_range_correct: forall f min max, let n := Ztrunc (B2R _ _ f) in ZofB_range f min max = if is_finite _ _ f && Z.leb min n && Z.leb n max then Some n else None.
Lemma ZofB_range_inversion: forall f min max n, ZofB_range f min max = Some n -> min <= n /\ n <= max /\ ZofB f = Some n.
Theorem ZofB_range_minus: forall minus_nan m f p q, ZofB_range f 0 (2 * q - 1) = Some p -> q <= 2^prec -> (Z2R q <= B2R _ _ f)%R -> ZofB_range (Bminus _ _ _ Hmax minus_nan m f (BofZ q)) (-q) (q - 1) = Some (p - q).
Theorem Bplus_commut: forall plus_nan mode (x y: binary_float), plus_nan x y = plus_nan y x -> Bplus _ _ _ Hmax plus_nan mode x y = Bplus _ _ _ Hmax plus_nan mode y x.
Theorem Bmult_commut: forall mult_nan mode (x y: binary_float), mult_nan x y = mult_nan y x -> Bmult _ _ _ Hmax mult_nan mode x y = Bmult _ _ _ Hmax mult_nan mode y x.
Theorem Bmult2_Bplus: forall plus_nan mult_nan mode (f: binary_float), (forall (x y: binary_float), is_nan _ _ x = true -> is_finite _ _ y = true -> plus_nan x x = mult_nan x y) -> Bplus _ _ _ Hmax plus_nan mode f f = Bmult _ _ _ Hmax mult_nan mode f (BofZ 2%Z).