(************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* n = 0 \/ m = 0. Proof. destruct n as [| n]; simpl; intros m H. left; trivial. right; apply plus_is_O in H; destruct H; trivial. Qed. Lemma mult_is_one : forall n m, n * m = 1 -> n = 1 /\ m = 1. Proof. destruct n as [|n]; simpl; intros m H. edestruct O_S; eauto. destruct plus_is_one with (1:=H) as [[-> Hnm] | [-> Hnm]]. simpl in H; rewrite mult_0_r in H; elim (O_S _ H). rewrite mult_1_r in Hnm; auto. Qed. (** ** Multiplication and successor *) Lemma mult_succ_l : forall n m:nat, S n * m = n * m + m. Proof. intros; simpl. rewrite plus_comm. reflexivity. Qed. Lemma mult_succ_r : forall n m:nat, n * S m = n * m + n. Proof. induction n as [| p H]; intro m; simpl. reflexivity. rewrite H, <- plus_n_Sm; apply f_equal; rewrite plus_assoc; reflexivity. Qed. (** * Compatibility with orders *) Lemma mult_O_le : forall n m, m = 0 \/ n <= m * n. Proof. induction m; simpl in |- *; auto with arith. Qed. Hint Resolve mult_O_le: arith v62. Lemma mult_le_compat_l : forall n m p, n <= m -> p * n <= p * m. Proof. induction p as [| p IHp]; intros; simpl in |- *. apply le_n. auto using plus_le_compat. Qed. Hint Resolve mult_le_compat_l: arith. Lemma mult_le_compat_r : forall n m p, n <= m -> n * p <= m * p. Proof. intros m n p H; rewrite mult_comm, (mult_comm n); auto with arith. Qed. Lemma mult_le_compat : forall n m p (q:nat), n <= m -> p <= q -> n * p <= m * q. Proof. intros m n p q Hmn Hpq; induction Hmn. induction Hpq. (* m*p<=m*p *) apply le_n. (* m*p<=m*m0 -> m*p<=m*(S m0) *) rewrite <- mult_n_Sm; apply le_trans with (m * m0). assumption. apply le_plus_l. (* m*p<=m0*q -> m*p<=(S m0)*q *) simpl in |- *; apply le_trans with (m0 * q). assumption. apply le_plus_r. Qed. Lemma mult_S_lt_compat_l : forall n m p, m < p -> S n * m < S n * p. Proof. induction n; intros; simpl in *. rewrite <- 2 plus_n_O; assumption. auto using plus_lt_compat. Qed. Hint Resolve mult_S_lt_compat_l: arith. Lemma mult_lt_compat_l : forall n m p, n < m -> 0 < p -> p * n < p * m. Proof. intros m n p H Hp. destruct p. elim (lt_irrefl _ Hp). now apply mult_S_lt_compat_l. Qed. Lemma mult_lt_compat_r : forall n m p, n < m -> 0 < p -> n * p < m * p. Proof. intros m n p H Hp. destruct p. elim (lt_irrefl _ Hp). rewrite (mult_comm m), (mult_comm n). now apply mult_S_lt_compat_l. Qed. Lemma mult_S_le_reg_l : forall n m p, S n * m <= S n * p -> m <= p. Proof. intros m n p H; destruct (le_or_lt n p). trivial. assert (H1:S m * n < S m * n). apply le_lt_trans with (m := S m * p). assumption. apply mult_S_lt_compat_l. assumption. elim (lt_irrefl _ H1). Qed. (** * n|->2*n and n|->2n+1 have disjoint image *) Theorem odd_even_lem : forall p q, 2 * p + 1 <> 2 * q. Proof. induction p; destruct q. discriminate. simpl; rewrite plus_comm. discriminate. discriminate. intro H0; destruct (IHp q). replace (2 * q) with (2 * S q - 2). rewrite <- H0; simpl. repeat rewrite (fun x y => plus_comm x (S y)); simpl; auto. simpl; rewrite (fun y => plus_comm q (S y)); destruct q; simpl; auto. Qed. (** * Tail-recursive mult *) (** [tail_mult] is an alternative definition for [mult] which is tail-recursive, whereas [mult] is not. This can be useful when extracting programs. *) Fixpoint mult_acc (s:nat) m n : nat := match n with | O => s | S p => mult_acc (tail_plus m s) m p end. Lemma mult_acc_aux : forall n m p, m + n * p = mult_acc m p n. Proof. induction n as [| p IHp]; simpl in |- *; auto. intros s m; rewrite <- plus_tail_plus; rewrite <- IHp. rewrite <- plus_assoc_reverse; apply f_equal2; auto. rewrite plus_comm; auto. Qed. Definition tail_mult n m := mult_acc 0 m n. Lemma mult_tail_mult : forall n m, n * m = tail_mult n m. Proof. intros; unfold tail_mult in |- *; rewrite <- mult_acc_aux; auto. Qed. (** [TailSimpl] transforms any [tail_plus] and [tail_mult] into [plus] and [mult] and simplify *) Ltac tail_simpl := repeat rewrite <- plus_tail_plus; repeat rewrite <- mult_tail_mult; simpl in |- *.