/*
Main method:
-generate random list
-time sequential quicksort
-time parallel quicksort
-time standard qsort
*/
int main(int argc, char *argv[])
{
  struct timeval start, end;
  double diff;

  srand(time(NULL));            //seed random
  int nbthread = THREAD_LEVEL;
  int NUM = DNUM;
  if (argc >= 2)                //user specified list size.
  {
    NUM = atoi(argv[1]);
    if (argc == 3)
    {
      nbthread = atoi(argv[2]);
    }
  }
  //Want to compare sorting on the same list,
  //so backup.
  double *lystbck = (double *) malloc(NUM * sizeof(double));
  double *lyst = (double *) malloc(NUM * sizeof(double));

  //Populate random original/backup list.
  for (int i = 0; i < NUM; i++) {
    lystbck[i] = 1.0 * rand() / RAND_MAX;
  }

  //copy list.
  memcpy(lyst, lystbck, NUM * sizeof(double));


  //Sequential mergesort, and timing.
  gettimeofday(&start, NULL);
  quicksort(lyst, NUM);
  gettimeofday(&end, NULL);

  if (!isSorted(lyst, NUM)) {
    printf("Oops, lyst did not get sorted by quicksort.\n");
  }
  //Compute time difference.
  diff = ((end.tv_sec * 1000000 + end.tv_usec)
          - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000.0;
  printf("Sequential quicksort took: %lf sec.\n", diff);



  //Now, parallel quicksort.

  //copy list.
  memcpy(lyst, lystbck, NUM * sizeof(double));

  gettimeofday(&start, NULL);
  parallelQuicksort(lyst, NUM, nbthread);
  gettimeofday(&end, NULL);

  if (!isSorted(lyst, NUM)) {
    printf("Oops, lyst did not get sorted by parallelQuicksort.\n");
  }
  //Compute time difference.
  diff = ((end.tv_sec * 1000000 + end.tv_usec)
          - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000.0;
  printf("Parallel quicksort took: %lf sec.\n", diff);



  //Finally, built-in for reference:
  memcpy(lyst, lystbck, NUM * sizeof(double));
  gettimeofday(&start, NULL);
  qsort(lyst, NUM, sizeof(double), compare_doubles);
  gettimeofday(&end, NULL);

  if (!isSorted(lyst, NUM)) {
    printf("Oops, lyst did not get sorted by qsort.\n");
  }
  //Compute time difference.
  diff = ((end.tv_sec * 1000000 + end.tv_usec)
          - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000.0;
  printf("Built-in quicksort took: %lf sec.\n", diff);

  free(lyst);
  free(lystbck);
  pthread_exit(NULL);
}
/*
Main method:
-generate random list
-time sequential quicksort
-time parallel quicksort
-time standard qsort
*/
int main(int argc, char *argv[])
{
  struct timeval start, end;
  double diff;

  srand(time(NULL));            //seed random

  int NUM = DNUM;
  int thread_lvl = THREAD_LEVEL;
  int opt;
  
  while( (opt = getopt(argc, argv, "hs:t:") ) != -1){
      switch(opt){
      case 'h':
          fprintf(stderr,"Usage: ./prog -s [array size] -t [thread level]\n");
          return 0;
      case 's':
          NUM = atoi(optarg);
          break;
      case 't':
          thread_lvl = atoi(optarg);
          break;
      default:
          break;
      }
  }
  
  /* if (argc == 2)                //user specified list size. */
  /* { */
  /*   NUM = atoi(argv[1]); */
  /* } */
  //Want to compare sorting on the same list,
  //so backup.
  double *lystbck = (double *) malloc(NUM * sizeof(double));
  double *lyst = (double *) malloc(NUM * sizeof(double));

  //Populate random original/backup list.
  for (int i = 0; i < NUM; i++) {
    lystbck[i] = 1.0 * rand() / RAND_MAX;
  }

  char* func_name[] = {"Sequential","Parallel","Built-in"};
  shuffle(3, func_name);

  int i;
  for(i = 0; i < 3; i++){
      //copy list.
      memcpy(lyst, lystbck, NUM * sizeof(double));
      
      if(strcmp(func_name[i], "Sequential")){
          gettimeofday(&start, NULL);
          quicksort(lyst, NUM);
          gettimeofday(&end, NULL);
      }
      else if(strcmp(func_name[i], "Parallel")){
          gettimeofday(&start, NULL);
          parallelQuicksort(lyst, NUM, thread_lvl);
          gettimeofday(&end, NULL);
      }
      else{
          gettimeofday(&start, NULL);
          qsort(lyst, NUM, sizeof(double), compare_doubles);
          gettimeofday(&end, NULL);
      }

      if (!isSorted(lyst, NUM)) {
          printf("Oops, lyst did not get sorted by %s quicksort.\n", func_name[i]);
      }

      //Compute time difference.
      diff = ((end.tv_sec * 1000000 + end.tv_usec)
              - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000.0;
      printf("%s quicksort took: %lf sec.\n", func_name[i],diff);
  }
  
  free(lyst);
  free(lystbck);
  pthread_exit(NULL);
}