/* Random collection of random functions
 * AlpT <alpt@freaknet.org>
 *
 * This source code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published 
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * Please refer to the GNU Public License for more details.
 *
 * You should have received a copy of the GNU Public License along with
 * this source code; if not, write to:
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>


inline int rand_range(int _min, int _max)
{
	return (rand()%(_max - _min + 1)) + _min;
}

void xsrand(void)
{
	FILE *fd;
	int seed;

	if((fd=fopen("/dev/urandom", "r"))) {
		fread(&seed, 4,1,fd);
		fclose(fd);
	} else
		seed=getpid() ^ time(0) ^ clock();

	srand(seed); 
}


int surandom2(void)
{
	srand(getpid() ^ clock());
}

int surandom(void)
{
	FILE *fd;
	int seed;
	
	fd=fopen("/dev/urandom", "r");
	fread(&seed, 4,1,fd);
	fclose(fd);
	srand(seed); 
}


void maketrash(int len, char *garbage)
{
	int i,e,g;

	memset(garbage,0,len);
	for(i=0;i<len;) {
		e=rand();
		g=len-i > sizeof(int) ? sizeof(int) : len-i;
		memcpy(&garbage[i], &e, g);
		i+=g;
	}
}

/*
 * wrand
 *
 * Weighted rand
 */
int wrand(u_int nmemb, u_int *w)
{
	int i, tot_w, r;

	for(i=0, tot_w=0; i<nmemb; i++)
		tot_w+=w[i];

	if(!tot_w)
		return rand_range(0, nmemb-1);
		
	r=rand_range(1, tot_w);

	for(i=0, tot_w=0; i<nmemb; i++) {
		if(r > tot_w && (r <= tot_w+w[i]))
			return i;
		tot_w+=w[i];
	}
	
	return -1;
}

/*
 * get_rand_interval
 *
 * It returns a real random integer.
 *
 * The idea is simple: it counts how many microseconds passes from the start
 * to the end of a simple loop that writes for 262144 times on a buffer.
 * The interval is then returned.
 *
 * The interval is influenced chaotically by all the running programs on the
 * OS and by the kernel itself. The computer is then influenced by the user
 * interference, the attached devices, the generated interrupts, etc...
 * For this reason, a same function, will always require different time
 * intervals to solve its computation.
 *
 * You should not use get_rand_interval() to get a random number, because the
 * returned intervals are not (luckily) uniformly distributed, moreover it
 * requires a lot of computation.
 * The correct use of this function is to set the random seed using srand(),
 * seed48(), _only if_ /dev/urandom is not present in the OS.
 *
 * Thanks to /dev/random for the inspiration (it measures the interval between
 * interrupts, etc...)
 */
int get_rand_interval(void)
{
	struct timeval t1, t2;
	int i;

	gettimeofday(&t1, 0);
	for(i=0; i<512; i++) {
		int e=0;
		char buf[512];

		for(e=0; e<512; e++)
			buf[e]=((e*i*e*i)/( !i ? 7 : i+1))+e-i;
	}
	gettimeofday(&t2, 0);

	return abs((t2.tv_usec-t1.tv_usec)+(t2.tv_sec-t1.tv_sec));
}
