00001
00005 #define DKUTIL_C_MT_RAND32_C
00006 #include "dkcMTRand32.h"
00007 #include "cpu_x86.h"
00008 #include <dkutil_c/dkc_misc.h>
00009
00011
00012
00013
00014
00015 #define M 397
00016 #define MATRIX_A 0x9908B0DF
00017 #define UMASK 0x80000000
00018 #define LMASK 0x7FFFFFFF
00019 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
00020 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1 ? MATRIX_A : 0))
00021
00022
00024
00025
00026
00027
00028
00029
00030
00031
00032 void dkcMTRand32Next_C(DKC_MT_RAND32 *mt)
00033 {
00034 int i;
00035 uint32 *p, *q;
00036
00037 p = mt->state;
00038 for (i = 0; i < dkcdMT_RAND32_N - M; i++, p++) {
00039 *p = p[M] ^ TWIST(p[0], p[1]);
00040 }
00041
00042 for (i = 0; i < M - 1; i++, p++) {
00043 *p = p[M-dkcdMT_RAND32_N] ^ TWIST(p[0], p[1]);
00044 }
00045
00046 *p = p[M-dkcdMT_RAND32_N] ^ TWIST(p[0], mt->state[0]);
00047 mt->index = 0;
00048
00049 p = mt->state;
00050 q = mt->output;
00051 for (i = 0; i < dkcdMT_RAND32_N; i++) {
00052 uint32 y;
00053 y = *p++;
00054
00055 y ^= (y >> 11);
00056 y ^= (y << 7) & 0x9D2C5680;
00057 y ^= (y << 15) & 0xEFC60000;
00058 y ^= (y >> 18);
00059 *q++ = y;
00060 }
00061 }
00062
00063 static DKC_INLINE next(DKC_MT_RAND32 *mt)
00064 {
00065 DKC_MT_RAND32_GENERATE_F_TYPE pf;
00066 pf = mt->function_ptr;
00067 pf(mt);
00068 }
00069
00070
00071 void WINAPI dkcMTRand32Init(DKC_MT_RAND32 *mt, uint32 seed)
00072 {
00073 uint32 *p;
00074 int i;
00075
00076 p = mt->state;
00077 p[0] = seed;
00078
00079 for (i = 1; i < dkcdMT_RAND32_N; i++) {
00080 p[i] = (1812433253 * (p[i-1] ^ (p[i-1] >> 30)) + i);
00081
00082
00083
00084
00085 p[i] &= 0xffffffffUL;
00086
00087 }
00088
00089 mt->index = i;
00090
00091 }
00092
00093 void WINAPI dkcMTRand32InitByArray(DKC_MT_RAND32 *p,uint32 *init_key,int32 key_length)
00094 {
00095 int i, j, k;
00096 uint32 *mt = p->state;
00097
00098 dkcMTRand32Init(p,19650218UL);
00099 i=1; j=0;
00100 k = (dkcdMT_RAND32_N>key_length ? dkcdMT_RAND32_N : key_length);
00101 for (; k; k--) {
00102 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
00103 + init_key[j] + j;
00104 mt[i] &= 0xffffffffUL;
00105 i++; j++;
00106 if (i>=dkcdMT_RAND32_N) { mt[0] = mt[dkcdMT_RAND32_N-1]; i=1; }
00107 if (j>=key_length) j=0;
00108 }
00109 for (k=dkcdMT_RAND32_N-1; k; k--) {
00110 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
00111 - i;
00112 mt[i] &= 0xffffffffUL;
00113 i++;
00114 if (i>=dkcdMT_RAND32_N) { mt[0] = mt[dkcdMT_RAND32_N-1]; i=1; }
00115 }
00116
00117 mt[0] = 0x80000000UL;
00118
00119
00120
00121 }
00122
00123
00124 #if 0
00125 void myMT_SetSeeds(myMT_t *mt, uint32 *seed, int seedNum)
00126 {
00127 uint32 *p = mt->state;
00128 int i;
00129 int num = (seedNum < dkcdMT_RAND32_N) ? seedNum : dkcdMT_RAND32_N;
00130
00131 if (num <= 0) {
00132 myMT_SetSeed(mt, 1234);
00133 return;
00134 }
00135
00136 memcpy(p, seed, num * sizeof(uint32));
00137
00138 for (i = num; i < dkcdMT_RAND32_N; i++) {
00139 p[i] = (1812433253 * (p[i-1] ^ (p[i-1] >> 30)) + i);
00140
00141
00142
00143
00144 }
00145 myMT_Next(mt);
00146 }
00147 #endif
00148
00149
00150
00151 DKC_MT_RAND32 *WINAPI dkcAllocMTRand32(uint32 seed)
00152 {
00153 const uint32 alignMask = 15;
00154 uint8 *tp = dkcAllocateFast_INL(sizeof(DKC_MT_RAND32) + alignMask);
00155 DKC_MT_RAND32 *p;
00156 int unit;
00157 if(NULL==tp) return NULL;
00158
00159 p = (DKC_MT_RAND32 *)(((int)tp + alignMask) & ~alignMask);
00160 p->mallocPtr = (char *)tp;
00161 #if 1
00162 unit = haveX86_UNIT();
00163 if (unit & MU_tSSE2) {
00164 p->function_ptr = (void *)dkcMTRand32Next_SSE2;
00165 } else if (unit & MU_tMMX) {
00166 p->function_ptr = (void *)dkcMTRand32Next_MMX;
00167 } else {
00168 p->function_ptr = (void *)dkcMTRand32Next_C;
00169 }
00170 #else
00171 p->function_ptr = (void *)dkcMTRand32Next_C;
00172 #endif
00173 dkcMTRand32Init(p,seed);
00174 return p;
00175 }
00176
00177 int WINAPI dkcFreeMTRand32(DKC_MT_RAND32 **p)
00178 {
00179 dkcFreeFast_INL((void **)(&((*p)->mallocPtr)));
00180 return edk_SUCCEEDED;
00181 }
00182
00183
00184
00185 uint32 WINAPI dkcMTRand32Get(DKC_MT_RAND32 *p){
00186
00187 return dkcMTRand32Get_INL(p);
00188 }