```//
// Course: BU CAS CS 520
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//

(* ****** ****** *)

//
// How to compile:
//   atscc -o isqrt -O3 isqrt.dats
//
// How to test:
//   ./isqrt [integer]
//

(* ****** ****** *)

(*
// this one is buggy
fn 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
if x / m < m then search (x, l, m) else search (x, m, r)
end // end of [if]
| _ => l
end // end of [search]
in
search (x, 0, x)
end // end of [isqrt]
*)

fn isqrt {x:nat} (x: int x): int = let
fun search {x,l,r:nat | l <= r} .<r-l>. // invariant: x < r * r!!!
(x: int x, l: int l, r: int r): int = let
val diff = r - l
in
case+ 0 of
| _ when diff >= 2 => let
val m = l + (diff / 2)
in
if div_int_int (x, m) < m then search (x, l, m) else search (x, m, r)
end // end of [if]
| _ => l
end (* end of [search] *)
in
if x >= 2 then search (x, 0, x) else x
end // end of [isqrt]

implement main (argc, argv) = let
val () = assert (argc >= 2)
val n = int1_of argv.[1]
val () = assert (n >= 0)
in
printf ("isqrt (%i) = %i\n", @(n, isqrt n))
end // end of [main]

(* ****** ****** *)

(* end of [isqrt.dats] *)
```