ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkMersenneTwisterRandomVariateGenerator.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkMersenneTwisterRandomVariateGenerator_h
19#define itkMersenneTwisterRandomVariateGenerator_h
20
21#include "itkMacro.h"
22#include "itkObjectFactory.h"
24#include "itkIntTypes.h"
25#include "itkMath.h"
26#include "itkSingletonMacro.h"
27
28#include <atomic>
29#include <mutex>
30#include <climits>
31#include <ctime>
32
33namespace itk
34{
35namespace Statistics
36{
121
122struct MersenneTwisterGlobals;
123
125{
126public:
132
133 using IntegerType = uint32_t;
134
136 itkOverrideGetNameOfClassMacro(MersenneTwisterRandomVariateGenerator);
137
146 static Pointer
148
157 static Pointer
159
162 static void
164
166 static constexpr IntegerType StateVectorLength = 624;
167
169 void
170 Initialize(const IntegerType seed);
171
172 /* Initialize with clock time */
173 void
174 Initialize();
175
177 double
179
181 double
182 GetVariateWithClosedRange(const double n);
183
185 double
187
189 double
190 GetVariateWithOpenUpperRange(const double n);
191
193 double
195
197 double
198 GetVariateWithOpenRange(const double n);
199
203
207
210 double
212
213 /* Access to a normal random number distribution
214 * TODO: Compare with vnl_sample_normal */
215 double
216 GetNormalVariate(const double mean = 0.0, const double variance = 1.0);
217
218 /* Access to a uniform random number distribution in the range [a, b)
219 * TODO: Compare with vnl_sample_uniform */
220 double
221 GetUniformVariate(const double a, const double b);
222
228 double
229 GetVariate() override;
230
232 double
233 operator()();
234
239 inline void
240 SetSeed(const IntegerType oneSeed);
241 inline void
242 SetSeed();
244
250 GetSeed() const;
251
257 static IntegerType
259
260 /*
261 // Saving and loading generator state
262 void save( IntegerType* saveArray ) const; // to array of size SAVE
263 void load( IntegerType *const loadArray ); // from such array
264 */
265
266protected:
269 void
270 PrintSelf(std::ostream & os, Indent indent) const override;
271
273 static constexpr unsigned int M = 397;
274
276 void
277 reload();
278
280 hiBit(const IntegerType & u) const
281 {
282 return u & 0x80000000;
283 }
284 IntegerType
285 loBit(const IntegerType & u) const
286 {
287 return u & 0x00000001;
288 }
289 IntegerType
290 loBits(const IntegerType & u) const
291 {
292 return u & 0x7fffffff;
293 }
294 IntegerType
295 mixBits(const IntegerType & u, const IntegerType & v) const
296 {
297 return hiBit(u) | loBits(v);
298 }
299
300 IntegerType
301 twist(const IntegerType & m, const IntegerType & s0, const IntegerType & s1) const
302 {
303 return m ^ (mixBits(s0, s1) >> 1) ^ (-static_cast<int32_t>(loBit(s1)) & 0x9908b0df);
304 }
305
306 static IntegerType
307 hash(time_t t, clock_t c);
308
309 // Internal state
311
312 // Next value to get from state
314
315 // Number of values left before reload is needed
316 int m_Left{};
317
318 // Seed value
319 std::atomic<IntegerType> m_Seed{};
320
321private:
323 itkGetGlobalDeclarationMacro(MersenneTwisterGlobals, PimplGlobals);
324
326 static Pointer
328
329 // Local lock to enable concurrent access to singleton
330 std::mutex m_InstanceMutex{};
331
332 // Static/Global Variable need to be thread-safely accessed
333
334 static MersenneTwisterGlobals * m_PimplGlobals;
335
336}; // end of class
337
338// Declare inlined functions.... (must be declared in the header)
339
340inline void
342{
343 const std::lock_guard<std::mutex> lockGuard(m_InstanceMutex);
344 this->m_Seed = seed;
345 // Initialize generator state with seed
346 // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
347 // In previous versions, most significant bits (MSBs) of the seed affect
348 // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
349 IntegerType * s = state;
350 IntegerType * r = state;
351
352 *s++ = seed & 0xffffffffUL;
354 {
355 *s++ = (1812433253UL * (*r ^ (*r >> 30)) + i) & 0xffffffffUL;
356 ++r;
357 }
358 reload();
359}
360
361inline void
363{
364 // Generate N new values in state
365 // Made clearer and faster by Matthew Bellew
366 // matthew dot bellew at home dot com
367
368 // get rid of VS warning
369 constexpr auto index = int{ M } - int{ MersenneTwisterRandomVariateGenerator::StateVectorLength };
370
371 IntegerType * p = state;
372
374 {
375 *p = twist(p[M], p[0], p[1]);
376 }
377 for (int i = M; --i; ++p)
378 {
379 *p = twist(p[index], p[0], p[1]);
380 }
381 *p = twist(p[index], p[0], state[0]);
382
384 m_PNext = state;
385}
386
387inline void
392
393inline void
395{
396 // Seed the generator with a simple IntegerType
397 Initialize(oneSeed);
398}
399
400inline void
402{
403 // use time() and clock() to generate a unlikely-to-repeat seed.
404 SetSeed(hash(time(nullptr), clock()));
405}
406
407
410{
411 return this->m_Seed;
412}
413
417{
418 if (m_Left == 0)
419 {
420 reload();
421 }
422 --m_Left;
424
425 IntegerType s1 = *m_PNext++;
426 s1 ^= (s1 >> 11);
427 s1 ^= (s1 << 7) & 0x9d2c5680;
428 s1 ^= (s1 << 15) & 0xefc60000;
429 return (s1 ^ (s1 >> 18));
430}
431
432inline double
434{
435 return static_cast<double>(GetIntegerVariate()) * (1.0 / 4294967295.0);
436}
437
439inline double
444
446inline double
448{
449 return static_cast<double>(GetIntegerVariate()) * (1.0 / 4294967296.0);
450}
451
453inline double
458
460inline double
462{
463 return (static_cast<double>(GetIntegerVariate()) + 0.5) * (1.0 / 4294967296.0);
464}
465
467inline double
472
475{
476 // Find which bits are used in n
477 IntegerType used = n;
478
479 used |= used >> 1;
480 used |= used >> 2;
481 used |= used >> 4;
482 used |= used >> 8;
483 used |= used >> 16;
484
485 // Draw numbers until one is found in [0,n]
486 IntegerType i;
487 do
488 {
489 i = GetIntegerVariate() & used; // toss unused bits to shorten search
490 } while (i > n);
491
492 return i;
493}
494
497inline double
499{
500 const IntegerType a = GetIntegerVariate() >> 5;
501 const IntegerType b = GetIntegerVariate() >> 6;
503
504 return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); // by Isaku
505 // Wada
506}
507
509// TODO: Compare with vnl_sample_normal
510inline double
511MersenneTwisterRandomVariateGenerator::GetNormalVariate(const double mean, const double variance)
512{
513 // Return a real number from a normal (Gaussian) distribution with given
514 // mean and variance by Box-Muller method
515 const double r = std::sqrt(-2.0 * std::log(1.0 - GetVariateWithOpenRange()) * variance);
516 const double phi = 2.0 * itk::Math::pi * GetVariateWithOpenUpperRange();
518
519 return mean + r * std::cos(phi);
520}
521
523// TODO: Compare with vnl_sample_uniform
524inline double
526{
527 const double u = GetVariateWithOpenUpperRange();
528
529 return ((1.0 - u) * a + u * b);
530}
531
532inline double
537
538inline double
543
544/* Change log from MTRand.h */
545// Change log:
546//
547// v0.1 - First release on 15 May 2000
548// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
549// - Translated from C to C++
550// - Made completely ANSI compliant
551// - Designed convenient interface for initialization, seeding, and
552// obtaining numbers in default or user-defined ranges
553// - Added automatic seeding from /dev/urandom or time() and clock()
554// - Provided functions for saving and loading generator state
555//
556// v0.2 - Fixed bug which reloaded generator one step too late
557//
558// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
559//
560// v0.4 - Removed trailing newline in saved generator format to be consistent
561// with output format of built-in types
562//
563// v0.5 - Improved portability by replacing static const int's with enum's and
564// clarifying return values in seed(); suggested by Eric Heimburg
565// - Removed MAXINT constant; use 0xffffffffUL instead
566//
567// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
568// - Changed integer [0,n] generator to give better uniformity
569//
570// v0.7 - Fixed operator precedence ambiguity in reload()
571// - Added access for real numbers in (0,1) and (0,n)
572//
573// v0.8 - Included time.h header to properly support time_t and clock_t
574//
575// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
576// - Allowed for seeding with arrays of any length
577// - Added access for real numbers in [0,1) with 53-bit resolution
578// - Added access for real numbers from normal (Gaussian) distributions
579// - Increased overall speed by optimizing twist()
580// - Doubled speed of integer [0,n] generation
581// - Fixed out-of-range number generation on 64-bit machines
582// - Improved portability by substituting literal constants for long enum's
583// - Changed license from GNU LGPL to BSD
584} // end namespace Statistics
585} // end namespace itk
586
587#endif
Control indentation during Print() invocation.
Definition itkIndent.h:50
Implements transparent reference counting.
IntegerType mixBits(const IntegerType &u, const IntegerType &v) const
static Pointer New()
Method for creation through the object factory.
void PrintSelf(std::ostream &os, Indent indent) const override
IntegerType twist(const IntegerType &m, const IntegerType &s0, const IntegerType &s1) const
static IntegerType hash(time_t t, clock_t c)
itkGetGlobalDeclarationMacro(MersenneTwisterGlobals, PimplGlobals)
double GetNormalVariate(const double mean=0.0, const double variance=1.0)
static constexpr double pi
Definition itkMath.h:66
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....