/*-----------------------------------------------------------*/
int testPingping(int sizeofBuffer,int dataSize){
	int otherPingRank, i, testFlag, reduceFlag;
	int *testBuf;

	/* initialise testFlag to true (test passed) */
	testFlag = TRUE;

	/* Testing only needs to be done by pingRankA & pingRankB */
	if (myMPIRank == pingRankA || myMPIRank == pingRankB){
		/* allocate space for testBuf */
		testBuf = (int *)malloc(sizeofBuffer * sizeof(int));

		/* set the ID of other pingRank */
		if (myMPIRank == pingRankA){
			otherPingRank = pingRankB;
		}
		else if (myMPIRank == pingRankB){
			otherPingRank = pingRankA;
		}

		/* construct testBuf array with correct values.
		 * These are the values that should be in finalRecvBuf.
		 */
#pragma omp parallel for default(none) \
	private(i) \
	shared(otherPingRank,numThreads,testBuf,dataSize,sizeofBuffer) \
	schedule(static,dataSize)
		for (i=0; i<sizeofBuffer; i++){
			/* calculate globalID of thread expected in finalRecvBuf
			 * This is done by using otherPingRank
			 */
			testBuf[i] = (otherPingRank * numThreads) + myThreadID;
		}

		/* compare each element of testBuf and finalRecvBuf */
		for (i=0; i<sizeofBuffer; i++){
			if (testBuf[i] != finalRecvBuf[i]){
				testFlag = FALSE;
			}
		}

		/* free space for testBuf */
		free(testBuf);
	}


	MPI_Reduce(&testFlag, &reduceFlag, 1, MPI_INT, MPI_LAND, 0, comm);

	/* Master process sets the testOutcome using testFlag. */
	 if (myMPIRank == 0){
		 setTestOutcome(reduceFlag);
	 }

	 return 0;
}
/*-----------------------------------------------------------*/
int testReduce(int bufferSize, int benchmarkType){
	int i, testFlag, reduceFlag;
	int correctReduce, lastGlobalID;

	/* Initialise correctReduce to 0.. */
	correctReduce = 0;
	/* ..and testFlag to true */
	testFlag = TRUE;

	/* set lastGlobalID */
	lastGlobalID = (numMPIprocs * numThreads);

	/* Now find correctReduce value by summing to lastGlobalID */
	for (i=0; i<lastGlobalID; i++){
		correctReduce = correctReduce + i;
	}

	/* Compare each element of finalRecvBuf to correctRedcue */
	for (i=0; i<bufferSize; i++){
		if (finalReduceBuf[i] != correctReduce){
			testFlag = FALSE;
		}
	}

	/* For allReduce, combine testFlag into master
	 * with logical AND.
	 */
	if (benchmarkType == ALLREDUCE){
		MPI_Reduce(&testFlag, &reduceFlag, 1, MPI_INT, MPI_LAND, 0, comm);
		/* then master sets testOutcome using reduceFlag */
		if (myMPIRank == 0){
			setTestOutcome(reduceFlag);
		}
	}
	else{
		/* for reduce master process just sets testOurcome using testFlag */
		setTestOutcome(testFlag);
	}

	return 0;
}
/*-----------------------------------------------------------*/
int testHaloexchange(int sizeofBuffer, int dataSize){
	int i;
	int testFlag, reduceFlag;
	int *testLeftBuf, *testRightBuf;

	/* set testFlag to true */
	testFlag = TRUE;

	/*allocate space for testLeftBuf and testRightBuf */
	testLeftBuf = (int *)malloc(sizeofBuffer * sizeof(int));
	testRightBuf = (int *)malloc(sizeofBuffer * sizeof(int));

	/*construct testLeftBuf and testRightBuf with correct values */
#pragma omp parallel for  \
	private(i) \
	shared(leftNeighbour,rightNeighbour,numThreads) \
	shared(dataSize,sizeofBuffer,testLeftBuf,testRightBuf) \
	schedule(static,dataSize)
	for (i=0; i<sizeofBuffer; i++){
		/* Calculate globalID of thread expected in finalLeftBuf.. */
		testLeftBuf[i] = (leftNeighbour * numThreads) + myThreadID;
		/* ..and in finalRightBuf. */
		testRightBuf[i] = (rightNeighbour * numThreads) + myThreadID;
	}

	/* Compare.. */
	for (i=0; i<sizeofBuffer; i++){
		/* 1) values from left neighbour */
		if (testLeftBuf[i] != finalLeftBuf[i]){
			testFlag = FALSE;
		}
		/* 2) values from right neighbour */
		if (testRightBuf[i] != finalRightBuf[i]){
			testFlag = FALSE;
		}
	}

	MPI_Reduce(&testFlag, &reduceFlag, 1, MPI_INT, MPI_LAND, 0, comm);

	/* Master then sets testOutcome flag */
	if (myMPIRank == 0){
		setTestOutcome(reduceFlag);
	}

	/* free space for testLeftBuf and testRightBuf */
	free(testLeftBuf);
	free(testRightBuf);

	return 0;
}