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) *) (************************************************************************) Require Import ZArithRing. Require Import Omega. Require Export ZArith_base. Local Open Scope Z_scope.
THIS FILE IS DEPRECATED
Instead of the various Zsqrt defined here, please use rather
Z.sqrt (or Z.sqrtrem). The latter are pure functions without
proof parts, and more results are available about them.
Some equivalence proofs between the old and the new versions
can be found below. Importing ZArith will provides by default
the new versions.
(**********************************************************************)
Definition and properties of square root on Z
The following tactic replaces all instances of (POS (xI ...)) by
`2*(POS ...)+1`, but only when ... is not made only with xO, XI, or xH.
Ltac compute_POS := match goal with | |- context [(Zpos (xI ?X1))] => match constr:(X1) with | context [1%positive] => fail 1 | _ => rewrite (Pos2Z.inj_xI X1) end | |- context [(Zpos (xO ?X1))] => match constr:(X1) with | context [1%positive] => fail 1 | _ => rewrite (Pos2Z.inj_xO X1) end end. Inductive sqrt_data (n:Z) : Set := c_sqrt : forall s r:Z, n = s * s + r -> 0 <= r <= 2 * s -> sqrt_data n.refine (fix sqrtrempos (p:positive) : sqrt_data (Zpos p) := match p return sqrt_data (Zpos p) with | xH => c_sqrt 1 1 0 _ _ | xO xH => c_sqrt 2 1 1 _ _ | xI xH => c_sqrt 3 1 2 _ _ | xO (xO p') => match sqrtrempos p' with | c_sqrt _ s' r' Heq Hint => match Z_le_gt_dec (4 * s' + 1) (4 * r') with | left Hle => c_sqrt (Zpos (xO (xO p'))) (2 * s' + 1) (4 * r' - (4 * s' + 1)) _ _ | right Hgt => c_sqrt (Zpos (xO (xO p'))) (2 * s') (4 * r') _ _ end end | xO (xI p') => match sqrtrempos p' with | c_sqrt _ s' r' Heq Hint => match Z_le_gt_dec (4 * s' + 1) (4 * r' + 2) with | left Hle => c_sqrt (Zpos (xO (xI p'))) (2 * s' + 1) (4 * r' + 2 - (4 * s' + 1)) _ _ | right Hgt => c_sqrt (Zpos (xO (xI p'))) (2 * s') (4 * r' + 2) _ _ end end | xI (xO p') => match sqrtrempos p' with | c_sqrt _ s' r' Heq Hint => match Z_le_gt_dec (4 * s' + 1) (4 * r' + 1) with | left Hle => c_sqrt (Zpos (xI (xO p'))) (2 * s' + 1) (4 * r' + 1 - (4 * s' + 1)) _ _ | right Hgt => c_sqrt (Zpos (xI (xO p'))) (2 * s') (4 * r' + 1) _ _ end end | xI (xI p') => match sqrtrempos p' with | c_sqrt _ s' r' Heq Hint => match Z_le_gt_dec (4 * s' + 1) (4 * r' + 3) with | left Hle => c_sqrt (Zpos (xI (xI p'))) (2 * s' + 1) (4 * r' + 3 - (4 * s' + 1)) _ _ | right Hgt => c_sqrt (Zpos (xI (xI p'))) (2 * s') (4 * r' + 3) _ _ end end end); clear sqrtrempos; repeat compute_POS; try (try rewrite Heq; ring); try omega. Defined.forall p : positive, sqrt_data (Z.pos p)
Define with integer input, but with a strong (readable) specification.
forall x : Z, 0 <= x -> {s : Z & {r : Z | x = s * s + r /\ s * s <= x < (s + 1) * (s + 1)}}split; [ omega | rewrite Heq; ring_simplify (s*s) ((s + 1) * (s + 1)); omega ]. Defined.x:Zp:positiveh:0 <= Z.pos ps, r:ZHeq:Z.pos p = s * s + rHint:0 <= r <= 2 * sZ.pos p = s * s + r /\ s * s <= Z.pos p < (s + 1) * (s + 1)
Define a function of type Z->Z that computes the integer square root,
but only for positive numbers, and 0 for others.
Definition Zsqrt_plain (x:Z) : Z :=
match x with
| Zpos p =>
match Zsqrt (Zpos p) (Pos2Z.is_nonneg p) with
| existT _ s _ => s
end
| Zneg p => 0
| Z0 => 0
end.
A basic theorem about Zsqrt_plain
forall n : Z, 0 <= n -> Zsqrt_plain n * Zsqrt_plain n <= n < (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)forall n : Z, 0 <= n -> Zsqrt_plain n * Zsqrt_plain n <= n < (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)Hp:0 <= 0Zsqrt_plain 0 * Zsqrt_plain 0 <= 0 < (Zsqrt_plain 0 + 1) * (Zsqrt_plain 0 + 1)p:positiveHp:0 <= Z.pos pZsqrt_plain (Z.pos p) * Zsqrt_plain (Z.pos p) <= Z.pos p < (Zsqrt_plain (Z.pos p) + 1) * (Zsqrt_plain (Z.pos p) + 1)p:positiveHp:0 <= Z.neg pZsqrt_plain (Z.neg p) * Zsqrt_plain (Z.neg p) <= Z.neg p < (Zsqrt_plain (Z.neg p) + 1) * (Zsqrt_plain (Z.neg p) + 1)now compute.Hp:0 <= 0Zsqrt_plain 0 * Zsqrt_plain 0 <= 0 < (Zsqrt_plain 0 + 1) * (Zsqrt_plain 0 + 1)p:positiveHp:0 <= Z.pos pZsqrt_plain (Z.pos p) * Zsqrt_plain (Z.pos p) <= Z.pos p < (Zsqrt_plain (Z.pos p) + 1) * (Zsqrt_plain (Z.pos p) + 1)now destruct Zsqrt as (s & r & Heq & Hint).p:positiveHp:0 <= Z.pos p(let (s, _) := Zsqrt (Z.pos p) (Pos2Z.is_nonneg p) in s) * (let (s, _) := Zsqrt (Z.pos p) (Pos2Z.is_nonneg p) in s) <= Z.pos p < ((let (s, _) := Zsqrt (Z.pos p) (Pos2Z.is_nonneg p) in s) + 1) * ((let (s, _) := Zsqrt (Z.pos p) (Pos2Z.is_nonneg p) in s) + 1)now elim Hp. Qed.p:positiveHp:0 <= Z.neg pZsqrt_plain (Z.neg p) * Zsqrt_plain (Z.neg p) <= Z.neg p < (Zsqrt_plain (Z.neg p) + 1) * (Zsqrt_plain (Z.neg p) + 1)
Positivity
forall n : Z, 0 <= n -> 0 <= Zsqrt_plain nforall n : Z, 0 <= n -> 0 <= Zsqrt_plain nn:Zm:0 <= nZsqrt_plain n * Zsqrt_plain n <= n -> n < (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1) -> 0 <= Zsqrt_plain nn:Zm:0 <= nH1:Zsqrt_plain n * Zsqrt_plain n <= nH2:n < (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)Zsqrt_plain n < 0 -> 0 <= Zsqrt_plain nn:Zm:0 <= nH1:Zsqrt_plain n * Zsqrt_plain n <= nH3:Zsqrt_plain n < 0(Zsqrt_plain n + 1) * (Zsqrt_plain n + 1) <= nn:Zm:0 <= nH1:Zsqrt_plain n * Zsqrt_plain n <= nH3:Zsqrt_plain n < 0(Zsqrt_plain n + 1) * (Zsqrt_plain n + 1) <= Zsqrt_plain n * Zsqrt_plain nring. Qed.n:Zm:0 <= nH1:Zsqrt_plain n * Zsqrt_plain n <= nH3:Zsqrt_plain n < 0Zsqrt_plain n * Zsqrt_plain n + (2 * Zsqrt_plain n + 1) = (Zsqrt_plain n + 1) * (Zsqrt_plain n + 1)
Direct correctness on squares.
forall a : Z, 0 <= a -> Zsqrt_plain (a * a) = aforall a : Z, 0 <= a -> Zsqrt_plain (a * a) = aa:ZH:0 <= aZsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * a -> a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1) -> Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:a <= Zsqrt_plain (a * a)Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:Zsqrt_plain (a * a) < aZsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:a <= Zsqrt_plain (a * a)Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:a < Zsqrt_plain (a * a)Zsqrt_plain (a * a) = aa:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:a < Zsqrt_plain (a * a)a * a < Zsqrt_plain (a * a) * Zsqrt_plain (a * a)apply Z.mul_lt_mono_pos_r; auto with zarith.a:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:a < Zsqrt_plain (a * a)a * Zsqrt_plain (a * a) < Zsqrt_plain (a * a) * Zsqrt_plain (a * a)a:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH2:a * a < (Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1)H3:Zsqrt_plain (a * a) < aZsqrt_plain (a * a) = aapply Z.mul_le_mono_nonneg; auto with zarith. Qed.a:ZH:0 <= aHaa:0 <= a * a -> 0 <= Zsqrt_plain (a * a)H1:Zsqrt_plain (a * a) * Zsqrt_plain (a * a) <= a * aH3:Zsqrt_plain (a * a) < a(Zsqrt_plain (a * a) + 1) * (Zsqrt_plain (a * a) + 1) <= a * a
Zsqrt_plain is increasing
forall p q : Z, 0 <= p <= q -> Zsqrt_plain p <= Zsqrt_plain qforall p q : Z, 0 <= p <= q -> Zsqrt_plain p <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p <= qZsqrt_plain p <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qZsqrt_plain p <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pZsqrt_plain p <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain p0 <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qZsqrt_plain p <= Zsqrt_plain qapply Zsqrt_plain_is_pos; auto with zarith.p, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain p0 <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qZsqrt_plain p <= Zsqrt_plain qp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qq <= pp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qq <= (Zsqrt_plain q + 1) * (Zsqrt_plain q + 1)p, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain q(Zsqrt_plain q + 1) * (Zsqrt_plain q + 1) <= pp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain q(Zsqrt_plain q + 1) * (Zsqrt_plain q + 1) <= pp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain q(Zsqrt_plain q + 1) * (Zsqrt_plain q + 1) <= Zsqrt_plain p * Zsqrt_plain pp, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qZsqrt_plain p * Zsqrt_plain p <= pcase (Zsqrt_interval p); auto with zarith. Qed.p, q:ZH1:0 <= pH2:p < qH3:Zsqrt_plain q < Zsqrt_plain pHp:0 <= Zsqrt_plain qZsqrt_plain p * Zsqrt_plain p <= p
Equivalence between Zsqrt_plain and Z.sqrt
forall n : Z, Zsqrt_plain n = Z.sqrt nforall n : Z, Zsqrt_plain n = Z.sqrt nn:ZZsqrt_plain n = Z.sqrt nn:Zl:0 <= nZsqrt_plain n = Z.sqrt nn:Zg:0 > nZsqrt_plain n = Z.sqrt nn:Zl:0 <= nZ.sqrt n = Zsqrt_plain nn:Zg:0 > nZsqrt_plain n = Z.sqrt nn:Zl:0 <= nZsqrt_plain n * Zsqrt_plain n <= n < Z.succ (Zsqrt_plain n) * Z.succ (Zsqrt_plain n)n:Zg:0 > nZsqrt_plain n = Z.sqrt nnow destruct n. Qed.n:Zg:0 > nZsqrt_plain n = Z.sqrt n