(** ** Conversion from scientific notation *)

(** Russian peasant exponentiation *)

Fixpoint pos_pow (x y: positive) : positive :=
  match y with
  | xH => x
  | xO y => Pos.square (pos_pow x y)
  | xI y => Pos.mul x (Pos.square (pos_pow x y))
  end.

(* Specifications: *)
Lemma pos_pow_spec: forall x y, Z.pos (pos_pow x y) = Z.pos x ^ Z.pos y.
Lemma Zpower_log: forall (base: radix) n, 0 < n -> 2 ^ (n * Z.log2 base) <= base ^ n <= 2 ^ (n * Z.log2_up base).
Lemma bpow_log_pos: forall (base: radix) n, 0 < n -> (bpow radix2 (n * Z.log2 base)%Z <= bpow base n)%R.
Lemma bpow_log_neg: forall (base: radix) n, n < 0 -> (bpow base n <= bpow radix2 (n * Z.log2 base)%Z)%R.
Lemma round_integer_overflow: forall (base: radix) e m, 0 < e -> emax <= e * Z.log2 base -> (bpow radix2 emax <= round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e))%R.
Lemma round_NE_underflows: forall x, (0 <= x <= bpow radix2 (emin - 1))%R -> round radix2 fexp (round_mode mode_NE) x = 0%R.
Lemma round_integer_underflow: forall (base: radix) e m, e < 0 -> e * Z.log2 base + Z.log2_up (Zpos m) < emin -> round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e) = 0%R.
Theorem Bparse_correct: forall b m e (BASE: 2 <= Zpos b), let base := {| radix_val := Zpos b; radix_prop := Zle_imp_le_bool _ _ BASE |} in let r := round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e) in if Rlt_bool (Rabs r) (bpow radix2 emax) then B2R _ _ (Bparse b m e) = r /\ is_finite _ _ (Bparse b m e) = true /\ Bsign _ _ (Bparse b m e) = false else B2FF _ _ (Bparse b m e) = F754_infinity false.
Lemma pos_pow_spec: forall x y, Z.pos (pos_pow x y) = Z.pos x ^ Z.pos y.
Lemma Zpower_log: forall (base: radix) n, 0 < n -> 2 ^ (n * Z.log2 base) <= base ^ n <= 2 ^ (n * Z.log2_up base).
Lemma bpow_log_pos: forall (base: radix) n, 0 < n -> (bpow radix2 (n * Z.log2 base)%Z <= bpow base n)%R.
Lemma bpow_log_neg: forall (base: radix) n, n < 0 -> (bpow base n <= bpow radix2 (n * Z.log2 base)%Z)%R.
Lemma round_integer_overflow: forall (base: radix) e m, 0 < e -> emax <= e * Z.log2 base -> (bpow radix2 emax <= round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e))%R.
Lemma round_NE_underflows: forall x, (0 <= x <= bpow radix2 (emin - 1))%R -> round radix2 fexp (round_mode mode_NE) x = 0%R.
Lemma round_integer_underflow: forall (base: radix) e m, e < 0 -> e * Z.log2 base + Z.log2_up (Zpos m) < emin -> round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e) = 0%R.
Theorem Bparse_correct: forall b m e (BASE: 2 <= Zpos b), let base := {| radix_val := Zpos b; radix_prop := Zle_imp_le_bool _ _ BASE |} in let r := round radix2 fexp (round_mode mode_NE) (Z2R (Zpos m) * bpow base e) in if Rlt_bool (Rabs r) (bpow radix2 emax) then B2R _ _ (Bparse b m e) = r /\ is_finite _ _ (Bparse b m e) = true /\ Bsign _ _ (Bparse b m e) = false else B2FF _ _ (Bparse b m e) = F754_infinity false.