| Introduction to Programming in ATS: | ||
|---|---|---|
| <<< Previous | Introduction to Dependent Types | Next >>> |
Given an integer x >= 0, the integer square root of x is the greatest integer i satisfying i * i <= x. An implementation of the integer square root function is given as follows based on the method of binary search:
fun isqrt (x: int): int = let
fun search (x: int, l: int, r: int): int = let
val diff = r - l
in
case+ 0 of
| _ when diff > 0 => let
val m = l + (diff / 2)
in
// x < m * m is more efficient but can overflow easily
if x / m < m then search (x, l, m) else search (x, m, r)
end // end of [if]
| _ => l (* the result is found *)
end // end of [search]
in
search (x, 0, x)
end // end of [isqrt]
|
l * l <= x and x <= r * r must hold when search(x, l, r) is called.
Assume l * l <= x < r * r for some integers x, l, r. If a recursive call search(x, l1, r1) for some integers l1 and r1 is encountered in the body of search(x, l, r), then r1-l1 < r-l must hold. This invariant implies that search is terminating.
fun isqrt {x:nat}
(x: int x): int = let
fun search
{x,l,r:nat | l < r} .<r-l>.
(x: int x, l: int l, r: int r): int = let
val diff = r - l
in
case+ 0 of
| _ when diff > 1 => let
val m = l + (diff / 2)
in
if x / m < m then search (x, l, m) else search (x, m, r)
end // end of [if]
| _ => l (* the result is found *)
end // end of [search]
in
if x > 0 then search (x, 0, x) else 0
end // end of [isqrt]
|
By being precise and being able to enforce precision effectively, the programmer will surely notice that his or her need for run-time debugging is diminishing rapidly.
| <<< Previous | Home | Next >>> |
| Termination-Checking for Recursive Functions | Up | Datatype Refinement |