(* -*- coding: utf-8 -*- *)
(************************************************************************)
(*         *   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)         *)
(************************************************************************)
(** * Euclidean Division *)
(** Initial Contribution by Claude Marché and Xavier Urbain *)
Require Export ZArith_base.
Local Open Scope Z_scope.
(** The definition of the division is now in [BinIntDef], the initial specifications and properties are in [BinInt]. *)
Notation Zdiv_eucl_POS := Z.pos_div_eucl (only parsing).
Notation Zmod := Z.modulo (only parsing).
Notation Z_div_mod_eq_full := Z.div_mod (only parsing).
Notation Zmod_POS_bound := Z.pos_div_eucl_bound (only parsing).
Notation Zmod_pos_bound := Z.mod_pos_bound (only parsing).
Notation Zmod_neg_bound := Z.mod_neg_bound (only parsing).
(** * Main division theorems *)
(** NB: many things are stated twice for compatibility reasons *)
(** For stating the fully general result, let's give a short name to the condition on the remainder. *)
Definition Remainder r b :=  0 <= r < b \/ b < r <= 0.
(** Another equivalent formulation: *)
Definition Remainder_alt r b :=  Z.abs r < Z.abs b /\ Z.sgn r <> - Z.sgn b.
(* In the last formulation, [ Z.sgn r <> - Z.sgn b ] is less nice than saying [ Z.sgn r = Z.sgn b ], but at least it works even when [r] is null. *)
Hint Unfold Remainder : core.
(** Now comes the fully general result about Euclidean division. *)
(** The same results as before, stated separately in terms of Z.div and Z.modulo *)
Proof (fun Hb => Z.mod_pos_bound a b (Z.gt_lt _ _ Hb)).
Proof (Z.mod_neg_bound a b).
Arguments Zdiv_eucl_exist : default implicits.
(** Uniqueness theorems *)
Proof Z.div_mod_unique.
Proof Z.div_unique.
Ltac zero_or_not a :=
destruct (Z.eq_dec a 0);
[subst; rewrite ?Zmod_0_l, ?Zdiv_0_l, ?Zmod_0_r, ?Zdiv_0_r;
auto with zarith|].
(** As soon as the divisor is greater or equal than 2, the division is strictly decreasing. *)
(** * Relations between usual operations and Z.modulo and Z.div *)
(** Operations modulo. *)

Lemma Zmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n.