import java.util.*;

public abstract class DataFit {
    double[] parameter;
    double[][] covar;
    boolean[] isFitted;

    public DataFit(int n) {
	parameter = new double[n];
	covar = new double[n][n];
	isFitted = new boolean[n];
	Arrays.fill(isFitted, true);
    }

    public int size() { return parameter.length; }

    // Reset the fit
    public void reset() {
	Arrays.fill(parameter, 0.0);
	for(int i=0; i<parameter.length; i++) Arrays.fill(covar[i], 0.0);
    }

    public int countFitted() {
	int fitted = 0;
	for(int p=0; p<parameter.length; p++) if(isFitted[p]) fitted++;
	return fitted;
    } 

    public abstract double valueAt(double x);

    public abstract double varianceAt(double x);

    public double uncertaintyAt(double x) { return Math.sqrt(varianceAt(x)); }

    public abstract void fit(double[] x, double[] y, double[] sigma) throws IllegalStateException;
    
    public double getChiSquared(double[] x, double[] y, double[] sigma) {
	double chiSquared = 0.0;
	for(int i=0; i < x.length; i++) if(sigma[i] > 0.0) {
	    double chi = (valueAt(x[i]) - y[i]) / sigma[i];
	    chiSquared += chi * chi;
	}
	return chiSquared;
    }

    protected void covsrt() {	
	int mfit = countFitted();
	int ma = size();

	for(int i=mfit; i < ma; i++)
	    for(int j=0; j <= i; j++) { 
		covar[i][j]= 0.0; 
		covar[j][i]= 0.0;
	    }

	int k = mfit-1;
	for (int j=ma-1; j >= 0; j--) {
	    if(isFitted[j]) {
		for(int i=0; i < ma; i++) {
		    double temp = covar[i][k];
		    covar[i][k] = covar[i][j];
		    covar[i][j] = temp;
		}
		for(int i=0; i < ma; i++) {
		    double temp = covar[k][i];
		    covar[k][i] = covar[j][i];
		    covar[j][i] = temp;
		}
		k--;
	    }
	}
    }

}
