ITK  6.0.0
Insight Toolkit
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 
33 namespace itk
34 {
35 namespace Statistics
36 {
125 struct MersenneTwisterGlobals;
126 
128 {
129 public:
135 
136  using IntegerType = uint32_t;
137 
139  itkOverrideGetNameOfClassMacro(MersenneTwisterRandomVariateGenerator);
140 
149  static Pointer
150  New();
151 
160  static Pointer
161  GetInstance();
162 
165  static void
166  ResetNextSeed();
167 
169  static constexpr IntegerType StateVectorLength = 624;
170 
172  void
173  Initialize(const IntegerType seed);
174 
175  /* Initialize with clock time */
176  void
177  Initialize();
178 
180  double
181  GetVariateWithClosedRange();
182 
184  double
185  GetVariateWithClosedRange(const double n);
186 
188  double
189  GetVariateWithOpenUpperRange();
190 
192  double
193  GetVariateWithOpenUpperRange(const double n);
194 
196  double
197  GetVariateWithOpenRange();
198 
200  double
201  GetVariateWithOpenRange(const double n);
202 
205  GetIntegerVariate();
206 
209  GetIntegerVariate(const IntegerType & n);
210 
213  double
214  Get53BitVariate();
215 
216  /* Access to a normal random number distribution
217  * TODO: Compare with vnl_sample_normal */
218  double
219  GetNormalVariate(const double mean = 0.0, const double variance = 1.0);
220 
221  /* Access to a uniform random number distribution in the range [a, b)
222  * TODO: Compare with vnl_sample_uniform */
223  double
224  GetUniformVariate(const double a, const double b);
225 
231  double
232  GetVariate() override;
233 
235  double
236  operator()();
237 
242  inline void
243  SetSeed(const IntegerType oneSeed);
244  inline void
245  SetSeed();
253  GetSeed() const;
254 
260  static IntegerType
261  GetNextSeed();
262 
263  /*
264  // Saving and loading generator state
265  void save( IntegerType* saveArray ) const; // to array of size SAVE
266  void load( IntegerType *const loadArray ); // from such array
267  */
268 
269 protected:
272  void
273  PrintSelf(std::ostream & os, Indent indent) const override;
274 
276  static constexpr unsigned int M = 397;
277 
279  void
280  reload();
281 
283  hiBit(const IntegerType & u) const
284  {
285  return u & 0x80000000;
286  }
287  IntegerType
288  loBit(const IntegerType & u) const
289  {
290  return u & 0x00000001;
291  }
292  IntegerType
293  loBits(const IntegerType & u) const
294  {
295  return u & 0x7fffffff;
296  }
297  IntegerType
298  mixBits(const IntegerType & u, const IntegerType & v) const
299  {
300  return hiBit(u) | loBits(v);
301  }
302 
303  IntegerType
304  twist(const IntegerType & m, const IntegerType & s0, const IntegerType & s1) const
305  {
306  return m ^ (mixBits(s0, s1) >> 1) ^ (-static_cast<int32_t>(loBit(s1)) & 0x9908b0df);
307  }
308 
309  static IntegerType
310  hash(time_t t, clock_t c);
311 
312  // Internal state
313  IntegerType state[StateVectorLength];
314 
315  // Next value to get from state
316  IntegerType * m_PNext{};
317 
318  // Number of values left before reload is needed
319  int m_Left{};
320 
321  // Seed value
322  std::atomic<IntegerType> m_Seed{};
323 
324 private:
326  itkGetGlobalDeclarationMacro(MersenneTwisterGlobals, PimplGlobals);
327 
329  static Pointer
330  CreateInstance();
331 
332  // Local lock to enable concurrent access to singleton
333  std::mutex m_InstanceMutex{};
334 
335  // Static/Global Variable need to be thread-safely accessed
336 
337  static MersenneTwisterGlobals * m_PimplGlobals;
338 
339 }; // end of class
340 
341 // Declare inlined functions.... (must be declared in the header)
342 
343 inline void
345 {
346  const std::lock_guard<std::mutex> lockGuard(m_InstanceMutex);
347  this->m_Seed = seed;
348  // Initialize generator state with seed
349  // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
350  // In previous versions, most significant bits (MSBs) of the seed affect
351  // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
352  IntegerType * s = state;
353  IntegerType * r = state;
354  IntegerType i = 1;
355 
356  *s++ = seed & 0xffffffffUL;
358  {
359  *s++ = (1812433253UL * (*r ^ (*r >> 30)) + i) & 0xffffffffUL;
360  ++r;
361  }
362  reload();
363 }
364 
365 inline void
367 {
368  // Generate N new values in state
369  // Made clearer and faster by Matthew Bellew
370  // matthew dot bellew at home dot com
371 
372  // get rid of VS warning
373  constexpr auto index = int{ M } - int{ MersenneTwisterRandomVariateGenerator::StateVectorLength };
374 
375  IntegerType * p = state;
376 
378  {
379  *p = twist(p[M], p[0], p[1]);
380  }
381  for (int i = M; --i; ++p)
382  {
383  *p = twist(p[index], p[0], p[1]);
384  }
385  *p = twist(p[index], p[0], state[0]);
386 
388  m_PNext = state;
389 }
390 
391 inline void
393 {
394  SetSeed();
395 }
396 
397 inline void
399 {
400  // Seed the generator with a simple IntegerType
401  Initialize(oneSeed);
402 }
403 
404 inline void
406 {
407  // use time() and clock() to generate a unlikely-to-repeat seed.
408  SetSeed(hash(time(nullptr), clock()));
409 }
410 
411 
414 {
415  return this->m_Seed;
416 }
417 
421 {
422  if (m_Left == 0)
423  {
424  reload();
425  }
426  --m_Left;
429  IntegerType s1 = *m_PNext++;
430  s1 ^= (s1 >> 11);
431  s1 ^= (s1 << 7) & 0x9d2c5680;
432  s1 ^= (s1 << 15) & 0xefc60000;
433  return (s1 ^ (s1 >> 18));
434 }
435 
436 inline double
438 {
439  return static_cast<double>(GetIntegerVariate()) * (1.0 / 4294967295.0);
440 }
441 
443 inline double
445 {
446  return GetVariateWithClosedRange() * n;
447 }
448 
450 inline double
452 {
453  return static_cast<double>(GetIntegerVariate()) * (1.0 / 4294967296.0);
454 }
455 
457 inline double
459 {
460  return GetVariateWithOpenUpperRange() * n;
461 }
462 
464 inline double
466 {
467  return (static_cast<double>(GetIntegerVariate()) + 0.5) * (1.0 / 4294967296.0);
468 }
469 
471 inline double
473 {
474  return GetVariateWithOpenRange() * n;
475 }
476 
479 {
480  // Find which bits are used in n
481  IntegerType used = n;
482 
483  used |= used >> 1;
484  used |= used >> 2;
485  used |= used >> 4;
486  used |= used >> 8;
487  used |= used >> 16;
488 
489  // Draw numbers until one is found in [0,n]
490  IntegerType i;
491  do
492  {
493  i = GetIntegerVariate() & used; // toss unused bits to shorten search
494  } while (i > n);
495 
496  return i;
497 }
498 
501 inline double
503 {
504  const IntegerType a = GetIntegerVariate() >> 5;
505  const IntegerType b = GetIntegerVariate() >> 6;
508  return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); // by Isaku
509  // Wada
510 }
511 
513 // TODO: Compare with vnl_sample_normal
514 inline double
515 MersenneTwisterRandomVariateGenerator::GetNormalVariate(const double mean, const double variance)
516 {
517  // Return a real number from a normal (Gaussian) distribution with given
518  // mean and variance by Box-Muller method
519  const double r = std::sqrt(-2.0 * std::log(1.0 - GetVariateWithOpenRange()) * variance);
520  const double phi = 2.0 * itk::Math::pi * GetVariateWithOpenUpperRange();
523  return mean + r * std::cos(phi);
524 }
525 
527 // TODO: Compare with vnl_sample_uniform
528 inline double
530 {
531  const double u = GetVariateWithOpenUpperRange();
532 
533  return ((1.0 - u) * a + u * b);
534 }
535 
536 inline double
538 {
539  return GetVariateWithClosedRange();
540 }
541 
542 inline double
544 {
545  return GetVariate();
546 }
547 
548 /* Change log from MTRand.h */
549 // Change log:
550 //
551 // v0.1 - First release on 15 May 2000
552 // - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
553 // - Translated from C to C++
554 // - Made completely ANSI compliant
555 // - Designed convenient interface for initialization, seeding, and
556 // obtaining numbers in default or user-defined ranges
557 // - Added automatic seeding from /dev/urandom or time() and clock()
558 // - Provided functions for saving and loading generator state
559 //
560 // v0.2 - Fixed bug which reloaded generator one step too late
561 //
562 // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
563 //
564 // v0.4 - Removed trailing newline in saved generator format to be consistent
565 // with output format of built-in types
566 //
567 // v0.5 - Improved portability by replacing static const int's with enum's and
568 // clarifying return values in seed(); suggested by Eric Heimburg
569 // - Removed MAXINT constant; use 0xffffffffUL instead
570 //
571 // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
572 // - Changed integer [0,n] generator to give better uniformity
573 //
574 // v0.7 - Fixed operator precedence ambiguity in reload()
575 // - Added access for real numbers in (0,1) and (0,n)
576 //
577 // v0.8 - Included time.h header to properly support time_t and clock_t
578 //
579 // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
580 // - Allowed for seeding with arrays of any length
581 // - Added access for real numbers in [0,1) with 53-bit resolution
582 // - Added access for real numbers from normal (Gaussian) distributions
583 // - Increased overall speed by optimizing twist()
584 // - Doubled speed of integer [0,n] generation
585 // - Fixed out-of-range number generation on 64-bit machines
586 // - Improved portability by substituting literal constants for long enum's
587 // - Changed license from GNU LGPL to BSD
588 } // end namespace Statistics
589 } // end namespace itk
590 
591 #endif
Pointer
SmartPointer< Self > Pointer
Definition: itkAddImageFilter.h:93
itk::Statistics::MersenneTwisterRandomVariateGenerator::mixBits
IntegerType mixBits(const IntegerType &u, const IntegerType &v) const
Definition: itkMersenneTwisterRandomVariateGenerator.h:298
itk::Statistics::MersenneTwisterRandomVariateGenerator::hiBit
IntegerType hiBit(const IntegerType &u) const
Definition: itkMersenneTwisterRandomVariateGenerator.h:283
itkObjectFactory.h
itk::Statistics::MersenneTwisterRandomVariateGenerator
MersenneTwisterRandom random variate generator.
Definition: itkMersenneTwisterRandomVariateGenerator.h:127
itk::Statistics::MersenneTwisterRandomVariateGenerator::m_Left
int m_Left
Definition: itkMersenneTwisterRandomVariateGenerator.h:319
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetNormalVariate
double GetNormalVariate(const double mean=0.0, const double variance=1.0)
Definition: itkMersenneTwisterRandomVariateGenerator.h:515
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetVariate
double GetVariate() override
Definition: itkMersenneTwisterRandomVariateGenerator.h:537
itk::Statistics::MersenneTwisterRandomVariateGenerator::hash
static IntegerType hash(time_t t, clock_t c)
itk::Statistics::MersenneTwisterRandomVariateGenerator::state
IntegerType state[StateVectorLength]
Definition: itkMersenneTwisterRandomVariateGenerator.h:313
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetSeed
IntegerType GetSeed() const
Definition: itkMersenneTwisterRandomVariateGenerator.h:413
itkSingletonMacro.h
itk::Statistics::MersenneTwisterRandomVariateGenerator::loBit
IntegerType loBit(const IntegerType &u) const
Definition: itkMersenneTwisterRandomVariateGenerator.h:288
itk::Statistics::MersenneTwisterRandomVariateGenerator::SetSeed
void SetSeed()
Definition: itkMersenneTwisterRandomVariateGenerator.h:405
itk::SmartPointer< Self >
itk::Indent
Control indentation during Print() invocation.
Definition: itkIndent.h:49
itk::Statistics::MersenneTwisterRandomVariateGenerator::M
static constexpr unsigned int M
Definition: itkMersenneTwisterRandomVariateGenerator.h:276
itk::Statistics::RandomVariateGeneratorBase
Defines common interfaces for random variate generators.
Definition: itkRandomVariateGeneratorBase.h:33
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetVariateWithOpenRange
double GetVariateWithOpenRange()
Definition: itkMersenneTwisterRandomVariateGenerator.h:465
itk::LightObject
Light weight base class for most itk classes.
Definition: itkLightObject.h:55
itkMacro.h
itkRandomVariateGeneratorBase.h
itk::Statistics::MersenneTwisterRandomVariateGenerator::m_InstanceMutex
std::mutex m_InstanceMutex
Definition: itkMersenneTwisterRandomVariateGenerator.h:333
itk::Statistics::MersenneTwisterRandomVariateGenerator::twist
IntegerType twist(const IntegerType &m, const IntegerType &s0, const IntegerType &s1) const
Definition: itkMersenneTwisterRandomVariateGenerator.h:304
itk::Statistics::MersenneTwisterRandomVariateGenerator::operator()
double operator()()
Definition: itkMersenneTwisterRandomVariateGenerator.h:543
itkIntTypes.h
itk::Statistics::MersenneTwisterRandomVariateGenerator::Get53BitVariate
double Get53BitVariate()
Definition: itkMersenneTwisterRandomVariateGenerator.h:502
itk::Statistics::MersenneTwisterRandomVariateGenerator::m_PNext
IntegerType * m_PNext
Definition: itkMersenneTwisterRandomVariateGenerator.h:316
itk::Statistics::MersenneTwisterRandomVariateGenerator::IntegerType
uint32_t IntegerType
Definition: itkMersenneTwisterRandomVariateGenerator.h:136
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetUniformVariate
double GetUniformVariate(const double a, const double b)
Definition: itkMersenneTwisterRandomVariateGenerator.h:529
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetVariateWithClosedRange
double GetVariateWithClosedRange()
Definition: itkMersenneTwisterRandomVariateGenerator.h:437
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnatomicalOrientation.h:29
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetVariateWithOpenUpperRange
double GetVariateWithOpenUpperRange()
Definition: itkMersenneTwisterRandomVariateGenerator.h:451
itkGetGlobalDeclarationMacro
#define itkGetGlobalDeclarationMacro(Type, VarName)
Definition: itkSingletonMacro.h:34
itk::Statistics::MersenneTwisterRandomVariateGenerator::m_Seed
std::atomic< IntegerType > m_Seed
Definition: itkMersenneTwisterRandomVariateGenerator.h:322
itk::Statistics::MersenneTwisterRandomVariateGenerator::loBits
IntegerType loBits(const IntegerType &u) const
Definition: itkMersenneTwisterRandomVariateGenerator.h:293
New
static Pointer New()
itk::Statistics::MersenneTwisterRandomVariateGenerator::StateVectorLength
static constexpr IntegerType StateVectorLength
Definition: itkMersenneTwisterRandomVariateGenerator.h:169
itk::Math::pi
static constexpr double pi
Definition: itkMath.h:66
itkMath.h
itk::Statistics::MersenneTwisterRandomVariateGenerator::Initialize
void Initialize()
Definition: itkMersenneTwisterRandomVariateGenerator.h:392
itk::Statistics::MersenneTwisterRandomVariateGenerator::GetIntegerVariate
IntegerType GetIntegerVariate()
Definition: itkMersenneTwisterRandomVariateGenerator.h:420
itk::Statistics::MersenneTwisterRandomVariateGenerator::m_PimplGlobals
static MersenneTwisterGlobals * m_PimplGlobals
Definition: itkMersenneTwisterRandomVariateGenerator.h:337
itk::Statistics::MersenneTwisterRandomVariateGenerator::reload
void reload()
Definition: itkMersenneTwisterRandomVariateGenerator.h:366