Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Properties of multiplication.
Require Import PeanoNat.
For Compatibility:
Require Export Plus Minus Le Lt. Local Open Scope nat_scope.
Notation mult_0_l := Nat.mul_0_l (only parsing). (* 0 * n = 0 *) Notation mult_0_r := Nat.mul_0_r (only parsing). (* n * 0 = 0 *)
Notation mult_1_l := Nat.mul_1_l (only parsing). (* 1 * n = n *) Notation mult_1_r := Nat.mul_1_r (only parsing). (* n * 1 = n *) Hint Resolve mult_1_l mult_1_r: arith.
Notation mult_comm := Nat.mul_comm (only parsing). (* n * m = m * n *) Hint Resolve mult_comm: arith.
Notation mult_plus_distr_r := Nat.mul_add_distr_r (only parsing). (* (n+m)*p = n*p + m*p *) Notation mult_plus_distr_l := Nat.mul_add_distr_l (only parsing). (* n*(m+p) = n*m + n*p *) Notation mult_minus_distr_r := Nat.mul_sub_distr_r (only parsing). (* (n-m)*p = n*p - m*p *) Notation mult_minus_distr_l := Nat.mul_sub_distr_l (only parsing). (* n*(m-p) = n*m - n*p *) Hint Resolve mult_plus_distr_r: arith. Hint Resolve mult_minus_distr_r: arith. Hint Resolve mult_minus_distr_l: arith.
Notation mult_assoc := Nat.mul_assoc (only parsing). (* n*(m*p)=n*m*p *)n, m, p:natn * m * p = n * (m * p)n, m, p:natn * m * p = n * (m * p)apply Nat.mul_assoc. Qed. Hint Resolve mult_assoc_reverse: arith. Hint Resolve mult_assoc: arith.n, m, p:natn * (m * p) = n * m * p
n, m:natn * m = 0 -> n = 0 \/ m = 0apply Nat.eq_mul_0. Qed.n, m:natn * m = 0 -> n = 0 \/ m = 0n, m:natn * m = 1 -> n = 1 /\ m = 1apply Nat.eq_mul_1. Qed.n, m:natn * m = 1 -> n = 1 /\ m = 1
Notation mult_succ_l := Nat.mul_succ_l (only parsing). (* S n * m = n * m + m *) Notation mult_succ_r := Nat.mul_succ_r (only parsing). (* n * S m = n * m + n *)
n, m:natm = 0 \/ n <= m * ndestruct m; [left|right]; simpl; trivial using Nat.le_add_r. Qed. Hint Resolve mult_O_le: arith.n, m:natm = 0 \/ n <= m * nn, m, p:natn <= m -> p * n <= p * mapply Nat.mul_le_mono_nonneg_l, Nat.le_0_l. (* TODO : get rid of 0<=n hyp *) Qed. Hint Resolve mult_le_compat_l: arith.n, m, p:natn <= m -> p * n <= p * mn, m, p:natn <= m -> n * p <= m * papply Nat.mul_le_mono_nonneg_r, Nat.le_0_l. Qed.n, m, p:natn <= m -> n * p <= m * pn, m, p, q:natn <= m -> p <= q -> n * p <= m * qn, m, p, q:natn <= m -> p <= q -> n * p <= m * qapply Nat.mul_le_mono_nonneg; trivial; apply Nat.le_0_l. Qed.n, m, p, q:natH:n <= mH0:p <= qn * p <= m * qn, m, p:natm < p -> S n * m < S n * papply Nat.mul_lt_mono_pos_l, Nat.lt_0_succ. Qed. Hint Resolve mult_S_lt_compat_l: arith.n, m, p:natm < p -> S n * m < S n * pn, m, p:natn < m -> 0 < p -> p * n < p * mn, m, p:natn < m -> 0 < p -> p * n < p * mnow apply Nat.mul_lt_mono_pos_l. Qed.n, m, p:natH:n < mH0:0 < pp * n < p * mn, m, p:natn < m -> 0 < p -> n * p < m * pn, m, p:natn < m -> 0 < p -> n * p < m * pnow apply Nat.mul_lt_mono_pos_r. Qed.n, m, p:natH:n < mH0:0 < pn * p < m * pn, m, p:natS n * m <= S n * p -> m <= papply Nat.mul_le_mono_pos_l, Nat.lt_0_succ. Qed.n, m, p:natS n * m <= S n * p -> m <= p
p, q:nat2 * p + 1 <> 2 * qp, q:nat2 * p + 1 <> 2 * qp, q:natH:2 * p + 1 = 2 * qFalsep, q:natH:2 * p + 1 = 2 * qNat.Even (2 * q)p, q:natH:2 * p + 1 = 2 * qNat.Odd (2 * q)now exists q.p, q:natH:2 * p + 1 = 2 * qNat.Even (2 * q)now exists p. Qed.p, q:natH:2 * p + 1 = 2 * qNat.Odd (2 * q)
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.forall n m p : nat, m + n * p = mult_acc m p nforall n m p : nat, m + n * p = mult_acc m p nn:natIHn:forall m p : nat, m + n * p = mult_acc m p nforall m p : nat, m + (p + n * p) = mult_acc (tail_plus p m) p nn:natIHn:forall m0 p0 : nat, m0 + n * p0 = mult_acc m0 p0 nm, p:natm + (p + n * p) = mult_acc (tail_plus p m) p nn:natIHn:forall m0 p0 : nat, m0 + n * p0 = mult_acc m0 p0 nm, p:natmult_acc (m + p) p n = mult_acc (tail_plus p m) p nn:natIHn:forall m0 p0 : nat, m0 + n * p0 = mult_acc m0 p0 nm, p:natm + p = tail_plus p mapply plus_tail_plus. Qed. Definition tail_mult n m := mult_acc 0 m n.n:natIHn:forall m0 p0 : nat, m0 + n * p0 = mult_acc m0 p0 nm, p:natp + m = tail_plus p mforall n m : nat, n * m = tail_mult n mintros; unfold tail_mult; rewrite <- mult_acc_aux; auto. Qed.forall n m : nat, n * m = tail_mult n m
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.