(* -*- 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 *)

Theorem Zdiv_mod_unique b q1 q2 r1 r2 :
0 <= r1 < Z.abs b -> 0 <= r2 < Z.abs b ->
b*q1+r1 = b*q2+r2 -> q1=q2 /\ r1=r2.