//#include "Random.h"
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
//#include <sys/types.h>
#include <stdint.h>
#include <math.h>
#include <sys/time.h>
//#include <unistd.h>


uint32_t lcg_rand2(uint32_t a)
{
    return ((uint64_t)a * 279470273UL) % 4294967291UL;
}


uint32_t good_rand(uint64_t *s){
	//uint64_t hi, lo;
	//uint32_t x;
	// initial value of s must be 2 or higher

	//127773 41943011

    uint64_t hi = *(uint64_t *)s / 41943011;
    uint64_t lo = *(uint64_t *)s % 41943011;
    *(uint64_t *)s = *(uint64_t *)s * lo - 2147483647 * hi;

    //if(*(uint64_t *)s < 0){ 
	//	*(uint64_t *)s += 0x7fffffffffffffff;
	//	printf("here !\n");
	//}

	//uint32_t hi = b / 41943011;
	//uint32_t lo = b % 41943011;

	//uint32_t hi = (*(char *)s & 0xFFFFFFFF00000000) >> 32;
	//uint32_t lo = *(char *)s & 0x00000000FFFFFFFF;
	//hi /= 41943011;
	//lo %= 41943011;
	// *(uint64_t *)s =  b * lo - 2147483647 * hi;

	//if(*(uint64_t *)s < 0) *(uint64_t *)s += 0x7fffffffffffffff;

	//uint64_t temp;
	//uint32_t msw, lsw;

	//*(uint64_t *)s = *(uint64_t *)s * lo - 41943011 * hi;

	/*
	uint32_t msw = (*(uint64_t *)s & 0xFFFFFFFF00000000) >> 32;
	uint32_t lsw = *(uint64_t *)s & 0x00000000FFFFFFFF;
	msw /= 41943011;
	lsw %= 41943011;
	x = x * lsw - 2147483647 * msw;
	*(uint64_t *)s = *(uint64_t *)s * lsw - 2147483647 * msw;
	if(*(uint64_t *)s < 0) *(uint64_t *)s += 0x7fffffffffffffff;
	*/

	//uint32_t x = *(uint64_t *)s;
  	//uint32_t x;
  	//static uint32_t s;
  	// Can't be initialized with 0, so use another value.
  	//if (x == 0) x = 123459876;
  	//x = *(uint64_t *)s << 32;
	//hi = (x << 32) / 127773;
	//lo = (x >> 32) % 127773;
	//hi = *(uint64_t *)s / 2147483647;
	//lo = *(uint64_t *)s % 2147483647;
	//*(uint64_t *)s = *(uint64_t *)s * lo - 4194301 * hi;
	
	//lo = (*(uint64_t *)s * lo - 4194301 * hi);
	//x = lo << 32;
	//*(uint64_t *)s = lo;
	//x = (uint32_t)(*(uint64_t *)s * lo - 4194301 * hi);
	//*(uint64_t *)s = (*(uint64_t *)s * lo - 4194301 * hi);

	//if (*(uint64_t *)s < 0) *(uint64_t *)s += 0x7fffffff;
	//*(uint64_t *)s = x;
	
	//x = *(uint64_t *)s;
	//*(uint64_t *)s = x;
  	//*(uint64_t *)s = x + hi * lo;
  	//return (uint32_t)*(uint64_t *)s  << 32;
	return (*(uint64_t *)s & 0xFFFFFFFF00000000) >> 32 ;
}



unsigned long int lehmer(long int s){
      // linear congruential pseudo random number generator based on D. Lehmer
	static unsigned long long a = 2007, b = 4194301, c = 2147483647, z = 4194301;
	if ( s < 0 ) {s = -s; a = s;}
	z = (a + b * z) % c;
	return z % s;
}

unsigned int ran_int(unsigned int a){
	static uint64_t b = 4194301 , c = 2147483647, z = 4194301;
	//a = s;
	//a = b >> 32;
	//if(b<0) {b = -b; a = b;}
	z = (a+b*z) % c;
	//a = z >> 32;
	return z;
}

