/*
 * Swarthmore College, CS 31
 * Copyright (c) 2023 Swarthmore College Computer Science Department,
 * Swarthmore PA
 */

/*
 * Starting point for in-class problem:
 *  - find the maximum value in a set of N values using M threads
 *  - parallelize the finding the max part
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define MAX_M 64

// Restrict the range of values generated. You could set this to
// something small for testing for correctness.
#define MAX_RANGE 1000000;

// TODO: your thread main routine must match this prototype:
void *findmax(void *arg);

// TODO: global variables shared by all threads (add more as needed)
static long *values; // the array of values from which max is found
static long result;

// TODO: if you want some shared synchronization primitives, declare
// them here (you can also init them here too).  For example:
static pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;

// TODO: if you want to pass each thread's main function more than a single
// value, you should define a new struct type with field values for
// each argument you want to pass it
/*
struct app_data {

};
*/

// create the initial array of random values
void init_values(long *values, unsigned long n);

// print values to test for correctness (try with small values of n)
void print_values(long *values, unsigned long n);

/***************************************************************/
int main(int argc, char **argv) {

  int ntids, show_values;
  unsigned long n;

  if (argc != 4) {
    printf("usage: %s num_values num_threads print[0/1]\n", argv[0]);
    exit(1);
  }
  result = 0;
  n = atol(argv[1]);
  ntids = atoi(argv[2]);
  show_values = atoi(argv[3]);

  // make ntids a sane value as needed
  if (ntids < 1) { ntids = 1; }
  if (ntids > MAX_M) { ntids = MAX_M; }
  printf("%d threads finding max of %lu values\n", ntids, n);

  values = malloc(sizeof(long)*n);
  if (!values) {
    perror("malloc failed\n");
    exit(1);
  }

  init_values(values, n);

  if (show_values) {
    print_values(values, n);
  }

  // TODO: add your solution below







  printf("max value is: %ld\n", result);
  free(values);
  values = 0;
  exit(0);
}


// TODO: implement your thread main loop function here
void *findmax(void *arg) {

  return NULL; // temporary: you might want to change this
}

// inits an array to random values
//   values: the array to init
//   n: size of the array
void init_values(long *values, unsigned long n) {
  unsigned long i;

  // seed the random number generator: different values based on current time
  srand(time(0));
  for(i=0; i < n; i++) {
    values[i] = rand() % MAX_RANGE;  // let's just make these a sane range
  }
}


// prints out an array of values
//   values: the array to init
//   n: size of the array
void print_values(long *values, unsigned long n) {
  unsigned long i;
  for(i=0; i < n; i++) {
    printf("%6ld ", values[i]);
    if (i < (n-1) && ((i+1) % 10) == 0) {
      printf("\n");
    }
  }
  printf("\n");
}