Timings for Spec.v
Require Import Basics.Overture Basics.Tactics.
Local Set Universe Minimization ToSet.
Local Open Scope positive_scope.
(** ** Specification of [succ] in term of [add] *)
Lemma pos_add_1_r p : p + 1 = pos_succ p.
Lemma pos_add_1_l p : 1 + p = pos_succ p.
(** ** Specification of [add_carry] *)
Theorem pos_add_carry_spec p q : pos_add_carry p q = pos_succ (p + q).
induction p; destruct q; simpl; by apply ap.
(** ** Commutativity of [add] *)
Theorem pos_add_comm p q : p + q = q + p.
induction p; destruct q; simpl; apply ap; trivial.
rewrite 2 pos_add_carry_spec; by apply ap.
(** ** Permutation of [add] and [succ] *)
Theorem pos_add_succ_r p q : p + pos_succ q = pos_succ (p + q).
induction p; destruct q; simpl; apply ap;
auto using pos_add_1_r; rewrite pos_add_carry_spec; auto.
Theorem pos_add_succ_l p q : pos_succ p + q = pos_succ (p + q).
rewrite pos_add_comm, (pos_add_comm p).
Definition pos_add_succ p q : p + pos_succ q = pos_succ p + q.
by rewrite pos_add_succ_r, pos_add_succ_l.
Definition pos_add_carry_spec_l q r
: pos_add_carry q r = pos_succ q + r.
by rewrite pos_add_carry_spec, pos_add_succ_l.
Definition pos_add_carry_spec_r q r
: pos_add_carry q r = q + pos_succ r.
by rewrite pos_add_carry_spec, pos_add_succ_r.
(** ** No neutral elements for addition *)
Lemma pos_add_no_neutral p q : q + p <> p.
induction p as [ |p IHp|p IHp]; intros [ |q|q].
1,2: intro H; apply (IHp q).
(** * Injectivity of [pos_succ] *)
Lemma pos_succ_inj n m : pos_succ n = pos_succ m -> n = m.
induction n as [ | n x | n x]; induction m as [ | m y | m y].
1,3: destruct (xH_neq_x0 p).
1,3: destruct (x0_neq_xH p).
(** ** Addition is associative *)
Theorem pos_add_assoc p q r : p + (q + r) = p + q + r.
1: apply pos_add_carry_spec.
apply pos_add_carry_spec.
1: symmetry; apply pos_add_carry_spec_r.
rewrite 2 pos_add_carry_spec_l.
rewrite <- pos_add_succ_r.
1: apply pos_add_carry_spec_l.
1: apply pos_add_carry_spec.
2: symmetry; apply pos_add_carry_spec_r.
1,2: rewrite 2 pos_add_carry_spec, ?pos_add_succ_l.
rewrite ?pos_add_carry_spec_r.
(** ** One is neutral for multiplication *)
Lemma pos_mul_1_l p : 1 * p = p.
Lemma pos_mul_1_r p : p * 1 = p.
induction p; cbn; trivial; by apply ap.
(** [pos_succ] and doubling functions *)
Lemma pos_pred_double_succ n
: pos_pred_double (pos_succ n) = n~1.
induction n as [|n|n nH].
Lemma pos_succ_pred_double n
: pos_succ (pos_pred_double n) = n~0.
induction n as [|n nH|n].
(** ** Iteration and [pos_succ] *)
Lemma pos_iter_succ_l {A} (f : A -> A) p a
: pos_iter f (pos_succ p) a = f (pos_iter f p a).
by rewrite pos_peano_rec_beta_pos_succ.
Lemma pos_iter_succ_r {A} (f : A -> A) p a
: pos_iter f (pos_succ p) a = pos_iter f p (f a).
1,3: unfold pos_iter;
by rewrite pos_peano_rec_beta_pos_succ.
(** ** Right reduction properties for multiplication *)
Lemma mul_xO_r p q : p * q~0 = (p * q)~0.
induction p; simpl; f_ap; f_ap; trivial.
Lemma mul_xI_r p q : p * q~1 = p + (p * q)~0.
induction p; simpl; trivial; f_ap.
rewrite (pos_add_comm q p).
(** ** Commutativity of multiplication *)
Lemma pos_mul_comm p q : p * q = q * p.
(** ** Distributivity of addition over multiplication *)
Theorem pos_mul_add_distr_l p q r :
p * (q + r) = p * q + p * r.
induction p; cbn; [reflexivity | f_ap | ].
change ((p*q+p*r)~0) with (m+n).
rewrite 2 pos_add_assoc; f_ap.
rewrite <- 2 pos_add_assoc; f_ap.
Theorem pos_mul_add_distr_r p q r :
(p + q) * r = p * r + q * r.
rewrite 3 (pos_mul_comm _ r); apply pos_mul_add_distr_l.
(** ** Associativity of multiplication *)
Theorem pos_mul_assoc p q r : p * (q * r) = p * q * r.
induction p; simpl; rewrite ?IHp; trivial.
by rewrite pos_mul_add_distr_r.
(** ** [pos_succ] and [pos_mul] *)
Lemma pos_mul_succ_l p q
: (pos_succ p) * q = p * q + q.
by rewrite <- pos_add_1_r, pos_mul_add_distr_r, pos_mul_1_l.
Lemma pos_mul_succ_r p q
: p * (pos_succ q) = p + p * q.
by rewrite <- pos_add_1_l, pos_mul_add_distr_l, pos_mul_1_r.