// Simpson's Rule: I = dx/3 { (f(a) + f(b)) + 2 * sum_k f(x_2k) + 4 sum_k f(x_2k-1)
// has error ~ (b-a) f^4(c) / 180 * dx^4 where a < c < b 
// step-by-step dI = dx/3 (f(x0) + 4f(x1) + f(x2));

public final class ConfidenceCalculator {
    static double accuracy = 1.0e-4;

    static double getOutsideProbability(double x) {
	x = Math.abs(x);
	
	// dE ~ dx^4
	
	double dx = 0.01 * Math.pow(accuracy, 0.25);
	
	double Q = 0.0, x1;
	for(x1=maxX; x1 > x; x1-=dx) Q += getdI(x1, dx);	   	    
	Q += getdI(x, x1+dx-x);	    
	
	return Q;
    }    

    static double getConfidence(double x) {
	return 1.0 - getOutsideProbability(x);
    }


    static double getSigma(double confidence) {

	double dx = 0.01 * Math.pow(accuracy, 0.25);

	double I=1.0, x1 = maxX;
	while(I > confidence) {
	    I -= getdI(x1, dx);
	    x1 -= dx;
	}
	x1 += dx;

	return x1;
    }    


    static double getdI(double x, double dx) {
	return dx / 3.0 * (P(x-dx) + 4.0*P(x) + P(x+dx));
    }


    static double P(double x) {
	return A * Math.exp(-x*x / 2.0);
    }

    static double A = 0.5 * Math.sqrt(0.5 / Math.PI);
    static double maxX = 100.0;
}
