/* Square Root by Newton's Method -- Version 2
   Functional Programming Example
   H. Conrad Cunningham, Professor Computer and Information Science
   University of Mississippi

   Developed for CSci 555, Functional Programming, Spring 2016

1234567890123456789012345678901234567890123456789012345678901234567890

2016-02-10: Developed from 2015 Elixir version 

Function sqrt computes the square root of its argument x using
Newton's method.  

I adapted this square root module from an Elixir version, which was,
in turn, adapted from a Lua version, which was, in turn, adapted from
the Scheme code in section 1.1.7 of Abelson and Sussman's Structure
and Interpretation of Computer Programs (SICP) textbook. I changed the
function names to better match the Scala naming convention.

I have only tested this code minimally.

Scala and functional programming highlights, version 2 relative to 1:
- Nests all other functions inside sqrt, hiding all but sqrt
- Returns last expression's value from sqrt
- Gives explicit return type for public function sqrt
- Uses type inference where possible for other return values

*/

object Sqrt {

  def sqrt(x: Double): Double = {

    // Tail recursive auxiliary function
    def sqrtIter(guess: Double, x: Double) : Double =
      if (isGoodEnough(guess,x))
        guess
      else
        sqrtIter(improve(guess,x),x)

    def isGoodEnough(guess: Double, x: Double) =
      Math.abs(square(guess)- x) < 0.001

    def square(x: Double) = x * x

    def average(x: Double, y: Double) = (x + y) / 2

    def improve(guess: Double, x: Double) = average(guess,x/guess)

    sqrtIter(1.0, x)
  }

  // Should implement extensive tesing externally
  def main(args: Array[String]) {
    println("square root of 9 is " + sqrt(9.0))
  }

}
