/****
 *
 * This program computes simple statistics for up to 1000 real numbers read
 * from standard input.  The numbers are read up to EOF or 1000 input values,
 * which ever occurs first.  The statistics computed are the sum of the
 * numbers, the arithmetic mean, and the standard deviation.  The results are
 * output to standard output, in the following form:
 *
 * Sum = 
 * Mean =
 * Standard Deviation =
 *
 * The precise formulae for mean and standard deviation are as defined here:
 *
 *    http://www.gcseguide.co.uk/statistics_and_probability.htm
 *
 *
 * Author: Gene Fisher (gfisher@calpoly.edu)
 * Created: 31mar11
 * Last Modified: 3apr11
 *
 */

#include <stdio.h>
#include <math.h>

#define MAX_DATA_POINTS 1000

/*
 * Declare the prototypes for functions used in the program.
 */
int read_values(double data[], int max);
double compute_sum(double data[], int n);
double compute_mean(double data[], int n);
double compute_std_dev(double data[], int n);

int main () {

    /*
     * Declare an array to hold the numbers, and an int for the number of
     * values read in.  Decclare a double to check if stdin is emmpty.
     */
    double data[MAX_DATA_POINTS];
    int n;
    double datum;

    /*
     * Prompt the user for the data values.  From the terminal, the user
     * generates an EOF by typing control-D.  If input is redirected from a
     * file, EOF is produced after the last value is read from the file.
     */
    printf(
        "Enter up to %d numeric values, terminating input with control-D:\n",
            MAX_DATA_POINTS);

    /*
     * Call the read_values function to read the numbers into the data array,
     * and return the number of values read.
     */
    n = read_values(data, MAX_DATA_POINTS);

    /*
     * Determine if there are any remaining data values on stdin, and tell the
     * user that they will be ignored.
     */
     if (scanf("%lf", &datum) != EOF) {
	printf("\n  NOTE: The program will use the first 1000 numbers only.\n\n");
    }

    /*
     * Compute and output the results.
     */
    printf("Sum = %f\n", compute_sum(data, n));
    printf("Mean = %f\n", compute_mean(data, n));
    printf("Standard Deviation = %f\n\n", compute_std_dev(data, n));

    return 0;

}

/*
 * Read up to max values from standard input, and put the values in the given
 * data array.  Return the number of values read, up to EOF or the given max,
 * whichever occurs first.  It is the caller's responsibility to ensure that
 * the given data array has at least max elements.
 */
int read_values(double data[], int max) {
    int i;
    for (i = 0; i < max && scanf("%lf", &data[i]) != EOF; i++)
        ;
    return i;
}

/*
 * Return the sum of the first n values of the given data array.
 */
double compute_sum(double data[], int n) {
    int i;
    double sum;
    for (i = 0, sum = 0; i < n; i++) {
	sum += data[i];
    }
    return sum;
}

/*
 * Return the arithmetic mean of the first n values of the given data array.
 */
double compute_mean(double data[], int n) {
    return compute_sum(data, n) / n;
}

/*
 * Return the standard deviation of the first n values of the given data array.
 */
double compute_std_dev(double data[], int n) {
    int i;
    double mean = compute_mean(data, n);
    double sum_squares = 0;

    for (i = 0; i < n; i++) {
	sum_squares += pow(data[i] - mean, 2);
    }

    return sqrt(sum_squares / (n - 1 ));
}


/***
 *
 * QUESTIONS:
 *
 *   1. How many lines would you have to change in the preceding program to
 *      have it compute stats for up to a 1000000 numbers?
 *
 *   2. There is an exquisitly subtle flaw in the following version of the for
 *      loop statement in read_values:
 *
 *          for (i = 0; scanf("%lf", &data[i]) != EOF && i < max; i++)
 *
 *      What is the flaw?  NOTE: This question will be on an upcoming quiz or
 *      exam!
 *
 *   3. Statistically, the median is the middle value in set of data points.
 *      Suppose I wanted to add a function compute_median.  What would it's
 *      implementation look like? 
 *
 */