ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkMersenneTwisterRandomVariateGenerator.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
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  * http://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 <mutex>
27 #include "itkSingletonMacro.h"
28 #include <climits>
29 #include <ctime>
30 
31 namespace itk
32 {
33 namespace Statistics
34 {
123 struct MersenneTwisterGlobals;
124 
127 {
128 public:
129 
135 
137 
141 
150  static Pointer New();
151 
160  static Pointer GetInstance();
161 
163  static constexpr IntegerType StateVectorLength = 624;
164 
166  void Initialize(const IntegerType oneSeed);
167 
168  /* Initialize with clock time */
169  void Initialize();
170 
172  double GetVariateWithClosedRange();
173 
175  double GetVariateWithClosedRange(const double & n);
176 
178  double GetVariateWithOpenUpperRange();
179 
181  double GetVariateWithOpenUpperRange(const double & n);
182 
184  double GetVariateWithOpenRange();
185 
187  double GetVariateWithOpenRange(const double & n);
188 
190  IntegerType GetIntegerVariate();
191 
193  IntegerType GetIntegerVariate(const IntegerType & n);
194 
197  double Get53BitVariate();
198 
199  /* Access to a normal random number distribution
200  * TODO: Compare with vnl_sample_normal */
201  double GetNormalVariate(const double & mean = 0.0,
202  const double & variance = 1.0);
203 
204  /* Access to a uniform random number distribution in the range [a, b)
205  * TODO: Compare with vnl_sample_uniform */
206  double GetUniformVariate(const double & a, const double & b);
207 
213  double GetVariate() override;
214 
216  double operator()();
217 
222  inline void SetSeed(const IntegerType oneSeed);
223  inline void SetSeed();
225 
230  IntegerType GetSeed();
231 
237  static IntegerType GetNextSeed();
238 
239  /*
240  // Saving and loading generator state
241  void save( IntegerType* saveArray ) const; // to array of size SAVE
242  void load( IntegerType *const loadArray ); // from such array
243  */
244 
245 protected:
248  void PrintSelf(std::ostream & os, Indent indent) const override;
249 
251  static constexpr unsigned int M = 397;
252 
254  void reload();
255 
256  IntegerType hiBit(const IntegerType & u) const { return u & 0x80000000; }
257  IntegerType loBit(const IntegerType & u) const { return u & 0x00000001; }
258  IntegerType loBits(const IntegerType & u) const { return u & 0x7fffffff; }
259  IntegerType mixBits(const IntegerType & u, const IntegerType & v) const
260  {
261  return hiBit(u) | loBits(v);
262  }
263 
264  IntegerType twist(const IntegerType & m, const IntegerType & s0, const IntegerType & s1) const
265  {
266  return m ^ ( mixBits(s0, s1) >> 1 ) ^ ( -static_cast<int32_t>(loBit(s1)) & 0x9908b0df );
267  }
268 
269  static IntegerType hash(time_t t, clock_t c);
270 
271  // Internal state
272  IntegerType state[StateVectorLength];
273 
274  // Next value to get from state
276 
277  // Number of values left before reload is needed
278  int m_Left;
279 
280  // Seed value
282 
283 private:
284 
286  itkGetGlobalDeclarationMacro(MersenneTwisterGlobals, PimplGlobals);
287 
289  static Pointer CreateInstance();
290 
291  // Local lock to enable concurrent access to singleton
292  std::mutex m_InstanceLock;
293 
294  // Static/Global Variable need to be thread-safely accessed
295 
296  static MersenneTwisterGlobals *m_PimplGlobals;
297 
298 }; // end of class
299 
300 // Declare inlined functions.... (must be declared in the header)
301 
302 inline void
304 {
305  std::lock_guard<std::mutex> mutexHolder(m_InstanceLock);
306  this->m_Seed = seed;
307  // Initialize generator state with seed
308  // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
309  // In previous versions, most significant bits (MSBs) of the seed affect
310  // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
311  IntegerType *s = state;
312  IntegerType *r = state;
313  IntegerType i = 1;
314 
315  *s++ = seed & 0xffffffffUL;
317  {
318  *s++ = ( 1812433253UL * ( *r ^ ( *r >> 30 ) ) + i ) & 0xffffffffUL;
319  r++;
320  }
321  reload();
322 }
323 
324 inline void
326 {
327  // Generate N new values in state
328  // Made clearer and faster by Matthew Bellew
329  // matthew dot bellew at home dot com
330 
331  // get rid of VS warning
332  auto index = static_cast< int >(
334 
335  IntegerType *p = state;
336  int i;
337 
339  {
340  *p = twist(p[M], p[0], p[1]);
341  }
342  for ( i = M; --i; ++p )
343  {
344  *p = twist(p[index], p[0], p[1]);
345  }
346  *p = twist(p[index], p[0], state[0]);
347 
349  m_PNext = state;
350 }
351 
352 inline void
354 {
355  SetSeed();
356 }
357 
358 inline void
360 {
361  // Seed the generator with a simple IntegerType
362  Initialize(oneSeed);
363 }
364 
365 inline void
367 {
368  // use time() and clock() to generate a unlikely-to-repeat seed.
369  SetSeed( hash( time(nullptr), clock() ) );
370 }
371 
372 
375 {
376  std::lock_guard<std::mutex> mutexHolder(m_InstanceLock);
377  volatile IntegerType seed = this->m_Seed;
378  return seed;
379 }
380 
384 {
385  if ( m_Left == 0 ) { reload(); }
386  --m_Left;
388 
389  IntegerType s1 = *m_PNext++;
390  s1 ^= ( s1 >> 11 );
391  s1 ^= ( s1 << 7 ) & 0x9d2c5680;
392  s1 ^= ( s1 << 15 ) & 0xefc60000;
393  return ( s1 ^ ( s1 >> 18 ) );
394 }
395 
396 inline double
398 {
399  return double( GetIntegerVariate() ) * ( 1.0 / 4294967295.0 );
400 }
401 
403 inline double
405  const double & n)
406 {
407  return GetVariateWithClosedRange() * n;
408 }
409 
411 inline double
413 {
414  return double( GetIntegerVariate() ) * ( 1.0 / 4294967296.0 );
415 }
416 
418 inline double
420  const double & n)
421 {
422  return GetVariateWithOpenUpperRange() * n;
423 }
424 
426 inline double
428 {
429  return ( double( GetIntegerVariate() ) + 0.5 ) * ( 1.0 / 4294967296.0 );
430 }
431 
433 inline double
435  const double & n)
436 {
437  return GetVariateWithOpenRange() * n;
438 }
439 
442  const IntegerType & n)
443 {
444  // Find which bits are used in n
445  IntegerType used = n;
446 
447  used |= used >> 1;
448  used |= used >> 2;
449  used |= used >> 4;
450  used |= used >> 8;
451  used |= used >> 16;
452 
453  // Draw numbers until one is found in [0,n]
454  IntegerType i;
455  do
456  {
457  i = GetIntegerVariate() & used; // toss unused bits to shorten search
458  }
459  while ( i > n );
460 
461  return i;
462 }
463 
466 inline double
468 {
469  IntegerType a = GetIntegerVariate() >> 5, b = GetIntegerVariate() >> 6;
470 
471  return ( a * 67108864.0 + b ) * ( 1.0 / 9007199254740992.0 ); // by Isaku
472  // Wada
473 }
474 
476 // TODO: Compare with vnl_sample_normal
477 inline double
479  const double & mean, const double & variance)
480 {
481  // Return a real number from a normal (Gaussian) distribution with given
482  // mean and variance by Box-Muller method
483  double r = std::sqrt(-2.0 * std::log( 1.0 - GetVariateWithOpenRange() ) * variance);
484  double phi = 2.0 * itk::Math::pi
487 
488  return mean + r *std::cos(phi);
489 }
490 
492 // TODO: Compare with vnl_sample_uniform
493 inline double
495  const double & a, const double & b)
496 {
497  double u = GetVariateWithOpenUpperRange();
498 
499  return ( ( 1.0 - u ) * a + u * b );
500 }
501 
502 inline double
504 {
505  return GetVariateWithClosedRange();
506 }
507 
508 inline double
510 {
511  return GetVariate();
512 }
513 
514 /* Change log from MTRand.h */
515 // Change log:
516 //
517 // v0.1 - First release on 15 May 2000
518 // - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
519 // - Translated from C to C++
520 // - Made completely ANSI compliant
521 // - Designed convenient interface for initialization, seeding, and
522 // obtaining numbers in default or user-defined ranges
523 // - Added automatic seeding from /dev/urandom or time() and clock()
524 // - Provided functions for saving and loading generator state
525 //
526 // v0.2 - Fixed bug which reloaded generator one step too late
527 //
528 // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
529 //
530 // v0.4 - Removed trailing newline in saved generator format to be consistent
531 // with output format of built-in types
532 //
533 // v0.5 - Improved portability by replacing static const int's with enum's and
534 // clarifying return values in seed(); suggested by Eric Heimburg
535 // - Removed MAXINT constant; use 0xffffffffUL instead
536 //
537 // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
538 // - Changed integer [0,n] generator to give better uniformity
539 //
540 // v0.7 - Fixed operator precedence ambiguity in reload()
541 // - Added access for real numbers in (0,1) and (0,n)
542 //
543 // v0.8 - Included time.h header to properly support time_t and clock_t
544 //
545 // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
546 // - Allowed for seeding with arrays of any length
547 // - Added access for real numbers in [0,1) with 53-bit resolution
548 // - Added access for real numbers from normal (Gaussian) distributions
549 // - Increased overall speed by optimizing twist()
550 // - Doubled speed of integer [0,n] generation
551 // - Fixed out-of-range number generation on 64-bit machines
552 // - Improved portability by substituting literal constants for long enum's
553 // - Changed license from GNU LGPL to BSD
554 } // end namespace Statistics
555 } // end namespace itk
556 
557 #endif
Light weight base class for most itk classes.
static constexpr double pi
Definition: itkMath.h:63
IntegerType mixBits(const IntegerType &u, const IntegerType &v) const
#define itkGetGlobalDeclarationMacro(Type, VarName)
Defines common interfaces for random variate generators.
::uint32_t uint32_t
Definition: itkIntTypes.h:33
IntegerType twist(const IntegerType &m, const IntegerType &s0, const IntegerType &s1) const
double GetNormalVariate(const double &mean=0.0, const double &variance=1.0)
Control indentation during Print() invocation.
Definition: itkIndent.h:49
static IntegerType hash(time_t t, clock_t c)