(** Divisibility **)
Notation "m %| d" := (dvdn m d) : nat_scope.

(* Specifications: *)
Lemma dvdnP d m : reflect (exists k, m = k * d) (d %| m).
Arguments dvdnP {d m}.
Lemma dvdn0 d : d %| 0.
Lemma dvdn_trans n d m : d %| n -> n %| m -> d %| m.
Lemma dvdn2 n : (2 %| n) = ~~ odd n.
Lemma divnK d m : d %| m -> m %/ d * d = m.
Lemma muln_divA d m n : d %| n -> m * (n %/ d) = m * n %/ d.
Lemma dvdn_leq d m : 0 < m -> d %| m -> d <= m.
Lemma dvdn_pmul2l p d m : 0 < p -> (p * d %| p * m) = (d %| m).
Lemma dvdn_div d m : d %| m -> m %/ d %| m.
Lemma dvdn_exp2r m n k : m %| n -> m ^ k %| n ^ k.
Lemma dvdn_exp k d m : 0 < k -> d %| m -> d %| (m ^ k).
Hint Resolve dvdn_add dvdn_sub dvdn_exp : core.
Lemma eqn_mod_dvd d m n : n <= m -> (m == n %[mod d]) = (d %| m - n).
Lemma divnDl m n d : d %| m -> (m + n) %/ d = m %/ d + n %/ d.
Lemma gcdnn : idempotent gcdn.
Lemma gcd0n : left_id 0 gcdn. Proof. by case. Qed.
Lemma gcdn0 : right_id 0 gcdn. Proof. by case. Qed.
Lemma gcd1n : left_zero 1 gcdn.
Lemma dvdn_gcdl m n : gcdn m n %| m.
Lemma gcdnMDl k m n : gcdn m (k * m + n) = gcdn m n.
Lemma gcdn_idPr {m n} : reflect (gcdn m n = n) (n %| m).
Lemma gcdn_modr m n : gcdn m (n %% m) = gcdn m n.
Lemma Bezoutl m n : m > 0 -> {a | a < m & m %| gcdn m n + a * n}.
Lemma Bezoutr m n : n > 0 -> {a | a < n & n %| gcdn m n + a * m}.
Lemma gcdnAC : right_commutative gcdn.
Lemma gcdnA : associative gcdn.
Lemma muln_gcdl : left_distributive muln gcdn.
Lemma muln_divCA_gcd n m : n * (m %/ gcdn n m)  = m * (n %/ gcdn n m).
Lemma muln_lcml : left_distributive muln lcmn.
Lemma lcmnCA : left_commutative lcmn.
Lemma lcmnMl m n : lcmn m (m * n) = m * n.
Lemma lcmn_idPl {m n} : reflect (lcmn m n = m) (n %| m).
Definition coprime m n := gcdn m n == 1.