;; newton.hs — Newton's method for square root.
;; Source: classic numerical analysis exercise.
;;
;; Exercises Phase 10: `Float`, `abs`, `/`, iteration via `until`.

(define
  hk-prog-val
  (fn
    (src name)
    (hk-deep-force (get (hk-eval-program (hk-core src)) name))))

(define
  hk-newton-source
  "improve x guess = (guess + x / guess) / 2\n\ngoodEnough x guess = abs (guess * guess - x) < 0.0001\n\nnewtonSqrt x = newtonHelp x 1.0\n\nnewtonHelp x guess = if goodEnough x guess\n                       then guess\n                       else newtonHelp x (improve x guess)\n")

(hk-test
  "newton.hs — newtonSqrt 4 ≈ 2"
  (hk-prog-val
    (str hk-newton-source "r = abs (newtonSqrt 4.0 - 2.0) < 0.001\n")
    "r")
  (list "True"))

(hk-test
  "newton.hs — newtonSqrt 9 ≈ 3"
  (hk-prog-val
    (str hk-newton-source "r = abs (newtonSqrt 9.0 - 3.0) < 0.001\n")
    "r")
  (list "True"))

(hk-test
  "newton.hs — newtonSqrt 2 ≈ 1.41421"
  (hk-prog-val
    (str hk-newton-source "r = abs (newtonSqrt 2.0 - 1.41421) < 0.001\n")
    "r")
  (list "True"))

(hk-test
  "newton.hs — improve converges (one step)"
  (hk-prog-val (str hk-newton-source "r = improve 4.0 1.0\n") "r")
  2.5)

(hk-test
  "newton.hs — newtonSqrt 100 ≈ 10"
  (hk-prog-val
    (str hk-newton-source "r = abs (newtonSqrt 100.0 - 10.0) < 0.001\n")
    "r")
  (list "True"))

{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
