//Game Maker real valued functions
//by BMF [IamBMF@gmail.com]
//fo' free
//26-03-2006

#include <stdlib.h>
#include <math.h>
#include <stdarg.h>

//in order to use this function you must call srand() before in your program
double random(double x)
{
	return ((double)rand()/RAND_MAX)*x;
}

double choose(char n, ...) //n is the number of options
{
	va_list puntero;
	va_start(puntero,n);

	double options[n];
	
	for (char _i=0; _i<n; _i++)
		options[_i]=va_arg(puntero,double);
		
	va_end(puntero);
		
	return options[(int)random(n)];
}

double abs(double x)
{
	return fabs(x);
}

int sign(double x)
{
	if (x>0)
		return 1;
	else if (x<0)
		return -1;
	else
		return 0;
}

//round(x) is in math.h

//floor(x) is in math.h

//ceil(x) is in math.h

double frac(double x)
{
	return x-floor(x);
}

//sqrt(x) is in math.h

double sqr(double x)
{
	return x*x;
}

double power(double x, double n)
{
	return pow(x,n);
}

//exp(x) is in math.h

double ln(double x)
{
	return log(x);
}

double log2(double x)
{
	return log(x)/log(2);
}

//log10(x) is in math.h

double logn(double n, double x) //n -> base
{
	return log(x)/log(n);
}

//sin(x) is in math.h

//cos(x) is in math.h

//tan(x) is in math.h

double arcsin(double x)
{
	return asin(x);
}

double arccos(double x)
{
	return acos(x);
}

double arctan(double x)
{
	return atan(x);
}

double arctan2(double x, double y)
{
	return atan2(x,y);
}

double degtorad(double x)
{
	return (x/180)*M_PI;
}

double radtodeg(double x)
{
	return (x*180)/M_PI;	
}

double min(char n, ...)
{
	va_list puntero;
	va_start(puntero,n);

	double min, temp;
	
	min=va_arg(puntero,double);
	
	for (char _i=1; _i<n; _i++)
	{
		temp=va_arg(puntero,double);
		if (temp<min)
			min=temp;
	}
		
	va_end(puntero);
		
	return min;
}

double max(char n, ...) 
{
	va_list puntero;
	va_start(puntero,n);

	double max, temp;
	
	max=va_arg(puntero,double);
	
	for (char _i=1; _i<n; _i++)
	{
		temp=va_arg(puntero,double);
		if (temp>max)
			max=temp;
	}
		
	va_end(puntero);
		
	return max;
}

double mean(char n, ...) 
{
	va_list puntero;
	va_start(puntero,n);

	double total=0;
	
	for (char _i=0; _i<n; _i++)
		total+=va_arg(puntero,double);
		
	va_end(puntero);
		
	return total/double(n);
}

double median(char n, ...) //this was the only one that required me to think xD
{
	va_list puntero;
	va_start(puntero,n);

	double options[n],other[n],temp,max;
	char temp_pos;

	//first we get all values to the options[] array
	for (char _i=0; _i<n; _i++)
		options[_i]=va_arg(puntero,double);

	//now we get the max, it's gonna be useful
	max=options[0];
	for (char _i=0; _i<n; _i++)
	{
		if (options[_i]>max)
			max=options[_i];
	}
	

	//next we are gonna order them on the other[] array
	for (char _a=0; _a<n; _a++) //we are going to extract as many values as there are 
	{
		temp=options[0];
		temp_pos=0;
		for (char _i=1; _i<n; _i++)
		{
			if (options[_i]<temp)
			{
				temp=options[_i];
				temp_pos=_i;
			}
		}
		//now we have the minimum value at 'temp', and it's pos at 'temp_pos'
		//so lets keep bulding out other[] one
		other[_a]=temp;
		//and we have to change options[temp_pos] in order it's not the minimum anymore
		options[temp_pos]=max;
	}	
		
	va_end(puntero);
		
	return other[char(ceil(double(n)/2))-1];
}

double point_distance(double x1, double y1, double x2, double y2)
{
	return sqrt(pow(fabs(x1-x2),2)+pow(fabs(y1-y2),2));
}

double point_direction(double x1, double y1, double x2, double y2)
{
	return asin(fabs(y1-y2)/point_distance(x1,y1,x2,y2));
}

double lengthdir_x(double length, double dir)
{
	return fabs(cos(dir/180*M_PI)*length);
}

double lengthdir_y(double length, double dir)
{
	return sin(dir/180*M_PI)*length;
}
