
/*

Name:

UTEID:


Here you should replace this comment with up to 60 lines describing
your results.  Remember to describe your approach for your
``initialize_slow_chase'' routine.

*/


#include "stdio.h"
#include "stdlib.h"
#include "time.h"

#define PAGE               (4096) // 2^12
#define LOG_ARRAY_SIZE     (12)   // For chase32, 5 is minimum shift amount
#define MAX_LOG_ARRAY_SIZE (30)   // Max log of array size
#define ARRAY_SIZE         (1 << (MAX_LOG_ARRAY_SIZE)) // Size of array

#define REPEAT             (16)   // Repeat experiment


void initialize_fast_chase( long int ar[], long int size ) {
  // Simple initialization
  long int i;

  for( i= 0; i < size-1; i++ )
    ar[ i ] = i+1;
  // Loop back to first array location
  ar[ size-1 ] = 0;
  }

// Simple, three, 4K-page array initialization.

//   Page 0  Page 1  Page 2
//  +-------+-------+-------+
//  |     0 |   512 |  1024 |
//  |     1 |   513 |  1025 |
//  |     2 |   514 |  1026 |
//  |   ... |   ... |   ... |
//  |   510 |  1022 |  1534 |
//  |   511 |  1023 |     0 |
//  +-------+-------+-------+


void initialize_slow_chase( long int ar[], long int size ) {

  // Here is where you put your initialization code that results in
  // the slowest possible execution for the ``chase32''  // routine.

  initialize_fast_chase( ar, size );  // To be replaced...
  }


long int chase( long int ar[], long int start, long int sum ) {
  // Routine not used, but it might serve as a useful reference.

  long int i = start;

  do {
    i = ar[i];
    sum = sum + i;
    }
  while( i );

  return sum;
}


long int chase32( long int ar[], long int start, long int xor_sum ) {
  long int i = start;

  do {
    i = ar[i];   //  1
    i = ar[i];   //  2
    i = ar[i];   //  3
    i = ar[i];   //  4
    i = ar[i];   //  5
    i = ar[i];   //  6
    i = ar[i];   //  7
    i = ar[i];   //  8

    i = ar[i];   //  9
    i = ar[i];   // 10
    i = ar[i];   // 11
    i = ar[i];   // 12
    i = ar[i];   // 13
    i = ar[i];   // 14
    i = ar[i];   // 15
    i = ar[i];   // 16

    i = ar[i];   // 17
    i = ar[i];   // 18
    i = ar[i];   // 19
    i = ar[i];   // 20
    i = ar[i];   // 21
    i = ar[i];   // 22
    i = ar[i];   // 23
    i = ar[i];   // 24

    i = ar[i];   // 25
    i = ar[i];   // 26
    i = ar[i];   // 27
    i = ar[i];   // 28
    i = ar[i];   // 29
    i = ar[i];   // 30
    i = ar[i];   // 31
    i = ar[i];   // 32

    // Next line included so GCC doesn't optimize the entire function away.
    xor_sum = xor_sum ^ i;
    }

    while( i );

  return xor_sum;
}


int main( int argc, char *argv[], char *env[] ) {

  long int i, step, log_size;
  long int array_size, result;

  clock_t clock_start_time;
  clock_t clock_stop_time;
  clock_t elasped_time;
  double cpu_time;

// For MacOS
  long int * ar = valloc( ARRAY_SIZE * sizeof(long int) );


//  For Linux
//  long int * ar = aligned_malloc( ARRAY_SIZE * sizeof(long int) );

  for( array_size = (1 << LOG_ARRAY_SIZE);
       array_size <= ARRAY_SIZE;
       array_size = array_size + array_size ) {

    printf( "The variable array_size is:  %lu.\n", array_size );

    // Fast-chase initialization
    initialize_fast_chase( ar, array_size );

    // The starting time
    clock_start_time = 0;
    clock_stop_time = 0;

    clock_start_time = clock( );

    // Run the fast-chase tests...
    for( i=0; i < REPEAT; i++ ) result = chase32( ar, 0, 4321 );

    // Print the result so the compiler doesn't optimize away the code
    // we are trying to measure.

    // The ending time
    clock_stop_time = clock( );
    elasped_time = clock_stop_time - clock_start_time;
    cpu_time = ((double) elasped_time) / ((double) CLOCKS_PER_SEC);

    printf( "Fast: result = %8ld,  elasped_time = %8ld,  elapsed %9f.\n",
            result, step, cpu_time );


    // Fast-chase initialization
    initialize_slow_chase( ar, array_size );

    // The starting time
    clock_start_time = 0;
    clock_stop_time = 0;

    clock_start_time = clock( );

    // Run the fast-chase tests...
    for( i=0; i < REPEAT; i++ ) result = chase32( ar, 0, 4321 );

    // Print the result so the compiler doesn't optimize away the code
    // we are trying to measure.

    // The ending time
    clock_stop_time = clock( );
    elasped_time = clock_stop_time - clock_start_time;
    cpu_time = ((double) elasped_time) / ((double) CLOCKS_PER_SEC);

    printf( "Slow: result = %8ld,  elasped_time = %8ld,  elapsed %9f.\n",
            result, step, cpu_time );

   }

//  for( i=0; i < ARRAY_SIZE; i++ )
//    printf( "ar[%3ld] = %3ld.\n", i, ar[i] );

  printf( "Finished.\n" );

}


//  Comment the next two lines when ARRAY_SIZE gets large...
//    for( i=0; i < array_size; i++ )
//      printf( "ar[%3ld] = %3ld.\n", i, ar[i] );
