/*
 * loop-swapping.c
 *
 * 1st assigment for the course ``Datenbanksysteme und moderne
 * CPU-Architekturen'' (Winter term 2006/07, TU Muenchen)
 *
 * Demonstrate the effect of hardware characteristics on two
 * nested loops that process a large array line- or column-wise.
 *
 * (c) Jens Teubner, TU Muenchen 2006.
 * slightly modified by Jan Rittinger, Uni Tuebingen 2009.
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>

int main (int argc, char **argv)
{
    unsigned int *src;        /* matrix */
    unsigned int rows, cols;  /* dimensions of the matrix */
    unsigned int r, c;        /* counters to iterate over the matrix */
    unsigned int sum1, sum2;  /* we compute the sum here */

    /* variables to measure execution times */
    struct timeval start, end;
    long time1, time2;

    /* simple check on soundness of command line arguments */
    if (argc != 3) {
        fprintf (stderr, "usage: %s rows columns\n", argv[0]);
        exit (EXIT_FAILURE);
    }

    /* interpret two arguments */
    rows = atoi (argv[1]);
    cols = atoi (argv[2]);

    /* allocate memory for the matrix */
    src = malloc (rows * cols * sizeof (*src));

    if (!src) {
        fprintf (stderr, "could not allocate memory\n");
        exit (EXIT_FAILURE);
    }

    /* initialize both tables with (pseudo) random values */
    for (r = 0; r < rows; r++)
        for (c = 0; c < cols; c++)
            src[r * cols + c] = (unsigned int) random ();

    /* ---------- loop combination 1 ---------- */

    /* remember start time */
    gettimeofday (&start, NULL);

    /* do the actual computation */
    sum1 = 0;
    for (r = 0; r < rows; r++)
        for (c = 0; c < cols; c++)
            sum1 += src[r * cols + c];

    /* get end time... */
    gettimeofday (&end, NULL);

    /* ...and compute the difference */
    time1 = ((end.tv_sec - start.tv_sec) * 1000000
        + (end.tv_usec - start.tv_usec))/1000;

    /* ---------- loop combination 2 ---------- */

    /* remember start time */
    gettimeofday (&start, NULL);

    /* do the actual computation */
    sum2 = 0;
    for (c = 0; c < cols; c++)
        for (r = 0; r < rows; r++)
            sum2 += src[r * cols + c];

    /* get end time... */
    gettimeofday (&end, NULL);

    /* ...and compute the difference */
    time2 = ((end.tv_sec - start.tv_sec) * 1000000
        + (end.tv_usec - start.tv_usec))/1000;

    /*
     * We're done with the work.  Now print statistical
     * information to stdout:
     *
     *  - sum computed by variant 1 - sum computed by variant 2 = 0
     *  - number of rows
     *  - number of columns
     *  - execution time variant 1
     *  - execution time variant 2
     *
     * (We are not actually interested in the sums computed.
     * Printing them out, however, avoids their computation
     * being optimized out by intelligent compilers.)
     */
    printf ("%u\rr %9u x c %9u -- rc %5lu cr: %5lu\n", sum1 - sum2, rows, cols, time1, time2);

    return EXIT_SUCCESS;
}

