///////////////////////////////////////////////////////////////////////////
//                                                                       //
// Program file name: Deriv3.java                                        //
//                                                                       //
// © Tao Pang 2006                                                       //
//                                                                       //
// Last modified: January 18, 2006                                       //
//                                                                       //
// (1) This Java program is part of the book, "An Introduction to        //
//     Computational Physics, 2nd Edition," written by Tao Pang and      //
//     published by Cambridge University Press on January 19, 2006.      //
//                                                                       //
// (2) No warranties, express or implied, are made for this program.     //
//                                                                       //
///////////////////////////////////////////////////////////////////////////

// An example of evaluating 1st-order derivative through
// the adaptive scheme.

import java.lang.*;
public class Deriv3 {
  public static void main(String argv[]) {
    double del = 1e-6;
    int n = 10, m = 10;
    double h = Math.PI/(2*n);

//  Evaluate the derivative and output the result
    int k = 0;
    for (int i=0; i<=n; ++i) {
      double x = h*i;
      double d = (f(x+h)-f(x-h))/(2*h);
      double f1 = firstOrderDerivative3(x, h, d, del, k, m);
      double df1 = f1-Math.cos(x);
      System.out.println("x = " + x);
      System.out.println("f'(x) = " + f1);
      System.out.println("Error in f'(x): " + df1);
    }
  }

// Method to carry out 1st-order derivative through the
// adaptive scheme.

  public static double firstOrderDerivative3(double x,
    double h, double d, double del, int step,
    int maxstep) {
    step++;
    h = h/2;
    double d1 = (f(x+h)-f(x-h))/(2*h);
    if (step >= maxstep) {
      System.out.println ("Not converged after "
        + step + " recursions");
      return d1;
    }
    else {
      if ((h*h*Math.abs(d-d1)) < del) return (4*d1-d)/3;
      else return firstOrderDerivative3(x, h, d1, del, step,
        maxstep);
    }
  }

  public static double f(double x) {
    return Math.sin(x);
  }
}
