2 (** {1 Integer square root} *)
8 function sqr (x:int) : int = x * x
10 lemma sqr_non_neg: forall x:int. sqr x >= 0
13 forall x y:int. 0 <= x <= y -> sqr x <= sqr y
16 forall x y : int. sqr(x+y) = sqr x + 2*x*y + sqr y
18 predicate isqrt_spec (x res:int) =
19 res >= 0 /\ sqr res <= x < sqr (res + 1)
22 (** {2 Simple algorithm} *)
30 let isqrt (x:int) : int
32 ensures { isqrt_spec x result }
33 = let ref count = 0 in
36 invariant { count >= 0 }
37 invariant { x >= sqr count }
38 invariant { sum = sqr (count+1) }
46 ensures { result = 4 }
51 (** {2 Another algorithm, in the style of Newton-Raphson} *)
60 let sqrt (x : int) : int
62 ensures { isqrt_spec x result }
63 = if x = 0 then 0 else
66 let ref z = (1 + x) / 2 in
71 invariant { z = div (div x y + y) 2 }
72 invariant { x < sqr (y + 1) }
73 invariant { x < sqr (z + 1) }
76 (* A few hints to prove preservation of the last invariant *)
77 assert { x < sqr (z + 1)
81 so sqr (a + y + 1) <= sqr (2 * z + 2)
82 so 4 * (sqr (z + 1) - x)
83 = sqr (2 * z + 2) - 4 * x
84 >= sqr (a + y + 1) - 4 * x
85 > sqr (a + y + 1) - 4 * (a * y + y)
89 assert { y * y <= div x y * y