text: // This is core/vnl/vnl_random.h
  #ifndef vnl_random_h
  #define vnl_random_h
  #ifdef VCL_NEEDS_PRAGMA_INTERFACE
  #pragma interface
  #endif
  #include <vcl_compiler.h>
  #include "vnl/vnl_export.h"
  
  //:
  // \file
  // \author Aaron Kotcheff (Manchester)
  // \brief A superior random number generator
  
  VXL_CONSTEXPR_VAR unsigned int vnl_random_array_size = 37;
  
  //: A superior random number generator.
  // Implements a new random number generator that
  // recently appeared in the literature. It generates 32 bit
  // numbers with a higher degree of randomness than previous
  // generators and has a cycle of 10^354 i.e. so huge that in
  // practice it never cycles.
  // For the mathematics behind it see:
  // "A New Class of Random Number Generators" G. Marsaglia and A. Zaman,
  // Annals of Applied Probability 1991, Vol. 1, No. 3, 462.
  class VNL_EXPORT vnl_random
  {
      enum {linear_congruential_multiplier = 1664525, mz_previous1 = 24};
      unsigned long linear_congruential_previous;
      unsigned long mz_seed_array[vnl_random_array_size];
      unsigned long mz_array[vnl_random_array_size];
      unsigned int mz_array_position;
      int mz_borrow;
      unsigned long linear_congruential_lrand32();
  
      double mz_previous_normal;
      int mz_previous_normal_flag;
  
   public:
      //: Default constructor.
      // Initializes the random number generator non-deterministically.
      // i.e. it will generate a different series of random numbers each
      // time the program is run.
      vnl_random();
  
      //: Destructor
      ~vnl_random();
  
      //: Construct with seed.
      //  Initializes the random number generator deterministically
      //  using a single ulong as the 'seed'. A linear congruential
      //  generator is used to generate the 37 ulongs needed
      //  as the real seed. The same seed will produce the
      //  same series of random numbers.
      //
      //  9667566  is a good seed.
      vnl_random(unsigned long seed);
  
      //: Construct with seed.
      //  Initializes the random number generator deterministically
      //  using 37 ulongs as the 'seed'. The same seed will
      //  produce the same series of random numbers.
      vnl_random(unsigned long seed[vnl_random_array_size]);
  
      //: Copy constructor.
      //  Initializes/sets the random number generator to exactly
      //  the same state as the argument, i.e. both will generate exactly
      //  the same series of random numbers from then on.
      vnl_random(const vnl_random&);
  
      //: Copy operator.
      //  Initializes/sets the random number generator to exactly
      //  the same state as the argument, i.e. both will generate exactly
      //  the same series of random numbers from then on.
      vnl_random& operator=(const vnl_random&);
  
      //: Starts a new non-deterministic sequence from an already declared generator.
      void reseed();
  
      //: Starts a new deterministic sequence from an already declared generator using the provided seed.
      void reseed(unsigned long);
  
      //: Starts a new deterministic sequence from an already declared generator using the provided seed.
      void reseed(unsigned long[vnl_random_array_size]);
  
      //: This restarts the sequence of random numbers.
      //  Restarts so that it repeats
      //  from the point at which you declared the generator, last
      //  initialized it, or last called a 'reseed'.
      void restart();
  
      //: Generates a random unsigned 32-bit number.
      unsigned long lrand32();
  
      //: Generates a random unsigned long in [a,b]
      int lrand32(int a, int b);
  
      //: Generates a random unsigned long in [0,b]
      int lrand32(int b) {return lrand32(0, b);}
  
      //: Generates a random unsigned long in [a,b]
      int lrand32(int a, int b, int&);
  
      //:  Generates a random double in the range a <= x <= b with 32 bit randomness.
      //   drand32(1,0) is random down to about the 10th decimal place.
      double drand32(double a, double b);
  
      //: Generates a random unsigned integer in [0,n)
      // This function allows the random number generator to be used as
      // a functor, e.g. with std::random_shuffle()
      unsigned long operator()(unsigned n) { return lrand32(0, n-1); }
  
      //:  Generates a random double in the range 0 <= x <= b with 32 bit randomness.
      //   drand32(1.0) is random down to about the 10th decimal place.
      double drand32(double b) {return drand32(0.0, b);}
  
      //:  Generates a random double in the range 0 <= x <= 1 with 32 bit randomness.
      //   drand32() is random down to about the 10th decimal place.
      double drand32() {return drand32(0.0, 1.0);}
  
      //: Generates a random double in the range a <= x <= b with 64 bit randomness.
      //  Completely random down to the accuracy of an IEEE double.
      double drand64(double a, double b);
  
      //: Generates a random double in the range 0 <= x <= b with 64 bit randomness.
      //  Completely random down to the accuracy of an IEEE double.
      double drand64(double b) {return drand64(0.0, b);}
  
      //: Generates a random double in the range 0 <= x <= 1 with 64 bit randomness.
      //  Completely random down to the accuracy of an IEEE double.
      double drand64() {return drand64(0.0, 1.0);}
  
      //: Random value from a unit normal distribution about zero.
      // Uses a drand32() as its underlying generator.
      // Because the function uses a probability transform, the randomness (and
      // quantisation) is non-linearly dependent on the value. The further the
      // sample is from zero, the lower the number of bits on which it is random.
      double normal();
  
      //: Random value from a unit normal distribution about zero.
      // Uses a drand64() as its underlying generator.
      // Because the function uses a probability transform, the randomness (and
      // quantisation) is non-linearly dependent on the value. The further the
      // sample is from zero, the lower the number of bits on which it is random.
      double normal64();
  };
  
  #endif // vnl_random_h
  