mirror of
https://gitcode.com/gh_mirrors/ope/OpenFace.git
synced 2026-05-14 19:27:56 +00:00
211 lines
6.8 KiB
C++
211 lines
6.8 KiB
C++
/* 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
|
|
|