/*
 * Newton.java by Richard J. Davies
 * from `Introductory Java for Scientists and Engineers'
 * chapter: `Numerical Computation'
 * section: `Newton's Method'
 *
 * This program solves the equation sin(x) - 1/2 = 0
 * it uses Newton's method to approach the root
 * more rapidly than by bisection.
 */
public class Newton
{
  // The starting point for Newton's method
  public static final double START = 0.5;

  // The closeness to f(x) = 0 that we want to obtain
  // before giving x as the root.
  public static final double CLOSENESS = 1e-14;

  // The maximum number of steps to take before
  // giving up.
  public static final double MAXSTEPS = 100;

  // A small number for use in numerical
  // derivatives.
  public static final double BIT = 1e-8;


  // The function that we are going to
  // find a root for.
  public static double f(double x)
  {
    return Math.sin(x) - 0.5;
  }


  // A numerical derivative of that
  // function
  public static double deriv(double x)
  {
    return (f(x+BIT) - f(x-BIT)) / (2*BIT);
  }


  // The `main' method actually implements
  // Newton's method.
  public static void main(String[] argv)
  {
    // Set up the starting point
    double x = START;
    int steps = 0;

    // And print it out
    System.out.println(x);

    // Until we are sufficiently close to a root...
    while((Math.abs(f(x)) > CLOSENESS) && (steps < MAXSTEPS))
    {
      // Iterate by Newton's method
      x = x - f(x) / deriv(x);

      // Print the new position and update the counter
      System.out.println(x);
      steps++;
    }

    System.out.println();

    // Print out the result
    if (steps<MAXSTEPS)
    {
      System.out.println("Root at x = " + x);

      // The eqn to solve was sin(x) - 1/2 = 0
      // so the root will be pi/6.
      System.out.println("So, pi is computed to be "
                         + 6*x);
      System.out.println(" And its real value is     "
                         + Math.PI);
    }
    else
      System.out.println("No convergence");
  }
}

