]> git.localhorst.tv Git - blank.git/blob - src/rand/GaloisLFSR.hpp
avoid library rand()
[blank.git] / src / rand / GaloisLFSR.hpp
1 #ifndef BLANK_RAND_GALOISLFSR_HPP_
2 #define BLANK_RAND_GALOISLFSR_HPP_
3
4 #include <cstdint>
5 #include <limits>
6
7
8 namespace blank {
9
10 class GaloisLFSR {
11
12 public:
13         // seed should be non-zero
14         explicit GaloisLFSR(std::uint64_t seed) noexcept
15         : state(seed) { }
16
17         // get the next bit
18         bool operator ()() noexcept {
19                 bool result = state & 1;
20                 state >>= 1;
21                 if (result) {
22                         state |= 0x8000000000000000;
23                         state ^= mask;
24                 } else {
25                         state &= 0x7FFFFFFFFFFFFFFF;
26                 }
27                 return result;
28         }
29
30         template<class T>
31         T operator ()(T &out) noexcept {
32                 constexpr int num_bits =
33                         std::numeric_limits<T>::digits +
34                         std::numeric_limits<T>::is_signed;
35                 for (int i = 0; i < num_bits; ++i) {
36                         operator ()();
37                 }
38                 return out = static_cast<T>(state);
39         }
40
41         template<class T>
42         T Next() noexcept {
43                 T next;
44                 return (*this)(next);
45         }
46
47 private:
48         std::uint64_t state;
49         // bits 64, 63, 61, and 60 set to 1 (counting from 1 lo to hi)
50         static constexpr std::uint64_t mask = 0xD800000000000000;
51
52 };
53
54 }
55
56 #endif