Use Heinz's RKiss instead of marsenne
[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 #ifndef _RKISS_H_
31 #define _RKISS_H_
32
33 /** Includes **/
34 #include <cstdlib>    // srand(), rand()
35 #include <ctime>      // time()
36 #include "types.h"    // (u)int8_t .. (u)int64_t
37
38
39 /** Random class **/
40 class RKISS {
41
42 private:
43         // Keep variables always together
44         struct S { uint64_t a; uint64_t b; uint64_t c; uint64_t d; } s;
45
46         // Init seed and scramble a few rounds
47         void raninit ( uint64_t seed ) {
48                 s.a = 0xf1ea5eed; s.b = s.c = s.d = seed;
49                 for ( uint64_t i=0; i<8; i++ ) rand64();
50         }
51
52 public:
53         // Instance seed random or implicite
54         RKISS() { ::srand ( (uint32_t)time(NULL) ); raninit ( (uint64_t)::rand() ); }
55         // RKISS( uint64_t s ) { raninit ( s ); }
56
57         // (Re)init seed
58         // void init ( uint64_t seed ) { raninit ( seed ); }
59
60         // Return 32 bit unsigned integer in between [0,2^32-1]
61         uint32_t rand32 () { return (uint32_t) rand64 (); }
62
63         // Return 64 bit unsigned integer in between [0,2^64-1]
64         uint64_t rand64 () {
65                 const uint64_t e = s.a - ((s.b<<7) | (s.b>>57));
66                 s.a = s.b ^ ((s.c<<13) | (s.c>>51));
67                 s.b = s.c + ((s.d<<37) | (s.d>>27));
68                 s.c = s.d + e;
69                 return s.d = e + s.a;
70         }
71
72         // Return double in between [0,1). Keep full 53 bit mantissa
73         // double frand () { return (int64_t)(rand64()>>11) * (1.0/(67108864.0*134217728.0)); }
74 };
75
76 // _RKISS_H_
77 #endif