// (C)2007 Attila Kovacs <attila@submm.caltech.edu>

public final class ArrayExtras {

    public static double[] stretch(double[] data, int n) {
	double[] stretched = new double[data.length * n];
	for(int i=0; i<data.length; i++) stretched[n*i] = data[i];
	return stretched;
    }

    public static double[] shrink(double[] data, int n) {
	double[] shrunk = new double[data.length/n];
	for(int i=0; i<shrunk.length; i++) shrunk[i] = data[n*i];
	return shrunk;
    }

    public static double[] boxcar(double[] data, int n) {
	double[] smoothed = new double[data.length];
	double sum = 0.0;
	int nans = 0;

	for(int i=0; i<n; i++) {
	    if(Double.isNaN(data[i])) nans++;
	    else sum += data[i];
	}

	for(int i=n,j=0; i<data.length; i++,j++) {	  
	    smoothed[j] = nans > 0 ? Double.NaN : sum;

	    if(Double.isNaN(data[i])) nans++;
	    else sum += data[i];

	    if(Double.isNaN(data[j])) nans--;
	    else sum -= data[j];
	}
	smoothed[data.length-n] = sum;

	for(int i=data.length-n+1; i<data.length; i++) smoothed[i] = Double.NaN;
	
	return smoothed;
    }

    public static double[] shift(double[] data, int n) {
	if(n>0) {
	    for(int to=data.length-1, from=to-n; from > 0; to--, from--)
		data[to] = data[from];
	    for(int i=0; i<n; i++) data[i] = Double.NaN;
	}
	else {
	    for(int to=0, from=n; from < data.length; to++, from++)
		data[to] = data[from];
	    for(int i=data.length-1-n; i<data.length; i++) data[i] = Double.NaN;
	}
	
	return data;
    }


    public static double[] shift(double[] data, double d, double accuracy) {
	int n = (int) Math.round(1.0/accuracy);
	int dN = (int) Math.round(d/accuracy);
	return shrink(shift(boxcar(stretch(data, n), n), dN), n);
    }

}