#include <sys/time.h>
#include <math.h>       /* for sin, exp etc.           */
#include <stdio.h>      /* standard I/O                */
#include <string.h>     /* for strcpy - 3 occurrences  */
#include <stdlib.h>     /* for exit   - 1 occurrence   */
#include <time.h>
#include <ctype.h>
//#include "../threading.h"
#define NUM_THREADS 16



/*#define enable_threading 1 uncomment for threading 
#ifdef enable_threading
#include <pthread.h>
#endif
*/

char e2[32500]; /* ~64MB array with 1 byte char systems */
int ae1 = 32500;
double e3[4096];
int ae2 = 4096;

//char e2[16250]; /* ~32MB */
//int ae1 = 16250;
//double e3[2048];
//int ae2 = 2048;

struct timeval starttime,endtime;
#define LOOPS 16

/* char alphabet1[26]; */

/* setup the array with the alphabet */
/* abcdefghijklmnopqrstuvwxyz */
char alphabet1[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
double te0, te1, te2; 
double prob0, prob1;
double lsalu;
long testno;
int i;

/* Converting between lower/uppercase */
int Problem0() {
        printf("\nRunning ALU tests (2 for now):\n");
	printf("\tPreparing test #1. setting up char array...\n");	
		for(i=0; i < ae1; i++) {  
			e2[i] = alphabet1[i % 26]; 
			}


		printf("\tdone.\n");
	//	printf("0 =: %c\n", e2[0]);
	//	printf("32499 =: %c\n", e2[32499]);
	//	printf("26 =: %c\n", e2[26]);
	//	e2[0]=(char)toupper((int)e2[0]);
	//	printf("0 =: %c\n", e2[0]);
	//	e2[0]=(char)tolower((int)e2[0]);
	//	printf("0 =: %c\n", e2[0]); 
/*		
		printf("\tTest running...\n\n");
//		gettimeofday(&starttime, NULL);

		for(testno=0; testno<LOOPS; testno++) {
        		for(i=0;i<strlen(e2);i++){
        			e2[i]=(char)toupper((int)e2[i]);
        		}
        		for(i=0;i<strlen(e2);i++){
        			e2[i]=(char)tolower((int)e2[i]);
        		}
		}	


// was all out next 6 lines	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te1 = LOOPS * ae1 * 2 / te0;
        printf("\tTest #1:\t ctype.h case modification: %lf/s\n\n", te1);
	prob0 = LOOPS * ae1 * 2  / te0;
return prob0;
*/


return 0;
}

/* Random number generation performance */ 
int Problem1() {
	printf("\tPreparing test #2. setting up double array...\n");
		for(i=0; i < ae2; i++) {
			e3[i] = 1;
               }
		printf("\tdone.\n");
/*                printf("\tTest running...\n\n");
//                gettimeofday(&starttime, NULL);

                for(testno=0; testno<LOOPS; testno++) {

			srand(testno);			
                        for(i=0;i<ae2-1;i++){
				e3[i]=rand();
                        }
                       
		}

// 6 lines out        gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        te2 = LOOPS * ae2 / te0;
        printf("\tTest #2:\t random number generation by stdlib.h: %lf/s\n", te2);
        prob1 = LOOPS * ae2 / te0 / 39;
return prob1;
*/
return 0;
}





#ifdef enable_threading
void *BusyWork(void *null)
{
               // for(testno=0; testno<LOOPS; testno++) {
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)toupper((int)e2[i]);
                        }
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)tolower((int)e2[i]);
                        }
                


                        srand(testno);
                        for(i=0;i<ae2-1;i++){
                                e3[i]=rand();
                        }


                //for(testno=0; testno<LOOPS; testno++) {
 
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)toupper((int)e2[i]);
                        }
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)tolower((int)e2[i]);
                        }
   
                        srand(testno);
                        for(i=0;i<ae2-1;i++){
                                e3[i]=rand();
                        }



                //}
   pthread_exit((void *) 0);
}
#endif


int Problem2() {
                for(testno=0; testno<LOOPS; testno++) {




                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)toupper((int)e2[i]);
                        }

                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)tolower((int)e2[i]);
                        }
                 
                        srand(testno);
                        for(i=0;i<ae2-1;i++){
                                e3[i]=rand();
                        }

                //for(testno=0; testno<LOOPS; testno++) {


                  
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)toupper((int)e2[i]);
                        }
                   
                        for(i=0;i<strlen(e2);i++){
                                e2[i]=(char)tolower((int)e2[i]);
                        }

                        srand(testno);
                        for(i=0;i<ae2-1;i++){
                                e3[i]=rand();
                        }




                }



}








int main(int argc, char *argv[]){
FILE *fp;

        Problem0();
        Problem1();


#ifdef enable_threading
   pthread_t thread[NUM_THREADS];
   pthread_attr_t attr;
   int a, t, s;

   /* Initialize and set thread detached attribute */
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        gettimeofday(&starttime, NULL);
   for(t=0; t<NUM_THREADS; t++)
   {
     // printf("Creating thread %d\n", t);
      a = pthread_create(&thread[t], &attr, BusyWork, NULL);   
 } 

   pthread_attr_destroy(&attr);
   for(t=0; t<NUM_THREADS; t++)
   {
      a = pthread_join(thread[t], (void **)&s);
      //printf("Completed join with thread %d s= %d\n",t, s);
   }
        gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        //te6 = 4 * ae * x100 / te0;
        lsalu=200/te0;
//        printf("\n\tTEST TIME MULTI THREAD:\t%lf/s\n", lsalu);
                
#else   
        gettimeofday(&starttime, NULL);

	Problem2();

        gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
        //te6 = 4 * ae * x100 / te0;
        lsalu=200/te0;
//        printf("\n\tTEST TIME MULTI THREAD:\t%lf/s\n", lsalu);

#endif



//lsalu = (prob1 + prob0) / 80000 * 1.1;
fp=fopen("aludir/lsalu.log", "w");
fprintf(fp, "%f\n", lsalu);
fclose(fp);

printf("DONE.\n");
return (0);
}
