/*
 *  psychlops_m_util.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2006/01/04 by Kenchi HOSOKAWA
 *  (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_MATH_UTIL
#define HEADER_PSYCHLOPS_MATH_UTIL

#include <math.h>
#include <algorithm>


namespace Psychlops {


	extern const double PI;


	/*		Functions		*/

	//	Random
	// in this version random(X) generates pseudrandom number in half-closed interval
	double random();	// [0,1)
	double random(double N);	//	[0,N)
	int random(int N);	//	[0,N)
	double random(double min, double max);	//	[min,max)
	void random(double array[], int size);	// [0,1)
	void random(double array[], int size, double N);	//	[0,N)
	void random(double array[], int size, double min, double max);	//	[min,max)
	class Matrix;
	void random(Matrix &mtx);
	void random(Matrix &mtx, double factor);
	void random(Matrix &mtx, double min, double max);
	void randomize();
	void randomize(unsigned long seed);


	//	shuffle
	class Math {
		public:
		static const double E;
		static const double LOG2E;
		inline static double abs(double val) { return (val<0 ? -val : val); }
		inline static double mod(double lhs, double rhs) { return lhs - floor(lhs/rhs)*rhs; }
		static int round(double val);
		static double log2(double val);
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
		template <class X, class Y> static double max(X val1, Y val2) { return val1>val2 ? val1 : val2; }
		template <class X, class Y> static double min(X val1, Y val2) { return val1<val2 ? val1 : val2; }

		template <class X> static void shuffle(X array, int n);
		template <class X> static void shuffle(X* array, int n, X init);
		void setscramble(int array[], unsigned int length);  //  obsolete

		static double gaussian(double x, double sigma);
		static double normalDistibution(double x, double mu, double sigma);
		static double cumulativeNormalDistibution(double x, double mu, double sigma);
	};

	//	!! this code is copied from http://ray.sakura.ne.jp/tips/shaffle.html
	template <class X> void Math::shuffle(X array, int n) {
		int a;
		for(int i = 1; i < n; i++){
			a = random(i + 1);
			std::swap(array[i], array[a]);
		}
	}
	template <class X> void Math::shuffle(X* array, int n, X init) {
		for(int i=init; i<n+init; i++) array[i] = i;
		shuffle(array, n);
	}

}	/*	<- namespace Psycholops 	*/

#endif
