summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/rand/mersenne_twister.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/rand/mersenne_twister.h')
-rw-r--r--ml/dlib/dlib/rand/mersenne_twister.h210
1 files changed, 210 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
+