uint32_t lcg_rand(uint32_t a)
{
	static uint64_t z = 2147483647;
	
    z = (z + (uint64_t)a * 279470273UL) % 4294967291UL;
	return z % a;
}

int main(int argc, char **argv){



	uint32_t n1, n2;
	uint64_t n3 = 173;

	uint64_t s;// = atoi(argv[1]);
	uint32_t b;

	const uint32_t Runs = 10000000;
	uint32_t *block = malloc(sizeof(uint32_t)*Runs);

	uint32_t zeroes = 0;
	uint32_t ones = 0;
	uint32_t times[10];
	uint32_t tc = 0;

	for(n1=0; n1<10; n1++)
		times[n1] = 0;

	//a=0;
	//a-=153;
    struct timeval cur;
    gettimeofday(&cur, NULL);
    srand ( (unsigned int)cur.tv_usec );
    //rand1 = rand() % 100 + 1;

	s = cur.tv_usec*3+3;

	//printf("seed: %lu\n", a);

//	for(n2=0; n2<10; n2++){
//		n1 = lcg_rand(2);
//		printf("lcg:%u\n", n1);
//	}


//	for(n2=0; n2<10; n2++){
//		printf("%u\n", good_rand(&s) % 2 + 1);
		//printf("%u\n", rand() % 1 + 1);
//	}
//	return 0;


	double tmp;
	unsigned char output;
	uint32_t use_ceil = 0;

    //use_ceil = lrand(&s) % 100 + 1;
    //if(use_ceil > 50)
      //  use_ceil = 1;

	//for(n2=0; n2<10; n2++){
	//	printf("%u\n", good_rand(&s) % 2);
	//}

	unsigned char *rand_a = malloc(sizeof(char)*Runs);;
	unsigned char *rand_b = malloc(sizeof(char)*Runs);;
	for(n2=0; n2<Runs; n2++){
		rand_a[n2] = good_rand(&s) % 6 + 140;
		rand_b[n2] = good_rand(&s) % 6 + 140;
		//printf("%u %u\n", rand_a[n2], rand_b[n2]);
	}
	//printf("\n");

	for(n2=0; n2<Runs; n2++){
		use_ceil = 0;
		use_ceil = good_rand(&s) % 100 + 1;
		if(use_ceil > 50)
			use_ceil = 1;
		tmp = ( rand_a[n2] + rand_b[n2] )/ 2;
		//printf("%lf\n", tmp);
		output = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );
		if(output > 145 || output < 140)
			tc++;
	}
	printf("\n");
	printf("%u\n", tc);

	return 0;



	n3 = 5;
	for(n2=0; n2<Runs; n2++){
		block[n2] = good_rand(&s) % 1  + 1;
		//block[n2] = rand() % 2;
		//block[n2] = lehmer(2);
		//block[n2] = ran_int(a) % 2;
		if(n2<10)
			printf("%u\n", block[n2]);
		if(block[n2] > 255 || block[n2] < 1)
			printf("Out of Range !\n");
	}
printf("here 1\n");

	uint32_t highest_run = 0;
	n3 = 0;
	n2 = block[0];
	for(n1=1; n1<Runs; n1++){
		//if(block[n1] == 0)
		//	zeroes++;
		//if(block[n1])
		//	ones++;
		for(tc=0; tc<2; tc++){
			if(block[n1] == tc)
				times[tc]++;
		}
		if(n2 == block[n1]){
			n3++;
			if(n3 > highest_run)
				highest_run = n3;
		}else{
			n3=0;
		}
		n2 = block[n1];
	}
	printf("highest: %u\n", highest_run);
	//printf("ones: %u zeroes: %u\n", ones, zeroes);
	for(tc=0; tc<2; tc++){
		printf("%u %u\n", tc, times[tc]);
	}

	return 0;
}