NEURON
isaac64.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_SYS_TYPES_H
3 #include <sys/types.h>
4 #endif
5 
6 /*
7 ------------------------------------------------------------------------------
8 isaac64.cpp: A Fast cryptographic random number generator
9  for 32-bit and 64-bit machines.
10 By Bob Jenkins, 1996. Public Domain.
11 
12 Modified for modularity by Tom Bartol and Rex Kerr
13 ------------------------------------------------------------------------------
14 */
15 #include "isaac64.h"
16 
17 
18 #define ind(mm,x) (*(ub8 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<3))))
19 
20 #define rngstep(mix,a,b,mm,m,m2,r,x) \
21 { \
22  x = *m; \
23  a = (mix) + *(m2++); \
24  *(m++) = y = ind(mm,x) + a + b; \
25  *(r++) = b = ind(mm,y>>RANDSIZL) + x; \
26 }
27 
28 #define mix(a,b,c,d,e,f,g,h) \
29 { \
30  a-=e; f^=h>>9; h+=a; \
31  b-=f; g^=a<<9; a+=b; \
32  c-=g; h^=b>>23; b+=c; \
33  d-=h; a^=c<<15; c+=d; \
34  e-=a; b^=d>>14; d+=e; \
35  f-=b; c^=e<<20; e+=f; \
36  g-=c; d^=f>>17; f+=g; \
37  h-=d; e^=g<<14; g+=h; \
38 }
39 
40 
41 
43 {
44  ub8 a,b,x,y,*m,*m2,*r,*mend;
45 
46  m=rng->mm; r=rng->randrsl;
47  a = rng->aa; b = rng->bb + (++rng->cc);
48  for (m = rng->mm, mend = m2 = m+(RANDSIZ/2); m<mend; )
49  {
50  rngstep(~(a^(a<<21)), a, b, rng->mm, m, m2, r, x);
51  rngstep( a^(a>>5) , a, b, rng->mm, m, m2, r, x);
52  rngstep( a^(a<<12) , a, b, rng->mm, m, m2, r, x);
53  rngstep( a^(a>>33) , a, b, rng->mm, m, m2, r, x);
54  }
55  for (m2 = rng->mm; m2<mend; )
56  {
57  rngstep(~(a^(a<<21)), a, b, rng->mm, m, m2, r, x);
58  rngstep( a^(a>>5) , a, b, rng->mm, m, m2, r, x);
59  rngstep( a^(a<<12) , a, b, rng->mm, m, m2, r, x);
60  rngstep( a^(a>>33) , a, b, rng->mm, m, m2, r, x);
61  }
62  rng->bb = b; rng->aa = a;
63 }
64 
65 
66 
67 void isaac64_init(struct isaac64_state *rng, ub4 seed)
68 {
69  ub8 *r, *m;
70  ub8 a,b,c,d,e,f,g,h;
71  ub4 i;
72 
73  rng->aa=(ub8)0;
74  rng->bb=(ub8)0;
75  rng->cc=(ub8)0;
76 
77  a=b=c=d=e=f=g=h=0x9e3779b97f4a7c13LL; /* the golden ratio */
78 
79  r = rng->randrsl;
80  m = rng->mm;
81 
82  for (i=0; i<RANDSIZ; ++i) r[i]=(ub8)0;
83 
84  r[0]=seed;
85 
86  for (i=0; i<4; ++i) /* scramble it */
87  {
88  mix(a,b,c,d,e,f,g,h);
89  }
90 
91  for (i=0; i<RANDSIZ; i+=8) /* fill in m[] with messy stuff */
92  {
93  /* use all the information in the seed */
94  a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
95  e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
96  mix(a,b,c,d,e,f,g,h);
97  m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
98  m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
99  }
100 
101  /* do a second pass to make all of the seed affect all of m[] */
102  for (i=0; i<RANDSIZ; i+=8)
103  {
104  a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
105  e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
106  mix(a,b,c,d,e,f,g,h);
107  m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
108  m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
109  }
110 
111  isaac64_generate(rng); /* fill in the first set of results */
112  rng->randcnt=RANDMAX; /* prepare to use the first set of results */
113 }
114 
#define RANDMAX
Definition: isaac64.h:25
ub8 mm[RANDSIZ]
Definition: isaac64.h:48
#define g
Definition: passive0.cpp:23
void isaac64_generate(struct isaac64_state *rng)
Definition: isaac64.cpp:42
unsigned int ub4
Definition: isaac64.h:31
#define e
Definition: passive0.cpp:24
unsigned long long ub8
Definition: isaac64.h:27
ub8 randrsl[RANDSIZ]
Definition: isaac64.h:47
int randcnt
Definition: isaac64.h:43
#define i
Definition: md1redef.h:12
#define c
void isaac64_init(struct isaac64_state *rng, ub4 seed)
Definition: isaac64.cpp:67
#define rngstep(mix, a, b, mm, m, m2, r, x)
Definition: isaac64.cpp:20
#define mix(a, b, c, d, e, f, g, h)
Definition: isaac64.cpp:28
#define RANDSIZ
Definition: isaac64.h:24