summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/rand
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/rand')
-rw-r--r--ml/dlib/dlib/rand/mersenne_twister.h210
-rw-r--r--ml/dlib/dlib/rand/rand_kernel_1.h354
-rw-r--r--ml/dlib/dlib/rand/rand_kernel_abstract.h218
3 files changed, 782 insertions, 0 deletions
diff --git a/ml/dlib/dlib/rand/mersenne_twister.h b/ml/dlib/dlib/rand/mersenne_twister.h
new file mode 100644
index 000000000..66ee87f54
--- /dev/null
+++ b/ml/dlib/dlib/rand/mersenne_twister.h
@@ -0,0 +1,210 @@
+/* boost random/mersenne_twister.hpp header file
+ *
+ * Copyright Jens Maurer 2000-2001
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org for most recent version including documentation.
+ *
+ * $Id: mersenne_twister.hpp,v 1.20 2005/07/21 22:04:31 jmaurer Exp $
+ *
+ * Revision history
+ * 2001-02-18 moved to individual header files
+*/
+
+#ifndef DLIB_BOOST_RANDOM_MERSENNE_TWISTER_HPP
+#define DLIB_BOOST_RANDOM_MERSENNE_TWISTER_HPP
+
+#include <iostream>
+#include <algorithm> // std::copy
+#include <stdexcept>
+#include "../uintn.h"
+#include "../serialize.h"
+
+namespace dlib
+{
+ namespace random_helpers
+ {
+
+ // ------------------------------------------------------------------------------------
+
+ // http://www.math.keio.ac.jp/matumoto/emt.html
+ template<
+ class UIntType,
+ int w,
+ int n,
+ int m,
+ int r,
+ UIntType a,
+ int u,
+ int s,
+ UIntType b,
+ int t,
+ UIntType c,
+ int l,
+ UIntType val
+ >
+ class mersenne_twister
+ {
+ public:
+ typedef UIntType result_type;
+ const static int word_size = w;
+ const static int state_size = n;
+ const static int shift_size = m;
+ const static int mask_bits = r;
+ const static UIntType parameter_a = a;
+ const static int output_u = u;
+ const static int output_s = s;
+ const static UIntType output_b = b;
+ const static int output_t = t;
+ const static UIntType output_c = c;
+ const static int output_l = l;
+
+ const static bool has_fixed_range = false;
+
+ mersenne_twister() { seed(); }
+
+ explicit mersenne_twister(UIntType value) { seed(value); }
+
+ void seed () { seed(UIntType(5489)); }
+
+ // compiler-generated copy ctor and assignment operator are fine
+
+ void seed(UIntType value)
+ {
+ // New seeding algorithm from
+ // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
+ // In the previous versions, MSBs of the seed affected only MSBs of the
+ // state x[].
+ const UIntType mask = ~0u;
+ x[0] = value & mask;
+ for (i = 1; i < n; i++) {
+ // See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106
+ x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
+ }
+ }
+
+ result_type min() const { return 0; }
+ result_type max() const
+ {
+ // avoid "left shift count >= with of type" warning
+ result_type res = 0;
+ for(int i = 0; i < w; ++i)
+ res |= (1u << i);
+ return res;
+ }
+
+ result_type operator()();
+
+ friend void serialize(
+ const mersenne_twister& item,
+ std::ostream& out
+ )
+ {
+ dlib::serialize(item.x, out);
+ dlib::serialize(item.i, out);
+ }
+
+ friend void deserialize(
+ mersenne_twister& item,
+ std::istream& in
+ )
+ {
+ dlib::deserialize(item.x, in);
+ dlib::deserialize(item.i, in);
+ }
+
+ private:
+
+ void twist(int block);
+
+ // state representation: next output is o(x(i))
+ // x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents
+ // x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)]
+ // The goal is to always have x(i-n) ... x(i-1) available for
+ // operator== and save/restore.
+
+ UIntType x[2*n];
+ int i;
+ };
+
+ // ------------------------------------------------------------------------------------
+
+ template<
+ class UIntType, int w, int n, int m, int r, UIntType a, int u,
+ int s, UIntType b, int t, UIntType c, int l, UIntType val
+ >
+ void mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::twist(
+ int block
+ )
+ {
+ const UIntType upper_mask = (~0u) << r;
+ const UIntType lower_mask = ~upper_mask;
+
+ if(block == 0) {
+ for(int j = n; j < 2*n; j++) {
+ UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask);
+ x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
+ }
+ } else if (block == 1) {
+ // split loop to avoid costly modulo operations
+ { // extra scope for MSVC brokenness w.r.t. for scope
+ for(int j = 0; j < n-m; j++) {
+ UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
+ x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0);
+ }
+ }
+
+ for(int j = n-m; j < n-1; j++) {
+ UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
+ x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
+ }
+ // last iteration
+ UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask);
+ x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0);
+ i = 0;
+ }
+ }
+
+ // ------------------------------------------------------------------------------------
+
+ template<
+ class UIntType, int w, int n, int m, int r, UIntType a, int u,
+ int s, UIntType b, int t, UIntType c, int l, UIntType val
+ >
+ inline typename mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::result_type
+ mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::operator()(
+ )
+ {
+ if(i == n)
+ twist(0);
+ else if(i >= 2*n)
+ twist(1);
+ // Step 4
+ UIntType z = x[i];
+ ++i;
+ z ^= (z >> u);
+ z ^= ((z << s) & b);
+ z ^= ((z << t) & c);
+ z ^= (z >> l);
+ return z;
+ }
+
+ // ------------------------------------------------------------------------------------
+
+ } // namespace random
+
+
+ typedef random_helpers::mersenne_twister<uint32,32,351,175,19,0xccab8ee7,11,
+ 7,0x31b6ab00,15,0xffe50000,17, 0xa37d3c92> mt11213b;
+
+ // validation by experiment from mt19937.c
+ typedef random_helpers::mersenne_twister<uint32,32,624,397,31,0x9908b0df,11,
+ 7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
+
+} // namespace dlib
+
+
+#endif // DLIB_BOOST_RANDOM_MERSENNE_TWISTER_HPP
+
diff --git a/ml/dlib/dlib/rand/rand_kernel_1.h b/ml/dlib/dlib/rand/rand_kernel_1.h
new file mode 100644
index 000000000..a1847be24
--- /dev/null
+++ b/ml/dlib/dlib/rand/rand_kernel_1.h
@@ -0,0 +1,354 @@
+// Copyright (C) 2007 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_RAND_KERNEl_1_
+#define DLIB_RAND_KERNEl_1_
+
+#include <string>
+#include "../algs.h"
+#include "rand_kernel_abstract.h"
+#include "mersenne_twister.h"
+#include "../is_kind.h"
+#include <iostream>
+#include "../serialize.h"
+#include "../string.h"
+
+namespace dlib
+{
+
+
+ class rand
+ {
+
+ /*!
+ INITIAL VALUE
+ - seed == ""
+
+ CONVENTION
+ - the random numbers come from the boost mersenne_twister code
+ - get_seed() == seed
+ !*/
+
+ public:
+
+ // These typedefs are here for backwards compatibility with older versions of dlib.
+ typedef rand kernel_1a;
+ typedef rand float_1a;
+
+ rand(
+ )
+ {
+ init();
+ }
+
+ rand (
+ time_t seed_value
+ )
+ {
+ init();
+ set_seed(cast_to_string(seed_value));
+ }
+
+ rand (
+ const std::string& seed_value
+ )
+ {
+ init();
+ set_seed(seed_value);
+ }
+
+ virtual ~rand(
+ )
+ {}
+
+ void clear(
+ )
+ {
+ mt.seed();
+ seed.clear();
+
+ has_gaussian = false;
+ next_gaussian = 0;
+
+ // prime the generator a bit
+ for (int i = 0; i < 10000; ++i)
+ mt();
+ }
+
+ const std::string& get_seed (
+ )
+ {
+ return seed;
+ }
+
+ void set_seed (
+ const std::string& value
+ )
+ {
+ seed = value;
+
+ // make sure we do the seeding so that using a seed of "" gives the same
+ // state as calling this->clear()
+ if (value.size() != 0)
+ {
+ uint32 s = 0;
+ for (std::string::size_type i = 0; i < seed.size(); ++i)
+ {
+ s = (s*37) + static_cast<uint32>(seed[i]);
+ }
+ mt.seed(s);
+ }
+ else
+ {
+ mt.seed();
+ }
+
+ // prime the generator a bit
+ for (int i = 0; i < 10000; ++i)
+ mt();
+
+
+ has_gaussian = false;
+ next_gaussian = 0;
+ }
+
+ unsigned char get_random_8bit_number (
+ )
+ {
+ return static_cast<unsigned char>(mt());
+ }
+
+ uint16 get_random_16bit_number (
+ )
+ {
+ return static_cast<uint16>(mt());
+ }
+
+ inline uint32 get_random_32bit_number (
+ )
+ {
+ return mt();
+ }
+
+ inline uint64 get_random_64bit_number (
+ )
+ {
+ const uint64 a = get_random_32bit_number();
+ const uint64 b = get_random_32bit_number();
+ return (a<<32)|b;
+ }
+
+ double get_double_in_range (
+ double begin,
+ double end
+ )
+ {
+ DLIB_ASSERT(begin <= end);
+ return begin + get_random_double()*(end-begin);
+ }
+
+ long long get_integer_in_range(
+ long long begin,
+ long long end
+ )
+ {
+ DLIB_ASSERT(begin <= end);
+ if (begin == end)
+ return begin;
+
+ auto r = get_random_64bit_number();
+ const auto limit = std::numeric_limits<decltype(r)>::max();
+ const auto range = end-begin;
+ // Use rejection sampling to remove the biased sampling you would get with
+ // the naive get_random_64bit_number()%range sampling.
+ while(r >= (limit/range)*range)
+ r = get_random_64bit_number();
+
+ return begin + static_cast<long long>(r%range);
+ }
+
+ long long get_integer(
+ long long end
+ )
+ {
+ DLIB_ASSERT(end >= 0);
+
+ return get_integer_in_range(0,end);
+ }
+
+ double get_random_double (
+ )
+ {
+ uint32 temp;
+
+ temp = rand::get_random_32bit_number();
+ temp &= 0xFFFFFF;
+
+ double val = static_cast<double>(temp);
+
+ val *= 0x1000000;
+
+ temp = rand::get_random_32bit_number();
+ temp &= 0xFFFFFF;
+
+ val += temp;
+
+ val /= max_val;
+
+ if (val < 1.0)
+ {
+ return val;
+ }
+ else
+ {
+ // return a value slightly less than 1.0
+ return 1.0 - std::numeric_limits<double>::epsilon();
+ }
+ }
+
+ float get_random_float (
+ )
+ {
+ uint32 temp;
+
+ temp = rand::get_random_32bit_number();
+ temp &= 0xFFFFFF;
+
+ const float scale = 1.0/0x1000000;
+
+ const float val = static_cast<float>(temp)*scale;
+ if (val < 1.0f)
+ {
+ return val;
+ }
+ else
+ {
+ // return a value slightly less than 1.0
+ return 1.0f - std::numeric_limits<float>::epsilon();
+ }
+ }
+
+ double get_random_gaussian (
+ )
+ {
+ if (has_gaussian)
+ {
+ has_gaussian = false;
+ return next_gaussian;
+ }
+
+ double x1, x2, w;
+
+ const double rndmax = std::numeric_limits<dlib::uint32>::max();
+
+ // Generate a pair of Gaussian random numbers using the Box-Muller transformation.
+ do
+ {
+ const double rnd1 = get_random_32bit_number()/rndmax;
+ const double rnd2 = get_random_32bit_number()/rndmax;
+
+ x1 = 2.0 * rnd1 - 1.0;
+ x2 = 2.0 * rnd2 - 1.0;
+ w = x1 * x1 + x2 * x2;
+ } while ( w >= 1.0 );
+
+ w = std::sqrt( (-2.0 * std::log( w ) ) / w );
+ next_gaussian = x2 * w;
+ has_gaussian = true;
+ return x1 * w;
+ }
+
+ void swap (
+ rand& item
+ )
+ {
+ exchange(mt,item.mt);
+ exchange(seed, item.seed);
+ exchange(has_gaussian, item.has_gaussian);
+ exchange(next_gaussian, item.next_gaussian);
+ }
+
+ friend void serialize(
+ const rand& item,
+ std::ostream& out
+ );
+
+ friend void deserialize(
+ rand& item,
+ std::istream& in
+ );
+
+ private:
+
+ void init()
+ {
+ // prime the generator a bit
+ for (int i = 0; i < 10000; ++i)
+ mt();
+
+ max_val = 0xFFFFFF;
+ max_val *= 0x1000000;
+ max_val += 0xFFFFFF;
+ max_val += 0.05;
+
+
+ has_gaussian = false;
+ next_gaussian = 0;
+ }
+
+ mt19937 mt;
+
+ std::string seed;
+
+
+ double max_val;
+ bool has_gaussian;
+ double next_gaussian;
+ };
+
+
+ inline void swap (
+ rand& a,
+ rand& b
+ ) { a.swap(b); }
+
+
+ template <>
+ struct is_rand<rand>
+ {
+ static const bool value = true;
+ };
+
+ inline void serialize(
+ const rand& item,
+ std::ostream& out
+ )
+ {
+ int version = 1;
+ serialize(version, out);
+
+ serialize(item.mt, out);
+ serialize(item.seed, out);
+ serialize(item.has_gaussian, out);
+ serialize(item.next_gaussian, out);
+ }
+
+ inline void deserialize(
+ rand& item,
+ std::istream& in
+ )
+ {
+ int version;
+ deserialize(version, in);
+ if (version != 1)
+ throw serialization_error("Error deserializing object of type rand: unexpected version.");
+
+ deserialize(item.mt, in);
+ deserialize(item.seed, in);
+ deserialize(item.has_gaussian, in);
+ deserialize(item.next_gaussian, in);
+ }
+}
+
+#endif // DLIB_RAND_KERNEl_1_
+
+
diff --git a/ml/dlib/dlib/rand/rand_kernel_abstract.h b/ml/dlib/dlib/rand/rand_kernel_abstract.h
new file mode 100644
index 000000000..67af27a9e
--- /dev/null
+++ b/ml/dlib/dlib/rand/rand_kernel_abstract.h
@@ -0,0 +1,218 @@
+// Copyright (C) 2003 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#undef DLIB_RAND_KERNEl_ABSTRACT_
+#ifdef DLIB_RAND_KERNEl_ABSTRACT_
+
+#include <string>
+#include "../uintn.h"
+
+namespace dlib
+{
+
+
+ class rand
+ {
+
+ /*!
+ INITIAL VALUE
+ get_seed() == ""
+
+
+ WHAT THIS OBJECT REPRESENTS
+ This object represents a pseudorandom number generator.
+ !*/
+
+ public:
+
+
+ rand(
+ );
+ /*!
+ ensures
+ - #*this is properly initialized
+ throws
+ - std::bad_alloc
+ !*/
+
+ rand (
+ time_t seed_value
+ );
+ /*!
+ ensures
+ - #*this is properly initialized
+ - #get_seed() == cast_to_string(seed_value)
+ - This version of the constructor is equivalent to using
+ the default constructor and then calling set_seed(cast_to_string(seed_value))
+ throws
+ - std::bad_alloc
+ !*/
+
+ rand (
+ const std::string& seed_value
+ );
+ /*!
+ ensures
+ - #*this is properly initialized
+ - #get_seed() == seed_value
+ - This version of the constructor is equivalent to using
+ the default constructor and then calling set_seed(seed_value)
+ throws
+ - std::bad_alloc
+ !*/
+
+ virtual ~rand(
+ );
+ /*!
+ ensures
+ - all memory associated with *this has been released
+ !*/
+
+ void clear(
+ );
+ /*!
+ ensures
+ - #*this has its initial value
+ throws
+ - std::bad_alloc
+ if this exception is thrown then *this is unusable
+ until clear() is called and succeeds
+ !*/
+
+ const std::string& get_seed (
+ );
+ /*!
+ ensures
+ - returns the string currently being used as the random seed.
+ !*/
+
+ void set_seed (
+ const std::string& value
+ );
+ /*!
+ ensures
+ - #get_seed() == value
+ !*/
+
+ unsigned char get_random_8bit_number (
+ );
+ /*!
+ ensures
+ - returns a pseudorandom number in the range 0 to 255
+ !*/
+
+ uint16 get_random_16bit_number (
+ );
+ /*!
+ ensures
+ - returns a pseudorandom number in the range 0 to 2^16-1
+ !*/
+
+ uint32 get_random_32bit_number (
+ );
+ /*!
+ ensures
+ - returns a pseudorandom number in the range 0 to 2^32-1
+ !*/
+
+ uint64 get_random_64bit_number (
+ );
+ /*!
+ ensures
+ - returns a pseudorandom number in the range 0 to 2^64-1
+ !*/
+
+ float get_random_float (
+ );
+ /*!
+ ensures
+ - returns a random float number N where: 0.0 <= N < 1.0.
+ !*/
+
+ double get_random_double (
+ );
+ /*!
+ ensures
+ - returns a random double number N where: 0.0 <= N < 1.0.
+ !*/
+
+ double get_double_in_range (
+ double begin,
+ double end
+ );
+ /*!
+ requires
+ - begin <= end
+ ensures
+ - if (begin < end) then
+ - returns a random double number N where: begin <= N < end.
+ - else
+ - returns begin
+ !*/
+
+ long long get_integer_in_range(
+ long long begin,
+ long long end
+ );
+ /*!
+ requires
+ - begin <= end
+ ensures
+ - returns a random integer selected from the range: begin <= N < end
+ The integer is selected uniformly at random.
+ !*/
+
+ long long get_integer(
+ long long end
+ );
+ /*!
+ requires
+ - 0 <= end
+ ensures
+ - returns get_integer_in_range(0,end)
+ !*/
+
+ double get_random_gaussian (
+ );
+ /*!
+ ensures
+ - returns a random number sampled from a Gaussian distribution
+ with mean 0 and standard deviation 1.
+ !*/
+
+ void swap (
+ rand& item
+ );
+ /*!
+ ensures
+ - swaps *this and item
+ !*/
+
+ };
+
+ inline void swap (
+ rand& a,
+ rand& b
+ ) { a.swap(b); }
+ /*!
+ provides a global swap function
+ !*/
+
+ void serialize (
+ const rand& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support
+ !*/
+
+ void deserialize (
+ rand& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support
+ !*/
+}
+
+#endif // DLIB_RAND_KERNEl_ABSTRACT_
+