/* Square Root by Newton's Method -- Version 1
   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:
- Uses object to define a module
- Uses type inference as much as possible (But I suggest it is 
  better to give return types for public functions.)
- Requires return type for sqrtIter because it is recursive
- Makes all functions visible.  Should hide all but sqrt.
- Uses tail recursion
- Calls Math.abs.

*/

object Sqrt {

  def sqrt(x: Double) = sqrtIter(1.0, x)

  // 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 improve(guess: Double, x: Double) = average(guess,x/guess)

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

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

}
