/* -*- c-file-style: "GNU" -*- */
/*
 * Copyright (C) CNRS, INRIA, Université Bordeaux 1, Télécom SudParis
 * See COPYING in top-level directory.
 */

# include <stdlib.h>
# include <stdio.h>
# include <time.h>
# include <omp.h>
#include <stdarg.h>

// Debugging part, print out only if debugging level of the system is verbose or more
int _debug = -77;

void debug(const char *fmt, ...) {
  if (_debug == -77) {
    char *buf = getenv("EZTRACE_DEBUG");
    if (buf == NULL)
      _debug = 0;
    else
      _debug = atoi(buf);
  }
  if (_debug >= 0) { // debug verbose mode
    va_list va;
    va_start(va, fmt);
    vfprintf(stdout, fmt, va);
    va_end(va);
  }
}
// end of debugging part

void fake_compute() {
  struct timeval t1, t2;
  gettimeofday(&t1, NULL);
  do {
    gettimeofday(&t2, NULL);
  } while(((t2.tv_sec-t1.tv_sec)*1e6)+(t2.tv_usec-t1.tv_usec) < 100000);
}

#define SIZE (1024*1024*8)

int main(void) {
  int i;
  int *A = malloc(sizeof(int) * SIZE);
  int *B = malloc(sizeof(int) * SIZE);
  int *C = malloc(sizeof(int) * SIZE);

  for (i = 0; i < SIZE; i++) {
    A[i] = i * 17 % 7;
    B[i] = i * 19 % 7;
    C[i] = 0;
  }

//compute for real!
  int j;
  for (j = 0; j < 3; j++) {
    debug("loop %d\n", j);
    debug("\trunning parallel for schedule(static)\n");
#pragma omp parallel
    {
#pragma omp for schedule(static)
      for (i = 0; i < SIZE; i++) {
	C[i] = A[i] + B[i];
      }

      fake_compute();

      debug("\trunning parallel for schedule(runtime)\n");
#pragma omp for schedule(runtime)
      for (i = 0; i < SIZE; i++) {
	C[i] = A[i] + B[i];
      }
      
      fake_compute();

      debug("\trunning parallel for schedule(dynamic)\n");
#pragma omp for schedule(dynamic)
      for (i = 0; i < SIZE; i++) {
	C[i] = A[i] + B[i];
      }
      
      fake_compute();

      debug("\trunning parallel for schedule(guided)\n");
#pragma omp for schedule(guided)
      for (i = 0; i < SIZE; i++) {
	C[i] = A[i] + B[i];
      }
      fake_compute();
    }
  }

  printf("C[3] = %d\n", C[3]);
  return 0;
}
