/***************************************************************************
 *   Copyright (C) 2009 by Paul Lutus                                      *
 *   lutusp@arachnoid.com                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

package plcalc;

import javax.swing.*;

/**
 *
 * @author lutusp
 */
public class Statistics {

    PLCalcMainPanel parent;
    static double epsilon = 1e-16;
    double[] defaults = {100,15,1,85,115};
    double[] vals;
    JTextField[] statFields;

    public Statistics(PLCalcMainPanel p) {
        parent = p;
        statFields = new JTextField[] {parent.MeanField,parent.SDField,parent.PopField,parent.aField,parent.bField};
        vals = new double[statFields.length];
        for(int i = 0;i < defaults.length;i++) {
            statFields[i].setText(parent.specialFormat(parent.getCurrentFormat(),defaults[i]));
        }
    }

    void getVals() {
       for(int i = 0;i < statFields.length;i++) {
           vals[i] = parent.getNum(statFields[i]);
           statFields[i].setText(parent.specialFormat(parent.getCurrentFormat(),vals[i]));
       }
    }

    double erfc(double z) {
        if (z == 0.0) {
            return 1.0;
        }
        if (Math.abs(z) < 2.2) {
            return 1.0 - erf(z);
        }
        if (z < 0.0) {
            return 2.0 - erfc(-z);
        }
        double n1 = 1.0;
        double d1 = z;
        double n2 = z;
        double d2 = z * z + 0.5;
        double v = d1 / d2;
        double n = 1.0;
        double t;
        double ov;
        do { // use continued fraction method
            t = n1 * n + d1 * z;
            n1 = d1;
            d1 = t;
            t = n2 * n + d2 * z;
            n2 = d2;
            d2 = t;
            n += 0.5;
            ov = v;
            v = d1 / d2;
        } while (Math.abs(ov - v) >= epsilon);
        return v * Math.exp(-(z * z)) / Math.sqrt(Math.PI);
    }

    double erf(double z) {
        if (z == 0.0) {
            return z;
        }
        if (Math.abs(z) > 2.2) {
            return 1.0 - erfc(z);
        }
        double sgn = (z < 0) ? -1.0 : 1.0;
        z = Math.abs(z);
        double t = z;
        double v = z;
        double zsq = z * z;
        double ov;
        int i = 1;
        do {
            ov = v;
            t = -t * zsq / i;
            v += t / (2 * i + 1);
            i++;
        } while (Math.abs(ov - v) >= epsilon);
        return sgn * v * 2.0 / Math.sqrt(Math.PI);
    }

    // mean, standard deviation, population size, a, b
    double erfint(double m, double sd, double p, double a, double b) {
        if (sd == 0) {
            parent.setStatus("Standard Deviation cannot be zero.", true);
        }
        double q = Math.sqrt(2.0) * sd;
        double av = erf((a - m) / q);
        double bv = erf((b - m) / q);
        return p * 0.5 * (bv - av);
    }

    public void process() {
        parent.setStatus("OK", false);
        //double m, sd, p, a, b;
        getVals();
        double result = erfint(vals[0],vals[1],vals[2],vals[3],vals[4]);
        String s = parent.specialFormat(parent.getCurrentFormat(),result);
        //String s = parent.specialFormat("%.16g", result);
        parent.resultField.setText(s);
    }
}
