Module Type NZSqrtUpProp
(Import A : NZDecOrdAxiomsSig')
(Import B : NZSqrt' A)
(Import C : NZMulOrderProp A)
(Import D : NZSqrtProp A B C).
(** * [sqrt_up] : a square root that rounds up instead of down *)
Local Notation "a ²" := (a*a) (at level 5, no associativity, format "a ²").
(** For once, we define instead of axiomatizing, thanks to sqrt *)
Definition sqrt_up a :=
match compare 0 a with
| Lt => S √(P a)
| _ => 0
end.
Local Notation "√° a" := (sqrt_up a) (at level 6, no associativity).
(** First, [sqrt_up] is non-negative *)
(** [sqrt_up] is a morphism *)
Instance sqrt_up_wd : Proper (eq==>eq) sqrt_up.
(** The spec of [sqrt_up] indeed determines it *)
(** [sqrt_up] is exact on squares *)
(** [sqrt_up] and successors of squares *)
(** Basic constants *)
(**  Links between sqrt and [sqrt_up] *)
(** [sqrt_up] is a monotone function (but not a strict one) *)
(** No reverse result for <=, consider for instance √°3 <= √°2 *)
(** When left side is a square, we have an equivalence for < *)
(** When right side is a square, we have an equivalence for <= *)
(** [sqrt_up] and multiplication. *)
(** Due to rounding error, we don't have the usual [√(a*b) = √a*√b] but only lower and upper bounds. *)
(** And we can't find better approximations in general. - The upper bound is exact for squares - Concerning the lower bound, for any c>0, take [a=b=c²+1], then [√°(a*b) = c²+1] while [P √°a = P √°b = c] *)
(** [sqrt_up] and successor : - the [sqrt_up] function climbs by at most 1 at a time - otherwise it stays at the same value - the +1 steps occur after squares *)

Lemma sqrt_up_eq_succ_iff_square : forall a, 0<=a ->
(√°(S a) == S (√°a) <-> exists b, 0<=b /\ a == b²).