SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送
メインページ   名前空間一覧   クラス階層   構成   ファイル一覧   名前空間メンバ   構成メンバ   ファイルメンバ  

dKingyoRandom.h

解説を見る。
00001 
00002 
00003 #ifndef _dKingyoRandom__
00004 #define _dKingyoRandom__
00005 
00006 #include "AllLoad.h"
00007 #include "dkutilMath.h"
00008 #include "dKingyoRandom_MT_SSE2.h"
00009 #include "dKingyoRandom_MT_MMXASM.h"
00010 #include <time.h>
00011 
00012 
00013 namespace dkutil{//begin dkutil namespace
00014     namespace math{//begin math namespace
00015 
00016 template<typename SEED>
00017 inline int arg_rand(SEED *seed)
00018 {
00019     (*seed) = (*seed) * 1103515245L + 12345;
00020     return (unsigned)((*seed) / 65536L) % 32768U;
00021 }
00022 
00023 
00024 
00025 template<typename T>
00026 class dKingyoRandom_ANSI : public dKingyoRandom_BasicMember<T>{
00027 public:
00028     dKingyoRandom_ANSI(T seed=timeGetTime())
00029     {       
00030         m_Max = 32767;//(RAMD_MAX)
00031         if(seed<0){seed = -seed;}
00032          m_ulSeed = m_Seed =seed;
00033 
00034     }
00035     virtual ~dKingyoRandom_ANSI(){}
00036     virtual T Rand(){
00037         //m_Seed = m_Seed * 1103515245L + 12345;
00038         //return (unsigned)(m_Seed / 65536L) % 32768U;
00039         return arg_rand(&m_ulSeed);
00040     }
00041     
00042     virtual T Random(T domain){
00043         return Rand() * domain / m_Max;
00044     }
00045     virtual T RandomDomain(T min,T max){
00046 
00047         //return max += Random(max + min);
00048         //return max-=Random(max-min);
00049         //return (max-min)*Rand()+min;
00050         {//しかたない。うまくいかないからこれで代用
00051             //http://members.tripod.co.jp/cprogram/various1.html
00052             //min<= x <=maxまで返す
00053             float fNum, fDenom;
00054 
00055             fNum   = (float)rand() * ( (float)max - (float)min + 1.0f );
00056             fDenom = (float)RAND_MAX + 1.0f;
00057 
00058             return min + (int)( fNum / fDenom );
00059         }
00060 
00061     }
00062     virtual T RandomDomainSafety(T min,T max){
00063         MINMAX_SWAP(T,min,max);
00064         MINMAX_ABS(min,max);
00065         MINMAX_SAFETY(min,max);
00066         return RandomDomain(min,max);
00067     }
00068     
00069     
00070     
00071 };
00072 template<class T>
00073 class dKingyoRandom_Float : public dKingyoRandom_BasicMember<T>{
00074 public:
00075     dKingyoRandom_Float(T seed = timeGetTime()){
00076         m_Max=32767;
00077         if(seed<0){seed = -seed;}
00078         m_ulSeed= m_Seed = seed;
00079     }
00080 
00081     virtual T Rand(){
00082         return (float)arg_rand(&m_ulSeed) / ( (float)m_Max + 1.0f );
00083     }
00084     virtual T Random(T fMax){
00085         return ( (float)arg_rand(&m_ulSeed) * fMax ) / ( (float)RAND_MAX + 1.0f );
00086     }
00087     //min<= x <maxまでの値を返す
00088     virtual T RandomDomain(T min,T max){
00089         return (max-min)*Rand()+min;
00090     }
00091     virtual T RandomDomainSafety(T min,T max){
00092         MINMAX_SWAP_FLOAT(T,min,max);
00093         MINMAX_ABS_FLOAT(T,min,max);
00094         MINMAX_SAFETY(min,max);
00095         return RandomDomain(min,max);
00096     }
00097 };
00098 
00099 
00100 
00101 
00102 /* Period parameters */
00103 #define N 624
00104 #define M 397
00105 #define MATRIX_A 0x9908b0df   /* constant vector a */
00106 #define UPPER_MASK 0x80000000 /* most significant w-r bits */
00107 #define LOWER_MASK 0x7fffffff /* least significant r bits */
00108 
00109 /* Tempering parameters */
00110 #define TEMPERING_MASK_B 0x9d2c5680
00111 #define TEMPERING_MASK_C 0xefc60000
00112 #define TEMPERING_SHIFT_U(y)  (y >> 11)
00113 #define TEMPERING_SHIFT_S(y)  (y << 7)
00114 #define TEMPERING_SHIFT_T(y)  (y << 15)
00115 #define TEMPERING_SHIFT_L(y)  (y >> 18)
00116 
00117 
00118 template<class T>
00119 class dKingyoRandom_MT : public dKingyoRandom_BasicMember<T>{//Please long or ULONG
00120     unsigned long bInitialized ;
00121     // Static member 
00122     int mti;                   // index number 
00123     unsigned long mt[N + 1];   // the array for the state vector 
00124     unsigned long mtr[N];      // the array for the random number 
00125 public:
00126     dKingyoRandom_MT(T seed=timeGetTime()){
00127         m_Max=2^32-1;
00128         SetSeed(seed);
00129         bInitialized=0;
00130     }
00131     virtual ~dKingyoRandom_MT(){}
00132 
00133     virtual void SetSeed(T seed){
00134         int i;
00135         for(i = 0; i < N; i++){
00136              mt[i] = seed & 0xffff0000;
00137              seed = 69069 * seed + 1;
00138              mt[i] |= (seed & 0xffff0000) >> 16;
00139              seed = 69069 * seed + 1;
00140         }
00141         bInitialized = 1;
00142         generateMT();
00143     }
00144     virtual T Rand(){
00145         if(mti >= N){
00146             if(!bInitialized) SetSeed(4357);
00147             generateMT();
00148         }
00149         return mtr[mti++]; 
00150     }
00151     virtual T Random(T max){return Rand() * max / m_Max;}
00152     //min<= x <maxまでの値を返す
00153     virtual T RandomDomain(T min,T max){
00154         return (max-min)*Rand()+min;
00155     }
00156     virtual T RandomDomainSafety(T min,T max){
00157         MINMAX_SWAP(T,min,max);
00158         MINMAX_ABS(min,max);
00159         MINMAX_SAFETY(min,max);
00160         return RandomDomain(min,max);
00161     }
00162     void generateMT(void)
00163     {
00164         int kk;
00165         unsigned long y;
00166         static unsigned long mag01[2] = {0x0, MATRIX_A}; /* mag01[x] = x * MATRIX_A  for x=0,1 */
00167     
00168         for(kk = 0; kk < N - M; kk++){
00169             y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
00170             mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
00171         }
00172 
00173         mt[N] = mt[0];
00174 
00175         for(; kk < N; kk++){
00176             y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
00177             mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
00178         }
00179 
00180         for(kk = 0; kk < N; kk++){
00181             y = mt[kk];
00182             y ^= TEMPERING_SHIFT_U(y);
00183             y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
00184             y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
00185             y ^= TEMPERING_SHIFT_L(y);
00186             mtr[kk] = y;
00187         }
00188         mti = 0;
00189     }
00190 };
00191 
00192 class dKingyoRandom_ANSI_EX : public dKingyoRandom_ANSI<int>{
00193 public: 
00194     dKingyoRandom_ANSI_EX(){}
00195 };
00196 class dKingyoRandom_MT_EX : public dKingyoRandom_MT<ULONG>{
00197 public:
00198     dKingyoRandom_MT_EX(){}
00199 };
00200 class dKingyoRandom_Float_EX : public dKingyoRandom_Float<float>{
00201 public:
00202     dKingyoRandom_Float_EX(){}
00203 };
00204 
00205 
00206 #ifdef USE_DKINGYO_OBJECT_TEST
00207 inline void RandomTest(){
00208     ODS("BEGIN RANDOM TEST()\n");
00209     char s[256],s2[256],s3[256];
00210     
00211     dKingyoRandom_Float<float> f(100);
00212     dKingyoRandom_MT<int> m(100);
00213     dKingyoRandom_ANSI<short> r(100);
00214     int count=0;
00215     while(1){
00216         int inum=r.RandomDomain(100,200);//r.GetRandomDomain(100,200);
00217         float fnum=f.RandomDomain(100,200);
00218         int mtnum = m.Rand();
00219         //int i=r.Random(200);
00220         //int i=arg_rand(&tane) * 200 / RAND_MAX;
00221         //int i=(200-100)*arg_rand((int *)&tane)+100;
00222         sprintf(s,"%d\n",inum);
00223         sprintf(s2,"%f\n",fnum);
00224         sprintf(s3,"MT=%d\n",mtnum);
00225         if(100 > inum || 200 < inum){
00226             MB(s);
00227         }
00228         if(100 >= fnum || 200 <= fnum){
00229             MB(s2);
00230         }
00231         
00232         ODS(s);
00233         ODS(s2);
00234         ODS(s3);
00235         count++;
00236         if(count > 20)
00237             break;
00238     }
00239 }
00240 inline void MTRandomTest(){
00241     dkutil::math::srandMT(timeGetTime());
00242     const int loopnum=5;
00243     int setSeed=100;
00244     ULONG ulsetSeed=100;
00245     ODS("//**********************************************************\n");
00246     ODS("//メルセンヌツイスター法の乱数生成テスト\n");
00247     ODS("int type\n");
00248     {
00249         dKingyoRandom_MT<int> mtc(setSeed) ;
00250         dKingyoRandom_MT_SSE2<int> mtsse(setSeed);
00251         //mtsse.SetSeed(setSeed);
00252         //mtc.SetSeed(setSeed);
00253         for(int i=0;i<loopnum;i++){
00254             int sse,c;
00255             sse=mtsse.Rand();
00256             c=mtc.Rand();
00257             dkutil::dOutputDebugString("SSE2 rand num=%d ",sse);
00258             dkutil::dOutputDebugString("C type rand num=%d ",c);
00259                 
00260         }
00261     }
00262     
00263     ODS("ulong type \n");
00264     {
00265         //::dkutil::math::dKingyoRandom_MT_EX mtc(ulsetSeed) ;
00266         //::dkutil::math::dKingyoRandom_MT_SSE2_EX mtsse(ulsetSeed);
00267         dKingyoRandom_MT_EX mtc ;
00268         dKingyoRandom_MT_SSE2_EX mtsse;
00269         mtsse.SetSeed(setSeed);
00270         mtc.SetSeed(setSeed);
00271         for(int i=0;i<loopnum;i++){
00272             ULONG sse,c;
00273             sse=mtsse.Rand();
00274             c=mtc.Rand();
00275             dkutil::dOutputDebugString("SSE2 rand num=%u ",sse);
00276             dkutil::dOutputDebugString("MMX type rand num=%d ",dkutil::math::randMT());
00277             dkutil::dOutputDebugString("C type rand num=%u ",c);
00278                         
00279         }
00280     }
00281     ODS("//**********************************************************\n");
00282     int loopcount=100000000;
00283     dkutil::dOutputDebugString("乱数生成速度テスト loop回数 = %d,出力単位=CPU clock",loopcount); 
00284     {
00285         dKingyoRandom_MT_EX mtc ;
00286         dKingyoRandom_MT_SSE2_EX mtsse;
00287         
00288         {//SSE2
00289             clock_t c=clock();
00290             for(int i=0;i<loopcount;i++){
00291                 mtsse.Rand();           
00292             }
00293             dkutil::dOutputDebugString("SSE2 clock is %d",clock() - c);
00294         }
00295         {//SSE2 inline
00296             INL_dKingyoRandom_MT_SSE2<ULONG> inlmt;
00297             clock_t c=clock();
00298             for(int i=0;i<loopcount;i++){
00299                 inlmt.Rand();       
00300             }
00301             dkutil::dOutputDebugString("SSE2 inline type clock is %d",clock() - c);
00302         }
00303         {//SSE2 original
00304             myMT_t *mt;
00305             mt = myMT_Init();
00306             myMT_SetSeed(mt, timeGetTime());
00307             clock_t c=clock();
00308             for(int i=0;i<loopcount;i++){
00309                 myMT_GetInt32(mt);      
00310             }
00311             dkutil::dOutputDebugString("SSE2 original type clock is %d",clock() - c);
00312             myMT_Term(mt);
00313         }
00314         {//MMX
00315             clock_t c=clock();
00316             for(int i=0;i<loopcount;i++){
00317                 dkutil::math::randMT();         
00318             }
00319             dkutil::dOutputDebugString("MMX2 clock is %d",clock() - c);
00320         }
00321         {//C Language
00322             clock_t c=clock();
00323             for(int i=0;i<loopcount;i++){
00324                 mtc.Rand();         
00325             }
00326             dkutil::dOutputDebugString("C type clock is %d",clock() - c);
00327         }
00328     }
00329 
00330 
00331 
00332 
00333 }
00334 
00335 
00336 #endif //end of USE_DKINGYO_OBJECT_TEST
00337 
00338 
00339 }//end of math namespace
00340 }//end of dkutil namespace
00341 
00342 
00343 #endif
00344 
00345 
00346 /* This main() outputs first 1000 generated numbers.  
00347 int main(int argc, char *argv[])
00348 { 
00349     int i;
00350 
00351     srandMT(4357);
00352     for (i=0; i<1000; i++) {
00353         printf("%10lu ", randMT());
00354         if (i%5==4) printf("\n");
00355     }
00356     return EXIT_SUCCESS;
00357 }
00358 */
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 /*
00373 参考資料:
00374 http://www2t.biglobe.ne.jp/~bono/c/memo1.htm
00375 http://members.tripod.co.jp/cprogram/various1.html
00376 
00377 
00378 乱数の発生
00379 
00380 
00381 関数による発生 
00382 stdlib.hをインクルードして,rand()を用いる
00383 ・Cライブラリのrand関数は,直前のrand()の呼び出しで得られた乱数の値に適当な演算を施して,次の乱数を作成するようになっている.
00384 ・一番最初にrandを呼び出すとき,一般にsrand関数で乱数の初期値となる値を指定する.これを乱数の種という.
00385 ・乱数の種を適切に設定しないと,毎回同じ乱数を発生させることになる.
00386 そこで,現在の時刻を与えることで毎回違う乱数になるように設定する例
00387 
00388 srand((unsigned)time(NULL)); //乱数の初期化
00389 
00390 
00391 線形合同法による一様乱数 
00392 適当な初期値X0から始め
00393 
00394 Xn = ( A*Xn-1 + C ) mod M
00395 という式を用いて,次々に0〜Mの範囲の値を発生させる.
00396 Aは,8で割って余りが5の整数
00397 Cは,奇数
00398 Mは,2^n という条件で,0〜M−1 までの整数が周期Mで1回ずつ現れる. 
00399 
00400 
00401 実数乱数の発生 
00402 線形合同法を使って,0〜1未満の実数乱数を発生させる関数の例
00403 double rnd(void)
00404 {
00405     unsigned rndnum=13;
00406 
00407     rndnum=(rndnum*109+1021)%32768;
00408     return rndnum/32767.1;
00409 } 
00410 
00411 1〜Mまでの乱数を発生 
00412 r=(int)(M*rand()/32767.1+1);
00413 
00414 
00415 正規乱数(ボックス・ミュラー法) 
00416 平均m,標準偏差σの正規分布N(m,σ)に従う乱数の発生例
00417 
00418 void boxrnd(double m,double sig,double *x,double *y)
00419 {
00420     double r1,r2;
00421     r1=rand()/32767.1;
00422     r2=rand()/32767.1;
00423     *x=sig*sqrt(-2*log(r1))*cos(2*3.14159*r2)+m;
00424     *y=sig*sqrt(-2*log(r1))*sin(2*3.14159*r2)+m;
00425 }
00426 stdlib.hとmath.hのインクルードを忘れないように!  
00427 
00428 
00429 */

dKingyoUtilClass (dkutil)に対してMon Jun 9 01:32:41 2003に生成されました。 doxygen1.3