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

void max(int *x, int nx, int *mx, int *whrmx) {
   *mx = x[0]; *whrmx = 0;
   for (int i = 1; i < nx; i++) 
      if (x[i] > *mx) {
         *mx = x[i];
         *whrmx = i;
      }
}

// inputs are the array x and its length, nx; outputs are the maximum
// value *mx and the index at which it occurs, whrmx
void wheremax(int *x, int nx, int *mx, int *whrmx) {
   int nth, chunk; 
   // the max values found in each chunk, and their indices within chunks
   int *maxvals, *maxivals;
   #pragma omp parallel
   {
      nth = omp_get_num_threads();
      #pragma omp single
      {
         maxvals = malloc(nth*sizeof(int));
         maxivals = malloc(nth*sizeof(int));
         chunk = nx / nth;
      }
      int me = omp_get_thread_num();
      // where my chunk starts
      int firsti = me * chunk;
      max(x+firsti,chunk,&maxvals[me],&maxivals[me]);
   }
   // combine the chunk info to get the overall answers 
   int whichchunk;
   max(maxvals,nth, mx, &whichchunk );
   *whrmx = whichchunk * chunk + maxivals[whichchunk];
}

int main() {
   int z[8] = {5,12,13,6,2,22,15,3};
   int m,wherem;
   omp_set_num_threads(4);
   wheremax(z,8,&m,&wherem);
   // should print out 22 and 5
   printf("the max value was %d\n",m);
   printf("it occurred at index %d\n",wherem);
}

