00001 #ifndef __ISAAC_HPP
00002 #define __ISAAC_HPP
00003
00004
00005
00006
00007
00008
00009 #include <stdlib.h>
00010
00011 #include <sys/time.h>
00012
00013 #ifndef __ISAAC64
00014 typedef unsigned long int UINT32;
00015 const UINT32 GOLDEN_RATIO = UINT32(0x9e3779b9);
00016 typedef UINT32 ISAAC_INT;
00017 #else // __ISAAC64
00018 typedef unsigned __int64 UINT64;
00019 const UINT64 GOLDEN_RATIO = UINT64(0x9e3779b97f4a7c13);
00020 typedef UINT64 ISAAC_INT;
00021 #endif // __ISAAC64
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 template <int ALPHA = (8), class T = ISAAC_INT>
00044 class QTIsaac {
00045 public:
00046 typedef unsigned char byte;
00047 enum {N = (1<<ALPHA)};
00048
00049 struct randctx {
00050 randctx() {
00051 randrsl = (T*)::malloc(N * sizeof(T));
00052 randmem = (T*)::malloc(N * sizeof(T));
00053 }
00054 ~randctx(void) {
00055
00056
00057 }
00058 T randcnt;
00059 T* randrsl;
00060 T* randmem;
00061 T randa;
00062 T randb;
00063 T randc;
00064 };
00065
00066 QTIsaac();
00067 QTIsaac(T a, T b = 0, T c = 0);
00068 virtual ~QTIsaac(void);
00069
00070 T rand(void);
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 T nrand(T n);
00081
00082
00083
00084
00085
00086
00087
00088 double drand(void);
00089 virtual void randinit(randctx* ctx, bool bUseSeed);
00090 virtual void srand(T a = 0, T b = 0, T c = 0, T* s = NULL);
00091
00092 T ls_a, ls_b, ls_c;
00093
00094 protected:
00095
00096 virtual void isaac(randctx* ctx);
00097
00098 T ind(T* mm, T x);
00099 void rngstep(T mix, T& a, T& b, T*& mm, T*& m, T*& m2, T*& r, T& x, T& y);
00100 virtual void shuffle(T& a, T& b, T& c, T& d, T& e, T& f, T& g, T& h);
00101
00102 private:
00103
00104 randctx m_rc;
00105 };
00106
00107 template<int ALPHA, class T>
00108 QTIsaac<ALPHA,T>::QTIsaac() {
00109 struct timeval t;
00110 gettimeofday(&t, 0);
00111 srand(t.tv_sec, t.tv_usec, t.tv_sec + t.tv_usec);
00112 }
00113
00114 template<int ALPHA, class T>
00115 QTIsaac<ALPHA,T>::QTIsaac(T a, T b, T c) {
00116 srand(a, b, c);
00117 }
00118
00119 template<int ALPHA, class T>
00120 QTIsaac<ALPHA,T>::~QTIsaac(void) {
00121
00122 }
00123
00124 template<int ALPHA, class T>
00125 void QTIsaac<ALPHA,T>::srand(T a, T b, T c, T* s) {
00126 for(int i = 0; i < N; i++) {
00127 m_rc.randrsl[i] = s != NULL ? s[i] : 0;
00128 }
00129
00130 m_rc.randa = ls_a = a;
00131 m_rc.randb = ls_b = b;
00132 m_rc.randc = ls_c = c;
00133
00134 randinit(&m_rc, true);
00135 }
00136
00137 template<int ALPHA, class T>
00138 inline T QTIsaac<ALPHA,T>::rand(void) {
00139 return(!m_rc.randcnt-- ? (isaac(&m_rc), m_rc.randcnt=(N-1), m_rc.randrsl[m_rc.randcnt]) : m_rc.randrsl[m_rc.randcnt]);
00140 }
00141
00142 template<int ALPHA, class T>
00143 inline double QTIsaac<ALPHA,T>::drand(void) {
00144 return (double)rand() / (T(0) - T(1));
00145 }
00146
00147 template<int ALPHA, class T>
00148 inline T QTIsaac<ALPHA,T>::nrand(T max) {
00149 T ret;
00150 T csize = (T(0) - T(1)) / max;
00151 do {
00152 ret = rand() / csize;
00153
00154 } while (ret >= max);
00155 return ret;
00156 }
00157
00158 template<int ALPHA, class T>
00159 void QTIsaac<ALPHA,T>::randinit(randctx* ctx, bool bUseSeed) {
00160 T a,b,c,d,e,f,g,h;
00161 int i;
00162
00163 a = b = c = d = e = f = g = h = GOLDEN_RATIO;
00164
00165 T* m = (ctx->randmem);
00166 T* r = (ctx->randrsl);
00167
00168 if(!bUseSeed) {
00169 ctx->randa = 0;
00170 ctx->randb = 0;
00171 ctx->randc = 0;
00172 }
00173
00174
00175 for(i=0; i < 4; ++i) {
00176 shuffle(a,b,c,d,e,f,g,h);
00177 }
00178
00179 if(bUseSeed) {
00180
00181
00182 for(i=0; i < N; i+=8) {
00183 a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
00184 e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
00185
00186 shuffle(a,b,c,d,e,f,g,h);
00187
00188 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
00189 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
00190 }
00191
00192
00193
00194 for(i=0; i < N; i += 8) {
00195 a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
00196 e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
00197
00198 shuffle(a,b,c,d,e,f,g,h);
00199
00200 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
00201 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
00202 }
00203 } else {
00204
00205
00206 shuffle(a,b,c,d,e,f,g,h);
00207
00208 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
00209 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
00210 }
00211
00212 isaac(ctx);
00213 ctx->randcnt = N;
00214 }
00215
00216 template<int ALPHA, class T>
00217 inline T QTIsaac<ALPHA,T>::ind(T* mm, T x) {
00218 #ifndef __ISAAC64
00219 return (*(T*)((byte*)(mm) + ((x) & ((N-1)<<2))));
00220 #else // __ISAAC64
00221 return (*(T*)((byte*)(mm) + ((x) & ((N-1)<<3))));
00222 #endif // __ISAAC64
00223 }
00224
00225 template<int ALPHA, class T>
00226 inline void QTIsaac<ALPHA,T>::rngstep(T mix, T& a, T& b, T*& mm, T*& m, T*& m2, T*& r, T& x, T& y) {
00227 x = *m;
00228 a = (a^(mix)) + *(m2++);
00229 *(m++) = y = ind(mm,x) + a + b;
00230 *(r++) = b = ind(mm,y>>ALPHA) + x;
00231 }
00232
00233 template<int ALPHA, class T>
00234 void QTIsaac<ALPHA,T>::shuffle(T& a, T& b, T& c, T& d, T& e, T& f, T& g, T& h) {
00235 #ifndef __ISAAC64
00236 a^=b<<11; d+=a; b+=c;
00237 b^=c>>2; e+=b; c+=d;
00238 c^=d<<8; f+=c; d+=e;
00239 d^=e>>16; g+=d; e+=f;
00240 e^=f<<10; h+=e; f+=g;
00241 f^=g>>4; a+=f; g+=h;
00242 g^=h<<8; b+=g; h+=a;
00243 h^=a>>9; c+=h; a+=b;
00244 #else // __ISAAC64
00245 a-=e; f^=h>>9; h+=a;
00246 b-=f; g^=a<<9; a+=b;
00247 c-=g; h^=b>>23; b+=c;
00248 d-=h; a^=c<<15; c+=d;
00249 e-=a; b^=d>>14; d+=e;
00250 f-=b; c^=e<<20; e+=f;
00251 g-=c; d^=f>>17; f+=g;
00252 h-=d; e^=g<<14; g+=h;
00253 #endif // __ISAAC64
00254 }
00255
00256 template<int ALPHA, class T>
00257 void QTIsaac<ALPHA,T>::isaac(randctx* ctx) {
00258 T x,y;
00259
00260 T* mm = ctx->randmem;
00261 T* r = ctx->randrsl;
00262
00263 T a = (ctx->randa);
00264 T b = (ctx->randb + (++ctx->randc));
00265
00266 T* m = mm;
00267 T* m2 = (m+(N/2));
00268 T* mend = m2;
00269
00270 for(; m<mend; ) {
00271 #ifndef __ISAAC64
00272 rngstep((a<<13), a, b, mm, m, m2, r, x, y);
00273 rngstep((a>>6) , a, b, mm, m, m2, r, x, y);
00274 rngstep((a<<2) , a, b, mm, m, m2, r, x, y);
00275 rngstep((a>>16), a, b, mm, m, m2, r, x, y);
00276 #else // __ISAAC64
00277 rngstep(~(a^(a<<21)), a, b, mm, m, m2, r, x, y);
00278 rngstep( a^(a>>5) , a, b, mm, m, m2, r, x, y);
00279 rngstep( a^(a<<12) , a, b, mm, m, m2, r, x, y);
00280 rngstep( a^(a>>33) , a, b, mm, m, m2, r, x, y);
00281 #endif // __ISAAC64
00282 }
00283
00284 m2 = mm;
00285
00286 for(; m2<mend; ) {
00287 #ifndef __ISAAC64
00288 rngstep((a<<13), a, b, mm, m, m2, r, x, y);
00289 rngstep((a>>6) , a, b, mm, m, m2, r, x, y);
00290 rngstep((a<<2) , a, b, mm, m, m2, r, x, y);
00291 rngstep((a>>16), a, b, mm, m, m2, r, x, y);
00292 #else // __ISAAC64
00293 rngstep(~(a^(a<<21)), a, b, mm, m, m2, r, x, y);
00294 rngstep( a^(a>>5) , a, b, mm, m, m2, r, x, y);
00295 rngstep( a^(a<<12) , a, b, mm, m, m2, r, x, y);
00296 rngstep( a^(a>>33) , a, b, mm, m, m2, r, x, y);
00297 #endif // __ISAAC64
00298 }
00299
00300 ctx->randb = b;
00301 ctx->randa = a;
00302 }
00303
00304 #endif // __ISAAC_HPP