package math;

import stdlib.Color;
import awt.Plot;


/*************************************************************************
 *  Compilation:  javac Catastrophic.java
 *  Execution:    java Catastrophic N
 *
 *  Plot fl(x) = (1 - cos x) / x^2 in the interval from
 *  -4 * 10^-8 to 4 * 10^-8. Catastrophic cancellation
 *  leads to extremely inaccurate values in this range.
 *  The true answer is approximately 0.5 for all x values
 *  in this range.
 *
 *  % java Catastrophic 10000
 *
 *************************************************************************/


public class Catastrophic {

    // compute f(x)  = (1 - cos x) / x^2 in floating point
    public static double fl(double x) {
        double a = Math.cos(x);
        double b = 1.0 - a;
        double c = b / (x*x);
        return c;
    }

    // compute f(x)  = (1 - cos x) / x^2 in floating point
    // compiler may produce more accurate results by using more precision than
    // IEEE requires
    public static double fl2(double x) {
        return (1.0 - Math.cos(x)) / (x*x);
    }

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

    public static void main(String[] args) { 
        // number of line segments to plot
        int N = Integer.parseInt(args[0]);


        // x-interval to plot
        double x0 = -4.0e-8;
        double x1 = +4.0e-8;
        
 	   Plot plot = new Plot();
        // rescale the coordinates
        plot.setXscale(x0, x1);
        plot.setYscale(-.1, 1.1);
        plot.show(0);

        double[] vals1 = new double[N+1];
        double[] vals2 = new double[N+1];
        double[] vals3 = new double[N+1];
        for (int i = 0; i <= N; i++) {
            vals1[i] = fl(x0 + (x1 - x0) * i / N);
            vals2[i] = fl2(x0 + (x1 - x0) * i / N);
            vals3[i] = f(x0 + (x1 - x0) * i / N);
        }
        plot.setPenColor(Color.BLACK);
        plot.lines(vals3);
        plot.setPenColor(Color.BLUE);
        plot.lines(vals1);
        plot.show(0);
   }

}
