/**
 * An Averager object calculates the moving average of (either all or
 * part of) a data array.
 *
 * Because this class implements the Runnable interface the code that
 * performs the calculations can be executed in a separate thread.
 *
 * Note: If constructed properly (if they work with disjoint subsets
 * of the array), multiple Averager objects can perform the
 * calculations on the same data array. This is because, though multiple
 * threads may read the same elements of the data array, multiple threads
 * will not write the same element. (Of course, this assumes that the
 * data array is not changed in any other thread after it is constructed.)
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */ 
public class Averager implements Runnable
{
    private double[]  data, result;
    private int       first, length, window;    

    /**
     * Explicit Value Constructor.
     *
     * @param window  The number of elements in the average
     * @param data    The data
     * @param first   The first element in the data array to process
     * @param length  The number of elements in the data array to process
     * @param result  The array that will hold the moving average
     */
    public Averager(int window, double[] data, int first, int length,
                    double[] result)
    {
        this.window  = window;
        this.data    = data;
        this.first   = first;
        this.length  = length;
        this.result = result;
    }
    
    /**
     * Calculate the moving average.
     */
    public void run()
    {
        // For each appropriate element in the data array
        int n      = first+length;
        int start  = Math.max(first, window-1);
        for (int i=start; i<n; i++)
        {
            // Calculate the average of the "previous" (including 
            // the current index) window number of elements
            double total = 0;
            int m = i - window + 1;
            for (int j=i; j>=m; j--)
            {
                total += data[j];
            }
            result[i] = total / (double)window;
        }
    }
}
