/*
 * Measure memory performance, using random and linear accesses
 *
 * (c) 2000 Marcel Waldvogel
 */


#include <stdio.h>
/* not error/Error.h, otherwise it might be taken from TIMEDIR/error/Error.h */
/* Needs to be included before Time.h, to prevent the definitions in */
/* Time.h's directory to be included by Time.h instead of these here */
#include "Error.h"
#include "Time.h"

/*
 * 2^{24}*(sqrt(5)-1)/2; according to Knuth ("Searching and Sorting"),
 * a "golden ratio" enumeration does its work most randomly.
 */
#define GOLDEN_STEPPING_16M 26544357    /* Bytes */
#define GOLDEN_STEPPING_16MI 6636089    /* Ints */

char buf[1<<24]; /* 2^{24} bytes */

int main(void)
{
    char a = 0;
    int i, b = 0;
    int *ptr=(int *)buf;
    
    TIME_VAR(ticks);

    /* Access memory once (make sure it is zero-filled) */
    i = 1<<24;
    a = 0;
    while (i-- > 0) {
        a += buf[i];
    }

    /* Integer sequential access */
    TIME_START(ticks);
    i = (1<<24)/sizeof(int);
    while (i-- > 0) {
        b += ptr[i];
    }
    TIME_PRINT(ecInt, ticks);

    /* Integer random access */
    TIME_START(ticks);
    i = 0;
    do{
        b += buf[i];
        i = (i + GOLDEN_STEPPING_16MI) & (((1<<24)/sizeof(int))-1); /* mod 2^20 */
    } while (i != 0);
    TIME_PRINT(ecRandomInt, ticks);

    /* Byte sequential access */
    TIME_START(ticks);
    i = 1<<24;
    while (i-- > 0) {
        a += buf[i];
    }
    TIME_PRINT(ecByte, ticks);

    /* Byte random access */
    TIME_START(ticks);
    i = 0;
    do{
        a += buf[i];
        i = (i + GOLDEN_STEPPING_16M) & ((1<<24)-1); /* mod 2^24 */
    } while (i != 0);
    TIME_PRINT(ecRandomByte, ticks);

    return a + b; /* Zero, but to make the compiler happy */
}

