/*************************************************************************/
/* Program file name: Ex3_5.java                                         */
/*                                                                       */
/* © Tao Pang 2006                                                       */
/*                                                                       */
/* Last modified: June 15, 2006                                           */
/*                                                                       */
/* (1) This Java program is created for 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 2nd-order derivative through
// the adaptive scheme.

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

//  Evaluate the derivative and output the result
    int k = 0;
    for (int i=1; i<=n; ++i) {
      double x = h*i;
      double d = (f(x+h)-2*f(x)+f(x-h))/(h*h);
      double f2 = secondOrderDerivative(x, h, d, del, k, m);
      double df2 = f2-(f(x)-Math.exp(-x)/(x*x)-2*Math.exp(-x)/x);

      System.out.println("x = " + x);
      System.out.println("f''(x) = " + f2);
      System.out.println("Error in f''(x): " + df2);
    }
  }

// Method to carry out 2nd-order derivative through the
// adaptive scheme.

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

  public static double f(double x) {
    return Math.exp(-x)*Math.log(x);
  }
}
