; Fieldtest — Floats milestone, axis 1: numerical computation.
;
; Newton's method for sqrt(N): x_{k+1} = 0.5 * (x_k + N / x_k).
; Iterate a fixed 20 times — well past convergence for double-precision
; from a starting guess of N (always positive). Prints the result of
; sqrt(2.0). Expected stdout (one line): approximately 1.41421356...
;
; Exercises: Float literals, polymorphic +, *, /, recursion with
; Float-typed accumulator, io/print_float.

(module floats_1_newton_sqrt

  (fn newton_iter
    (doc "Recurse k times applying x' = 0.5 * (x + n/x).")
    (type
      (fn-type
        (params (con Float) (con Float) (con Int))
        (ret (con Float))))
    (params n x k)
    (body
      (if (app == k 0)
        x
        (tail-app newton_iter
          n
          (app * 0.5 (app + x (app / n x)))
          (app - k 1)))))

  (fn sqrt
    (doc "20-step Newton iteration starting from x0 = n.")
    (type (fn-type (params (con Float)) (ret (con Float))))
    (params n)
    (body (app newton_iter n n 20)))

  (fn main
    (type (fn-type (params) (ret (con Unit)) (effects IO)))
    (params)
    (body
      (do io/print_float (app sqrt 2.0)))))
