#include "benchmark.h"
#include "system.h"
#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "../sort/sort.h"
#include "../common/common.h"

static uint32_t sort_lock;

int _benchmark_sort (sort_t sort_type,
                     unsigned int size)
{
  printf(" * Size : %d\n",size);

  unsigned int* SortArray;
  
  int cycle_begin;

  int num_cpu=procnum();
  
  printf(" * Algo : %s\n",sort_str(sort_type));
  
  printf("   * Init...\n");
  
  lock_lock(&sort_lock);
  SortArray = (unsigned int*) malloc(size*sizeof(unsigned int));
  lock_unlock(&sort_lock);
  
  unsigned int seed = num_cpu;
  int i;
  for (i=0; i<size; ++i)
    {
      seed = seed * 1103515245 + 12345;
      SortArray[i] = seed&0xff;
    }
  printf("   * Sort... \n");
  
  cycle_begin = cpu_cycles();
  sort((unsigned int *) (SortArray), (unsigned int) size, sort_type);
  int cycle_exec = cpu_cycles()-cycle_begin;
  
  printf("   * Executed in %d cycles\n",cycle_exec);
  
  int result = cycle_exec;
  
#if VERIFICATION_SORT      
  printf("   * Verification... ");
  
  for (i = 1; i < size; i++)
    {
      /* printf("%d ",SortArray[i-1]); */
      
      if (SortArray[i] < SortArray[i-1])
        {
          printf("KO !!!\n");
          EXIT(1);
        }
    }
  printf("OK\n");
#endif
  
  free (SortArray);

  return result;
}

int _benchmark_sort_all (unsigned int size)
{
  printf("\n");
  printf("================================\n");
  printf("Benchmark Sort (ALL)\n");
  printf("================================\n");
  printf("\n");

  int result = 0;
  int num_cpu=procnum();
  sort_t _sort_type;
  const sort_t nb_sort_type = 4;
  
  for (_sort_type=0; _sort_type < nb_sort_type; _sort_type++)
    result += _benchmark_sort((_sort_type+num_cpu)%nb_sort_type,size);
  
  return result;
}

int _benchmark_sort_one (sort_t sort_type,
                         unsigned int size)
{
  printf("\n");
  printf("================================\n");
  printf("Benchmark Sort\n");
  printf("================================\n");
  printf("\n");

  return _benchmark_sort(sort_type,size);
}

int benchmark_sort_all       (void) { return _benchmark_sort_all(SORT_ALL_SIZE); }
int benchmark_sort_bubble    (void) { return _benchmark_sort_one(SORT_BUBBLE   ,SORT_BUBBLE_SIZE   ); }
int benchmark_sort_insertion (void) { return _benchmark_sort_one(SORT_INSERTION,SORT_INSERTION_SIZE); }
int benchmark_sort_selection (void) { return _benchmark_sort_one(SORT_SELECTION,SORT_SELECTION_SIZE); }
int benchmark_sort_shell     (void) { return _benchmark_sort_one(SORT_SHELL    ,SORT_SHELL_SIZE    ); }
