#include <stdio.h>      /* standard I/O                */
#include <string.h>     /* for strcpy - 3 occurrences  */
#include <stdlib.h>     /* for exit   - 1 occurrence   */
#include <math.h>       /* for sin, exp etc.           */

struct timeval starttime,endtime;
double te0,te1,te2,te3,te4,te5,te6,te7;
double e1[4096]; /* 64MB array with 8 byte double systems */
long ae = 4096;
int n;
double ip;
double t = 0.49999975;
double t0 = 0.49999975;
double t1 = 0.50000025;
double t2 = 2.0;
double lsfpu;
double x,y,z;
long i,ix,j,k,l;
double pass0,pass1,pass2,pass3,pass4,pass5,pass6,pass7;
long x100 = 100;
long xtra = 100;
long n1;
long n2;
long n3;
long n4;
long n5;
long n6;
long n7;
long n8;
long n1mult;
void pa(double e[4], double t, double t2);	
void p3(double *x, double *y, double *z, double t, double t1, double t2);
void po(double e1[4], long j, long k, long l);

double Section1() {
	        /* Section 1, Math: general math.h capabilities*/
	/* double_size=sizeof(double); */
        /* asize=1024*1024/double*mt; how many longs then in one array? */
	printf("\n\tPreparing test. Setting up a 64MB array and assigning arbitrary values....");
	for (ix=0; ix<(ae-1); ix++) {
		e1[ix] = 1.3333;
		e1[ix+1] = 8.9273;
		e1[ix+2] = 2361.24521;
		e1[ix+3] = 902521468.102937;
		e1[ix+4] = 5823.443;
                e1[ix+5] = 17.8;
                e1[ix+6] = 281621463.4121727;
                e1[ix+7] = 77321.81;
		ix=ix + 7;
	}
	printf("\n\tdone.");
	printf("\n\tTest running....\n");
	                /* Simple add/sub/mult/div functions 511 passes to fill array 8 at a time to increase randomness of numbers*/
	
        for(i=0; i<1; i++)	
		{	
	gettimeofday(&starttime, NULL);
        for (ix=0; ix<(ae-1); ix++) 
                {
		e1[ix+7] = e1[ix] + e1[ix+1] - e1[ix+2] * e1[ix+3] / e1[ix+4] + e1[ix+1] - e1[ix+2] * e1[ix+3] / e1[ix+4];
		e1[ix+6] = e1[ix+7] + e1[ix+6] - e1[ix+5] * e1[ix+4] / e1[ix+3] + e1[ix+6] - e1[ix+5] * e1[ix+4] / e1[ix+3];
		e1[ix+5] = e1[ix+6] + e1[ix+7] - e1[ix+6] * e1[ix+7] / e1[ix+6] + e1[ix+7] - e1[ix+6] * e1[ix+7] / e1[ix+6];
                e1[ix+4] = e1[ix+5] + e1[ix+6] - e1[ix+7] * e1[ix+5] / e1[ix+6] + e1[ix+6] - e1[ix+7] * e1[ix+5] / e1[ix+6];
                e1[ix+3] = e1[ix+4] + e1[ix+7] - e1[ix+5] * e1[ix+6] / e1[ix+5] + e1[ix+7] - e1[ix+7] * e1[ix+6] / e1[ix+5];
                e1[ix+2] = e1[ix+5] + e1[ix+4] - e1[ix+6] * e1[ix+3] / e1[ix+4] + e1[ix+3] - e1[ix+6] * e1[ix+7] / e1[ix+4];
                e1[ix+1] = e1[ix+6] + e1[ix+5] - e1[ix+2] * e1[ix+4] / e1[ix+3] + e1[ix+7] - e1[ix+5] * e1[ix+4] / e1[ix+3];
                e1[ix] = e1[ix+7] + e1[ix+6] - e1[ix+5] * e1[ix+4] / e1[ix+3] + e1[ix+1] - e1[ix+5] * e1[ix+4] / e1[ix+3];
		ix = ix + 7;
                }
	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;	
	te1 = 9 * 512 / te0;
        printf("\n\tTest #1:\t Math.h add/sub/mult/div:\t%lf/s", te1);
		/* Trig functions */
	gettimeofday(&starttime, NULL);
	for (ix=0; ix<(ae-1); ix++)
              {
                e1[ix+7] = cos(e1[ix+7]) + sin(e1[ix+6]) - tan(e1[ix+5]) * acos(e1[ix+4]) / asin(e1[ix+3]) + atan(e1[ix+2]) - atan2(e1[ix+1],e1[ix]);
                e1[ix+6] = cos(e1[ix]) + sin(e1[ix+1]) - tan(e1[ix+2]) * acos(e1[ix+3]) / asin(e1[ix+4]) + atan(e1[ix+5]) - atan2(e1[ix+6],e1[ix+7]); 
                e1[ix+5] = cos(e1[ix+7]) + sin(e1[ix+6]) - tan(e1[ix+5]) * acos(e1[ix+4]) / asin(e1[ix+3]) + atan(e1[ix+2]) - atan2(e1[ix+1],e1[ix]);
                e1[ix+4] = cos(e1[ix]) + sin(e1[ix+1]) - tan(e1[ix+2]) * acos(e1[ix+3]) / asin(e1[ix+4]) + atan(e1[ix+5]) - atan2(e1[ix+6],e1[ix+7]);
                e1[ix+3] = cos(e1[ix+7]) + sin(e1[ix+6]) - tan(e1[ix+5]) * acos(e1[ix+7]) / asin(e1[ix+3]) + atan(e1[ix+2]) - atan2(e1[ix+1],e1[ix]);
                e1[ix+2] = cos(e1[ix+6]) + sin(e1[ix+7]) - tan(e1[ix+1]) * acos(e1[ix+6]) / asin(e1[ix+4]) + atan(e1[ix]) - atan2(e1[ix+3],e1[ix+2]);
                e1[ix+1] = cos(e1[ix+5]) + sin(e1[ix+6]) - tan(e1[ix+2]) * acos(e1[ix+5]) / asin(e1[ix+5]) + atan(e1[ix+1]) - atan2(e1[ix+4],e1[ix+1]);
                e1[ix] = cos(e1[ix+4]) + sin(e1[ix+5]) - tan(e1[ix+3]) * acos(e1[ix+4]) / asin(e1[ix+6]) + atan(e1[ix+2]) - atan2(e1[ix],e1[ix+7]);
		ix = ix +7;
               }
	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te2 = 7 * 512 / te0;
        printf("\n\tTest #2:\t Math.h trig:\t%lf/s", te2);
		/* Hyperbolic functions */
	gettimeofday(&starttime, NULL);
	for (ix=0; ix<(ae-1); ix++)
		{
                e1[ix+7] = cosh(e1[ix]) + sinh(e1[ix+1]) - tanh(e1[ix+2]) * cosh(e1[ix+3]) / sinh(e1[ix+4]);
                e1[ix+6] = sinh(e1[ix+7]) + tanh(e1[ix+6]) - cosh(e1[ix+5]) * sinh(e1[ix+4]) / tanh(e1[ix+3]);
                e1[ix+5] = tanh(e1[ix+6]) + cosh(e1[ix]) - sinh(e1[ix+6]) * tanh(e1[ix+7]) / cosh(e1[ix+1]);
                e1[ix+4] = cosh(e1[ix+5]) + tanh(e1[ix+6]) - sinh(e1[ix+7]) * cosh(e1[ix+5]) / sinh(e1[ix+6]);
                e1[ix+3] = tanh(e1[ix+4]) + sinh(e1[ix+7]) - cosh(e1[ix+3]) * tanh(e1[ix+6]) / sinh(e1[ix+5]);
                e1[ix+2] = sinh(e1[ix+5]) + tanh(e1[ix+4]) - cosh(e1[ix+6]) * sinh(e1[ix+5]) / cosh(e1[ix+4]);
                e1[ix+1] = tanh(e1[ix+6]) + cosh(e1[ix+5]) - sinh(e1[ix+5]) * cosh(e1[ix+4]) / tanh(e1[ix+3]);
                e1[ix] = cosh(e1[ix+7]) + sinh(e1[ix+6]) - tanh(e1[ix+5]) * cosh(e1[ix+4]) / sinh(e1[ix+3]);
                ix = ix + 7;

		}	
	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te3 = 5 * 512 / te0;
        printf("\n\tTest #3:\t Math.h hyperbolic:\t%lf/s", te3);
                /* Exponential and logarithmic functions */
	gettimeofday(&starttime, NULL);
        for (ix=0; ix<(ae-1); ix++)
                {
                e1[ix+7] = exp(e1[ix]) + frexp(e1[ix+1], &n) - ldexp(e1[ix+2], n) * log(e1[ix+3]) / log10(e1[ix+4]);
                e1[ix+6] = frexp(e1[ix+7], &n) + exp(e1[ix+6]) - ldexp(e1[ix+5], n) * modf(e1[ix+4], &ip) / log(e1[ix+3]);
                e1[ix+5] = ldexp(e1[ix+6], n) + log(e1[ix]) - log10(e1[ix+6]) * frexp(e1[ix+7], &n) / exp(e1[ix+1]);
                e1[ix+4] = log(e1[ix+5]) + log10(e1[ix+6]) - modf(e1[ix+7], &ip) * exp(e1[ix+5]) / frexp(e1[ix+6], &n);
                e1[ix+3] = log10(e1[ix+4]) + modf(e1[ix+7], &ip) - ldexp(e1[ix+3], n) * exp(e1[ix+6]) / log(e1[ix+5]);
                e1[ix+2] = modf(e1[ix+5], &ip) + frexp(e1[ix+4], &n) - log10(e1[ix+6]) * ldexp(e1[ix+5], n) / exp(e1[ix+4]);
                e1[ix+1] = exp(e1[ix+6]) + ldexp(e1[ix+5], n) - log(e1[ix+5]) * log10(e1[ix+4]) / modf(e1[ix+3], &ip);
                e1[ix] = frexp(e1[ix+7], &n) + log(e1[ix+6]) - exp(e1[ix+5]) * ldexp(e1[ix+4], n) / log10(e1[ix+3]);
                ix = ix + 7;
                }
	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te4 = 5 * 512 / te0;
        printf("\n\tTest #4:\t Math.h exp/log:\t%lf/s", te4);
                /* Power functions */
	gettimeofday(&starttime, NULL);
        for (ix=0; ix<(ae-1); ix++)
                {
                e1[ix+3] = pow(e1[ix], e1[ix+1]) + sqrt(e1[ix+1]) - pow (e1[ix+2], e1[ix]) * sqrt(e1[ix+2]) / sqrt(e1[ix+1]) ;
                e1[ix+2] = sqrt(e1[ix+3]) + sqrt(e1[ix+3]) - pow(e1[ix+3], e1[ix+2]) * pow(e1[ix+3], e1[ix+2]) / sqrt(e1[ix+3]);
                e1[ix+1] = sqrt(e1[ix+2]) + sqrt(e1[ix+3]) - pow(e1[ix+2], e1[ix+2]) * sqrt(e1[ix+3]) / pow(e1[ix+3], e1[ix+2]);
                e1[ix] = pow(e1[ix+2], e1[ix+1]) + sqrt(e1[ix+3]) - pow(e1[ix+2], e1[ix+1]) * sqrt(e1[ix+3]) / pow(e1[ix+2], e1[ix+3]);
                ix = ix + 3;
                }
	gettimeofday(&endtime, NULL);
        te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te5 = 5 * 256 / te0;
        printf("\n\tTest #5:\t Math.h power functions:\t%lf/s", te5);
                /* Rounding, absolute value and remainder functions */
	gettimeofday(&starttime, NULL);
        for (ix=0; ix<(ae-1); ix++)
                {
                e1[ix+7] = ceil(e1[ix]) + fabs(e1[ix+1]) - floor(e1[ix+2]) * fmod(e1[ix+3], e1[ix+4]);
                e1[ix+6] = fabs(e1[ix+7]) + floor(e1[ix+6]) - fmod(e1[ix+5], e1[ix+4]) / ceil(e1[ix+3]);
                e1[ix+5] = floor(e1[ix+6]) + fmod(e1[ix], e1[ix+6]) * ceil(e1[ix+7]) / fabs(e1[ix+1]);
                e1[ix+4] = fmod(e1[ix+5], e1[ix+6]) - ceil(e1[ix+7]) * fabs(e1[ix+5]) / floor(e1[ix+6]);
                e1[ix+3] = ceil(e1[ix]) + fabs(e1[ix+1]) - floor(e1[ix+2]) * fmod(e1[ix+3], e1[ix+4]);
                e1[ix+2] = fabs(e1[ix+7]) + floor(e1[ix+6]) - fmod(e1[ix+5], e1[ix+4]) / ceil(e1[ix+3]);
                e1[ix+1] = floor(e1[ix+6]) + fmod(e1[ix+1], e1[ix+6]) * ceil(e1[ix+7]) / fabs(e1[ix+1]);
                e1[ix] = fmod(e1[ix+5], e1[ix+6]) - ceil(e1[ix+7]) * fabs(e1[ix+6]) / floor(e1[ix+6]);
                ix = ix + 7;
                }
	}
	gettimeofday(&endtime, NULL);
	te0=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
	te6 = 4 * 512 / te0;
	printf("\n\tTest #6:\t Math.h abs value, rounding, remainder:\t%lf/s\n", te6);
	pass0 =  (te1 + te2 + te3 + te4 + te5 + te6) / 6;
return pass0;
}
