(* Coq Formalization of Q16_16 Fixed-Point Arithmetic (Rocq 9.0) *) From Corelib Require Import BinNums PosDef NatDef IntDef. Require Import SilverSight.coq.ZCompat. Local Open Scope Z_scope. Fixpoint pow2_positive (n : nat) : positive := match n with O => xH | S m => xO (pow2_positive m) end. Fixpoint ones_positive (n : nat) : positive := match n with O => xH | S m => xI (ones_positive m) end. Definition p65536 : positive := pow2_positive 16. Definition p2147483647 : positive := ones_positive 31. Definition p2147483648 : positive := pow2_positive 31. Lemma neg_le_pos (p q : positive) : Z.le (Zneg p) (Zpos q). Proof. unfold Z.le, Z.compare; discriminate. Qed. Lemma neg_le_zero (p : positive) : Z.le (Zneg p) Z0. Proof. unfold Z.le, Z.compare; discriminate. Qed. Lemma zero_le_pos (q : positive) : Z.le Z0 (Zpos q). Proof. unfold Z.le, Z.compare; discriminate. Qed. Lemma pos_le_pos (q : positive) : Z.le (Zpos q) (Zpos q). Proof. unfold Z.le, Z.compare; rewrite Pos_compare_self; discriminate. Qed. Lemma le_neg2147483648_2147483647 : Z.le (Zneg p2147483648) (Zpos p2147483647). Proof. apply neg_le_pos. Qed. Lemma le_0_2147483647 : Z.le Z0 (Zpos p2147483647). Proof. apply zero_le_pos. Qed. Lemma le_neg2147483648_0 : Z.le (Zneg p2147483648) Z0. Proof. apply neg_le_zero. Qed. Lemma le_2147483647_2147483647 : Z.le (Zpos p2147483647) (Zpos p2147483647). Proof. apply pos_le_pos. Qed. Module Q16_16. Open Scope Z_scope. Definition q16_min_raw : Z := Zneg p2147483648. Definition q16_max_raw : Z := Zpos p2147483647. Definition q16_scale : Z := Zpos p65536. Definition in_range (x : Z) : Prop := Z.le q16_min_raw x /\ Z.le x q16_max_raw. Definition clamp_raw (i : Z) : Z := if Z_lt_dec q16_max_raw i then q16_max_raw else if Z_lt_dec i q16_min_raw then q16_min_raw else i. Theorem clamp_bounded (x : Z) : in_range (clamp_raw x). Proof. unfold clamp_raw, in_range. case (Z_lt_dec q16_max_raw x); intros H1. - unfold q16_min_raw, q16_max_raw; split; [apply le_neg2147483648_2147483647 | apply Zle_refl]. - case (Z_lt_dec x q16_min_raw); intros H2. + unfold q16_min_raw, q16_max_raw; split; [apply Zle_refl | apply le_neg2147483648_2147483647]. + split; apply Znlt_ge; assumption. Qed. Theorem clamp_idempotent (x : Z) (h : in_range x) : clamp_raw x = x. Proof. destruct h as [Hlo Hhi]. unfold clamp_raw. case (Z_lt_dec q16_max_raw x); intros Hgt; [exfalso; exact (Zlt_not_le _ _ Hgt Hhi) |]. case (Z_lt_dec x q16_min_raw); intros Hlt; [exfalso; exact (Zlt_not_le _ _ Hlt Hlo) |]. reflexivity. Qed. Definition zero : Z := Z0. Definition one : Z := Zpos p65536. Definition epsilon : Z := Zpos xH. Definition half : Z := Zpos (pow2_positive 15). Definition pct1 : Z := Zpos (xI(xI(xI(xI(xO(xO(xO(xI(xO(xH)))))))))). Definition pct70 : Z := Zpos (xI(xI(xO(xO(xI(xI(xO(xO(xI(xI(xO(xO(xI(xI(xO(xH)))))))))))))))). Definition pct30 : Z := Zpos (xI(xO(xI(xI(xO(xO(xI(xI(xO(xO(xI(xI(xO(xO(xH))))))))))))))). Definition one50 : Z := Zpos (xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xO(xI(xH))))))))))))))))). Definition add (a b : Z) : Z := clamp_raw (Z.add a b). Definition sub (a b : Z) : Z := clamp_raw (Z.sub a b). Definition neg (a : Z) : Z := clamp_raw (Z.opp a). Definition mul (a b : Z) : Z := clamp_raw (Z.div (Z.mul a b) q16_scale). Definition div (a b : Z) : Z := if Z_eq_dec b Z0 then zero else clamp_raw (Z.div (Z.mul a q16_scale) b). Theorem add_comm (a b : Z) : add a b = add b a. Proof. unfold add; rewrite Zadd_comm; reflexivity. Qed. Theorem add_in_range (a b : Z) (ha : in_range a) (hb : in_range b) (hsum : in_range (Z.add a b)) : add a b = Z.add a b. Proof. unfold add; rewrite clamp_idempotent; trivial. Qed. Theorem sub_self (a : Z) (ha : in_range a) : sub a a = zero. Proof. unfold sub, zero; rewrite Zsub_diag. apply clamp_idempotent; unfold in_range; unfold q16_min_raw, q16_max_raw. split; [apply le_neg2147483648_0 | apply le_0_2147483647]. Qed. Theorem mul_comm (a b : Z) : mul a b = mul b a. Proof. unfold mul; rewrite Zmul_comm; reflexivity. Qed. Theorem in_range_zero : in_range Z0. Proof. unfold in_range, q16_min_raw, q16_max_raw. split; [apply le_neg2147483648_0 | apply le_0_2147483647]. Qed. Theorem in_range_one : in_range (Zpos xH). Proof. unfold in_range, q16_min_raw, q16_max_raw. split; [apply le_neg2147483648_0 | apply le_0_2147483647]. Qed. End Q16_16.