; Fieldtest fixture — Axis 3: Float comparison via the named-fn surface.
;
; Newton's method for sqrt: iterate x_{k+1} = (x_k + n/x_k) / 2 until
;   |x_{k+1} - x_k| < tol
; Reaches for `float_lt` (loop convergence) and `float_eq` (zero-arg
; guard against pathological 0.0 input). Also exercises Float
; arithmetic + Show Float via `print`.
;
; The interesting bit for the milestone is that there is no
; polymorphic `eq` / `lt` at Float — those would fail at typecheck
; with `NoInstance Eq Float`. The LLM-author has to reach for the
; named family `float_eq` / `float_lt` / `float_gt`. The shape mirrors
; how Rust's `f64::abs` / partial_cmp guides users toward bespoke
; Float-aware methods.
;
; abs implemented inline as `if x < 0 then -x else x` using float_lt.
;
; Expected stdout (one per line):
;   2 (sqrt 4.0)             ; 2.0
;   ~3.16 (sqrt 10.0)        ; 3.1622776601683795 — exact IEEE
;   0 (sqrt 0.0)             ; 0.0, short-circuit
;   1 (sqrt 1.0)             ; 1.0

(module eqord_3_newton_sqrt

  (fn fabs
    (doc "Float absolute value via the named-fn comparison surface.")
    (type (fn-type (params (own (con Float))) (ret (own (con Float)))))
    (params x)
    (body
      (if (app float_lt x 0.0)
        (app - 0.0 x)
        x)))

  (fn iterate
    (doc "Tail-recursive Newton iteration. Stops when |xnew - x| < tol.")
    (type (fn-type (params (own (con Float)) (own (con Float)) (own (con Float))) (ret (own (con Float)))))
    (params n x tol)
    (body
      (let xnew (app / (app + x (app / n x)) 2.0)
        (if (app float_lt (app fabs (app - xnew x)) tol)
          xnew
          (tail-app iterate n xnew tol)))))

  (fn sqrt
    (doc "sqrt n via Newton with initial guess 1.0 and tolerance 1e-10. Returns 0.0 for n == 0.0; assumes n >= 0.")
    (type (fn-type (params (own (con Float))) (ret (own (con Float)))))
    (params n)
    (body
      (if (app float_eq n 0.0)
        0.0
        (app iterate n 1.0 0.0000000001))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (app print (app sqrt 4.0))
      (seq (app print (app sqrt 10.0))
      (seq (app print (app sqrt 0.0))
           (app print (app sqrt 1.0))))))))
