]> git.sesse.net Git - stockfish/blob - src/rkiss.h
Let rkiss.h to follow SF coding style
[stockfish] / src / rkiss.h
1 /** *********************************************************************** **
2  ** A small "keep it simple and stupid" RNG with some fancy merits:
3  **
4  ** Quite platform independent
5  ** Passes ALL dieharder tests! Here *nix sys-rand() e.g. fails miserably:-)
6  ** ~12 times faster than my *nix sys-rand()
7  ** ~4 times faster than SSE2-version of Mersenne twister
8  ** Average cycle length: ~2^126
9  ** 64 bit seed
10  ** Return doubles with a full 53 bit mantissa
11  ** Thread save
12  **
13  ** (c) Heinz van Saanen
14
15   This file is free software: you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 3 of the License, or
18   (at your option) any later version.
19
20   This file is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
28  ** *********************************************************************** **/
29
30 #if !defined(RKISS_H_INCLUDED)
31 #define RKISS_H_INCLUDED
32
33
34 ////
35 //// Includes
36 ////
37
38 #include <cstdlib>
39 #include <ctime>
40
41 #include "types.h"
42
43
44 ////
45 //// Types
46 ////
47
48 class RKISS {
49
50         // Keep variables always together
51         struct S { uint64_t a, b, c, d; } s;
52
53         // Return 64 bit unsigned integer in between [0,2^64-1]
54         uint64_t rand64() {
55
56                 const uint64_t
57           e = s.a - ((s.b <<  7) | (s.b >> 57));
58                 s.a = s.b ^ ((s.c << 13) | (s.c >> 51));
59                 s.b = s.c + ((s.d << 37) | (s.d >> 27));
60                 s.c = s.d + e;
61                 return s.d = e + s.a;
62         }
63
64         // Init seed and scramble a few rounds
65         void raninit(uint64_t seed) {
66
67                 s.a = 0xf1ea5eed;
68         s.b = s.c = s.d = seed;
69                 for (uint64_t i = 0; i < 8; i++)
70             rand64();
71         }
72
73 public:
74         // Instance seed random or implicite
75         RKISS() { ::srand(uint32_t(time(NULL))); raninit(uint64_t(::rand())); }
76
77         // Return random number of type T (must be castable from uint64_t)
78     template<typename T>
79         T rand() { return T(rand64()); }
80 };
81
82 #endif // !defined(RKISS_H_INCLUDED)