(************************************************************************)
(*         *   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.  This file is mostly OBSOLETE now, see module [PeanoNat.Nat] instead.  [Nat.mul] is defined in [Init/Nat.v]. *)
(** For Compatibility: *)
Require Export Plus Minus Le Lt.
Local Open Scope nat_scope.
(** * [nat] is a semi-ring *)
(** ** Zero property *)
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 *)
(** ** 1 is neutral *)
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.
(** ** Commutativity *)
Notation mult_comm := Nat.mul_comm (only parsing). (* n * m = m * n *)
Hint Resolve mult_comm: arith.
(** ** Distributivity *)
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.
(** ** Associativity *)
Notation mult_assoc := Nat.mul_assoc (only parsing). (* n*(m*p)=n*m*p *)
Hint Resolve mult_assoc_reverse: arith.
Hint Resolve mult_assoc: arith.
(** ** Inversion lemmas *)
(** ** Multiplication and successor *)
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 *)
(** * Compatibility with orders *)
Hint Resolve mult_O_le: arith.
Hint Resolve mult_le_compat_l: arith.
Hint Resolve mult_S_lt_compat_l: arith.
(** * n|->2*n and n|->2n+1 have disjoint image *)
(** * 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.
Definition tail_mult n m := mult_acc 0 m n.

Lemma mult_tail_mult : forall n m, n * m = tail_mult n m.