

#ifndef _dKingyoRandom_MT_SSE2__h
#define _dKingyoRandom_MT_SSE2__h

#include <mymt.h>

//#include "../global.h"
#include "dkutilMath.h"

//#pragma warning(push:4146)
#pragma warning(disable:4146)
/*
	int i, ret;
	myMT_t *mt;

	mt = myMT_Init();
	myMT_SetSeed(mt, SEED);

	printf("test of myMT\n");
	for (i = 0; i < 16; i++) {
		int j;
		for (j = 0; j < 4; j++) {
			printf("%08X", myMT_GetInt32(mt));
		}
		printf("\n");
	}

	myMT_SetSeed(mt, SEED);
	elapsed();
	ret = 0;
	for (i = 0; i < 100000000; i++) {
		ret += myMT_GetInt32(mt);
	}
	printf("asm version ret=%08X  %ftime\n", ret, elapsed());

	if (0) {
		unsigned int seed[624];
		memset(seed, 2, sizeof(seed));
		seed[0] = 1;
		myMT_SetSeeds(mt, seed, 624);
		ret = 0;
		for (i = 0; i < 10000000; i++) { ret += myMT_GetInt32(mt); }
		printf("ret=%08X\n", myMT_GetInt32(mt));

		myMT_SetSeeds(mt, seed, 623);
		ret = 0;
		for (i = 0; i < 10000000; i++) { ret += myMT_GetInt32(mt); }
		printf("ret=%08X\n", myMT_GetInt32(mt));

		seed[623] = 1;
		myMT_SetSeeds(mt, seed, 624);
		ret = 0;
		for (i = 0; i < 10000000; i++) { ret += myMT_GetInt32(mt); }
		printf("ret=%08X\n", myMT_GetInt32(mt));
	}

	myMT_Term(mt);
	
*/
namespace dkutil{//begin dkutil namespace
	namespace oldmath{//begin math namespace


template<class T,DWORD RANDMAX_ = INT_MAX>
class INL_dKingyoRandom_MT_SSE2{
protected:
	myMT_t *mt;
	ULONG m_ulSeed;
	DWORD m_Max;
	///私の技術じゃ、コピーコンストラクタは作れない。
	INL_dKingyoRandom_MT_SSE2(INL_dKingyoRandom_MT_SSE2 &c);
public:
	
	INL_dKingyoRandom_MT_SSE2(T seed=timeGetTime())
	{
		//seed = ::abs(seed);
		if(seed<0){seed = -seed;}
		m_Max=RANDMAX_;
		//m_Max=RAND_MAX;
		m_ulSeed  =static_cast<ULONG>(seed);
		mt = myMT_Init();
		myMT_SetSeed(mt, (UINT)m_ulSeed);
	}

	~INL_dKingyoRandom_MT_SSE2(){
		myMT_Term(mt);
	}
	inline T Rand(){
		return myMT_GetInt32(mt);
	}
	
	inline T Random(DWORD domain){
		//return Rand() * domain / m_Max;
		return RandomDomain(0,domain);
	}
	inline  T RandomDomain(T min,T max){

		//return max += Random(max + min);
		//return max-=Random(max-min);
		//return (max-min)*Rand()+min;
		float fNum, fDenom;

			fNum   = (float)Rand() * ( (float)max - (float)min + 1.0f );
			fDenom = (float)RANDMAX_ + 1.0f;

			return min + (int)( fNum / fDenom );
	}
	inline T RandomDomainSafety(T min,T max){
		if(min>max){SWAP_NUM(min,max);}
		MINMAX_ABS(min,max);
		MINMAX_SAFETY(min,max);
		return RandomDomain(min,max);
	}
	inline void SetSeed(UINT seed){
		m_ulSeed = seed;
		myMT_SetSeed(mt, (UINT)seed);
	}
	inline ULONG GetSeed(){return m_ulSeed;}
	inline DWORD GetRandMax(){return m_Max;}
};

}//end of math namespace

namespace oldmath{


template<typename T,DWORD RANDMAX_ = INT_MAX>
class dKingyoRandom_MT_SSE2 : public dKingyoRandom_BasicMember<T>{
protected:
	INL_dKingyoRandom_MT_SSE2<T,RANDMAX_> mtsse;
public:
	dKingyoRandom_MT_SSE2(T seed=timeGetTime())
	{		
		m_Max = RANDMAX_;//(RAMD_MAX)
		seed = ::abs(seed);
		//if(seed<0){seed = -seed;}
		 m_ulSeed = static_cast<ULONG>(m_Seed =seed);
		mtsse.SetSeed(m_ulSeed);
	}
	~dKingyoRandom_MT_SSE2(){
	}
	virtual T Rand(){
		return mtsse.Rand();
	}
	
	virtual T Random(T domain){
		//return Rand() * domain / m_Max;
		return mtsse.Random(domain);
	}
	virtual T RandomDomain(T min,T max){

		//return max += Random(max + min);
		//return max-=Random(max-min);
		return mtsse.RandomDomain(min,max);

	}
	virtual T RandomDomainSafety(T min,T max){
		if(min>max){SWAP_NUM(min,max);}
		MINMAX_ABS(min,max);
		MINMAX_SAFETY(min,max);
		return RandomDomain(min,max);
	}
	virtual void SetSeed(T set){
		mtsse.SetSeed((UINT)set);
	}
	
};

typedef dKingyoRandom_MT_SSE2<ULONG,ULONG_MAX> dKingyoRandom_MT_SSE2_NO_SETUP;
/*
class dKingyoRandom_MT_SSE2_NO_SETUP : public dKingyoRandom_MT_SSE2<ULONG,ULONG_MAX>{
public:
	dKingyoRandom_MT_SSE2_NO_SETUP(){}
};
*/
}//end of math namespace
}//end of dkutil namespace

#pragma warning(default:4146)
//#pragma warning(pop)

#endif //end of _dKingyoRandom_MT_SSE2__h