1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     math_MersenneTwister.h
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 47802 $
14  *---------------------------------------------------------------------------*/
15 
16 /* Please see man pages for details
17 
18 
19 
20 */
21 
22 #ifndef NN_MATH_MATH_MERSENNETWISTER_H_
23 #define NN_MATH_MATH_MERSENNETWISTER_H_
24 
25 #include <nn/types.h>
26 
27 namespace nn { namespace math {
28 
29     /* ------------------------------------------------------------------------
30             Class definitions
31        ------------------------------------------------------------------------ */
32 
33     //----------------------------------------------------------------------
34     //
35     //
36     //
37     //
38     //
39     //
40     //
41     //
42     //
43     //
44     //
45     //
46     //
47     //
48     //
49     //----------------------------------------------------------------------
50     class MersenneTwister
51     {
52     private:
53         static const int   PARAMETER_W  =  32;
54         static const int   PARAMETER_N  = 624;
55         static const int   PARAMETER_M  = 397;
56         static const int   PARAMETER_R  =  31;
57         static const int   PARAMETER_U  =  11;
58         static const int   PARAMETER_S  =   7;
59         static const int   PARAMETER_T  =  15;
60         static const int   PARAMETER_L  =  18;
61 
62         static const bit32 PARAMETER_A  = 0x9908b0df;
63         static const bit32 PARAMETER_B  = 0x9d2c5680;
64         static const bit32 PARAMETER_C  = 0xefc60000;
65 
66         static const bit32 MIX_MASK = (~0u << PARAMETER_R);
67 
68     public:
69         //----------------------------------------------------------------------
70         //
71         //----------------------------------------------------------------------
72         struct State
73         {
74             //----------------------------------------------------------------------
75             //
76             //----------------------------------------------------------------------
77             int     index;
78 
79             //----------------------------------------------------------------------
80             //
81             //----------------------------------------------------------------------
82             bit32   state[PARAMETER_N];
83         };
84 
85     private:
86         int     m_Index;
87         bit32   m_State[PARAMETER_N];
88 
89     public:
90 
91     //
92     //
93 
94         //----------------------------------------------------------------------
95         //
96         //
97         //
98         //
99         //
100         //----------------------------------------------------------------------
101         void Initialize();
102 
103         //----------------------------------------------------------------------
104         //
105         //
106         //
107         //
108         //
109         //----------------------------------------------------------------------
110         void Initialize(bit32 seed);
111 
112         //----------------------------------------------------------------------
113         //
114         //
115         //
116         //
117         //
118         //
119         //----------------------------------------------------------------------
120         void Initialize(const bit32* pSeed, int numSeed);
121 
122         //----------------------------------------------------------------------
123         //
124         //----------------------------------------------------------------------
Finalize()125         void Finalize(){}
126 
127     //
128 
129     //
130     //
131 
132         //----------------------------------------------------------------------
133         //
134         //
135         //
136         //
137         //
138         //
139         //
140         //
141         //
142         //
143         //
144         //----------------------------------------------------------------------
145         void SaveState(MersenneTwister::State* pStateBuffer);
146 
147         //----------------------------------------------------------------------
148         //
149         //
150         //
151         //
152         //
153         //
154         //
155         //
156         //----------------------------------------------------------------------
157         void RestoreState(const MersenneTwister::State* pStateBuffer);
158 
159     //
160 
161     //
162     //
163 
164         //----------------------------------------------------------------------
165         //
166         //
167         //
168         //
169         //
170         //----------------------------------------------------------------------
171         u32 GenerateRandomU32();
172 
173         //----------------------------------------------------------------------
174         //
175         //
176         //
177         //
178         //
179         //----------------------------------------------------------------------
180         u64 GenerateRandomU64();
181 
182         //----------------------------------------------------------------------
183         //
184         //
185         //
186         //----------------------------------------------------------------------
187         f32 GenerateRandomF32();
188 
189         //----------------------------------------------------------------------
190         //
191         //
192         //
193         //----------------------------------------------------------------------
194         f64 GenerateRandomF64();
195 
196         //----------------------------------------------------------------------
197         //
198         //
199         //
200         //
201         //
202         //
203         //
204         //
205         //
206         //
207         //
208         //
209         //
210         //
211         //
212         //
213         //
214         //
215         //
216         //
217         //
218         //
219         //----------------------------------------------------------------------
220         u32 GenerateRandomN(u16 num);
221 
222         //----------------------------------------------------------------------
223         //
224         //
225         //
226         //
227         //
228         //
229         //
230         //----------------------------------------------------------------------
231         void GenerateRandomBytes(void* p, size_t size);
232 
233     //
234 
235 
236     private:
GenerateRandomU24()237         u32 GenerateRandomU24()
238         {
239             return GenerateRandomU32() >> 8;
240         }
241 
242         static inline bit32 MixBits(bit32 u, bit32 l);
243         static inline bit32 GenerateXkn(bit32 xkm, bit32 xk, bit32 xk1);
244     };
245 
246 
247 
248     /* ------------------------------------------------------------------------
249             Inline member function definitions
250        ------------------------------------------------------------------------ */
251 
GenerateRandomU64()252     inline u64 MersenneTwister::GenerateRandomU64()
253     {
254         const u32 lo = GenerateRandomU32();
255         const u32 hi = GenerateRandomU32();
256         return (static_cast<u64>(hi) << 32) | lo;
257     }
258 
GenerateRandomF32()259     inline f32 MersenneTwister::GenerateRandomF32()
260     {
261         return GenerateRandomU24() * (1.0f / (1ull << 24));
262     }
263 
GenerateRandomF64()264     inline f64 MersenneTwister::GenerateRandomF64()
265     {
266         static const int RESOLUTION = 53;
267         static const int U32_BITS   = 32;
268         static const int A_SHIFT    = (2 * U32_BITS - RESOLUTION) / 2;
269         static const int B_SHIFT    = (2 * U32_BITS - RESOLUTION) - A_SHIFT;
270         //static const int A_BITS     = U32_BITS - A_SHIFT;
271         static const int B_BITS     = U32_BITS - B_SHIFT;
272 
273         u32 a = (GenerateRandomU32() >> A_SHIFT);
274         u32 b = (GenerateRandomU32() >> B_SHIFT);
275 
276         return (1.0 * a * (1u << B_BITS) + b) * (1.0 / (1ull << RESOLUTION));
277     }
278 
GenerateRandomN(u16 max)279     inline u32 MersenneTwister::GenerateRandomN(u16 max)
280     {
281         return static_cast<u32>((static_cast<u64>(GenerateRandomU32()) * max) >> 32);
282     }
283 
284 
285 
286 }}
287 
288 
289 /* NN_MATH_MATH_MERSENNETWISTER_H_ */
290 #endif
291