/* average.c
 *
 * Copyright 2018 Bruce Cowan <bruce@bcowan.me.uk>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdlib.h>
#include <math.h>

#include <glib.h>

#include <array.h>

static gdouble
get_total (const Array *array)
{
    double total = 0;
    size_t length = array_get_length (array);

    for (size_t i = 0; i < length; i++)
        total += (double) GPOINTER_TO_INT (array_get (array, i));

    return total;
}

static gdouble
get_average (const Array *array)
{
    return get_total (array) / array_get_length (array);
}

static Array *
create_array (size_t length)
{
    Array *array = array_new (NULL);

    for (size_t i = 1; i < length; i++)
        array_add (array, GINT_TO_POINTER (i));

    return array;
}

static void
expected_values (Array  *array,
                 double *total,
                 double *average)
{
    size_t n = array_get_length (array);
    gdouble sum = (n * (n+1)) / 2;

    if (total)
        *total = sum;

    if (average)
        *average = sum / n;
}

static void
test_total (void)
{
    Array *array = create_array (100);

    gdouble expected_total;
    gdouble total = get_total (array);
    expected_values (array, &expected_total, NULL);

    g_assert_cmpfloat (total, ==, expected_total);

    array_unref (array);
}

static void
test_average (void)
{
    Array *array = create_array (100);

    gdouble expected_average;
    gdouble average = get_average (array);
    expected_values (array, NULL, &expected_average);

    g_assert_cmpfloat (average, ==, expected_average);

    array_unref (array);
}

int
main (int    argc,
      char **argv)
{
    g_test_init (&argc, &argv, NULL);

    g_test_add_func ("/array/total", test_total);
    g_test_add_func ("/array/average", test_average);

    return g_test_run ();
}