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

#include <time.h>
#include <cmath>
#include <omp.h>
#include "timer.h"

int array[100000];

int number;
int overall;

// Fill the array with random data [0-10)
void fill ( )
{
	srand (time (NULL));

	for (int i=0; i<100000; i++)
	{
		array[i] = rand()%10;
	}
}

// OMP count
void countOMP ( )
{
	int i;

	// Try to make openMP behave in a decent manner
	omp_set_dynamic (0);
	omp_set_num_threads (number);

	// Tell openMP that this loop should be done in parallel
	#pragma omp parallel for reduction(+:overall)
	for (i=0; i<100000; i++)
	{
		if (array[i] == 3)
		{
			overall++;
		}
	}
}

// Standard sequential count 3's
void count ( )
{
	int i;

	for (i=0; i<100000; i++)
	{
		if (array[i] == 3)
		{
			overall++;
		}
	}
}

int main (int argc, char** argv)
{
    	int i, j;

	timer watch;

    	float total=0.0f;

    	number = i = 0;

	// Run the sequential
	for (j=0; j<100000; j++)
	{
		// Randomize the data set
	    	fill ( );

    		overall = 0;
    
		// Time a run

		watch.start ();

    		count ( );

    		watch.stop ();

		// Keep only the center runs
		if (j>1000 && j<99000)
		{
			total += watch.read ();
		}
	}

	printf ("%i\t%.3f\n", number, total/99000.0f);
	
	// OMP runs for 1-16 threads

	for (i=1; i<17; i++)
	{
        	total = 0.0f;

        	number = i;

        	for (j=0; j<100000; j++)
        	{
			// Randomize the input
			fill ( );

	        	overall = 0;

			// Time the run
    	    		watch.start ();

	        	countOMP ( );

	        	watch.stop ();

			// Keep only the middle values
			if (j>1000 && j<99000)
			{
				total += watch.read ();
			}
		}
		
		printf ("%i\t%.3f\n", number, total/99000.0f);
	}

	// Done!
	return 0;
}