Coverage Report

Created: 2023-12-08 07:00

/src/mcl/include/cybozu/xorshift.hpp
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
/**
3
  @file
4
  @brief XorShift
5
6
  @author MITSUNARI Shigeo(@herumi)
7
  @author MITSUNARI Shigeo
8
*/
9
#include <cybozu/inttype.hpp>
10
#include <assert.h>
11
12
namespace cybozu {
13
14
namespace xorshift_local {
15
16
/*
17
  U is uint32_t or uint64_t
18
*/
19
template<class U, class Gen>
20
void read_local(void *p, size_t n, Gen& gen, U (Gen::*f)())
21
0
{
22
0
  uint8_t *dst = static_cast<uint8_t*>(p);
23
0
  const size_t uSize = sizeof(U);
24
0
  assert(uSize == 4 || uSize == 8);
25
0
  union ua {
26
0
    U u;
27
0
    uint8_t a[uSize];
28
0
  };
29
30
0
  while (n >= uSize) {
31
0
    ua ua;
32
0
    ua.u = (gen.*f)();
33
0
    for (size_t i = 0; i < uSize; i++) {
34
0
      dst[i] = ua.a[i];
35
0
    }
36
0
    dst += uSize;
37
0
    n -= uSize;
38
0
  }
39
0
  assert(n < uSize);
40
0
  if (n > 0) {
41
0
    ua ua;
42
0
    ua.u = (gen.*f)();
43
0
    for (size_t i = 0; i < n; i++) {
44
0
      dst[i] = ua.a[i];
45
0
    }
46
0
  }
47
0
}
48
49
} // xorshift_local
50
51
class XorShift {
52
  uint32_t x_, y_, z_, w_;
53
public:
54
  explicit XorShift(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)
55
0
  {
56
0
    init(x, y, z, w);
57
0
  }
58
  void init(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)
59
0
  {
60
0
    x_ = x ? x : 123456789;
61
0
    y_ = y ? y : 362436069;
62
0
    z_ = z ? z : 521288629;
63
0
    w_ = w ? w : 88675123;
64
0
  }
65
  uint32_t get32()
66
0
  {
67
0
    unsigned int t = x_ ^ (x_ << 11);
68
0
    x_ = y_; y_ = z_; z_ = w_;
69
0
    return w_ = (w_ ^ (w_ >> 19)) ^ (t ^ (t >> 8));
70
0
  }
71
0
  uint32_t operator()() { return get32(); }
72
  uint64_t get64()
73
0
  {
74
0
    uint32_t a = get32();
75
0
    uint32_t b = get32();
76
0
    return (uint64_t(a) << 32) | b;
77
0
  }
78
  template<class T>
79
  void read(bool *pb, T *p, size_t n)
80
0
  {
81
0
    xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift::get32);
82
0
    *pb = true;
83
0
  }
84
  template<class T>
85
  size_t read(T *p, size_t n)
86
  {
87
    bool b;
88
    read(&b, p, n);
89
    (void)b;
90
    return n;
91
  }
92
};
93
94
// see http://xorshift.di.unimi.it/xorshift128plus.c
95
class XorShift128Plus {
96
  uint64_t s_[2];
97
  static const uint64_t seed0 = 123456789;
98
  static const uint64_t seed1 = 987654321;
99
public:
100
  explicit XorShift128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)
101
0
  {
102
0
    init(s0, s1);
103
0
  }
104
  void init(uint64_t s0 = seed0, uint64_t s1 = seed1)
105
0
  {
106
0
    s_[0] = s0;
107
0
    s_[1] = s1;
108
0
  }
109
  uint32_t get32()
110
0
  {
111
0
    return static_cast<uint32_t>(get64());
112
0
  }
113
0
  uint64_t operator()() { return get64(); }
114
  uint64_t get64()
115
0
  {
116
0
    uint64_t s1 = s_[0];
117
0
    const uint64_t s0 = s_[1];
118
0
    s_[0] = s0;
119
0
    s1 ^= s1 << 23;
120
0
    s_[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
121
0
    return s_[1] + s0;
122
0
  }
123
  template<class T>
124
  void read(bool *pb, T *p, size_t n)
125
  {
126
    xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift128Plus::get64);
127
    *pb = true;
128
  }
129
  template<class T>
130
  size_t read(T *p, size_t n)
131
  {
132
    bool b;
133
    read(&b, p, n);
134
    (void)b;
135
    return n;
136
  }
137
};
138
139
// see http://xoroshiro.di.unimi.it/xoroshiro128plus.c
140
class Xoroshiro128Plus {
141
  uint64_t s_[2];
142
  static const uint64_t seed0 = 123456789;
143
  static const uint64_t seed1 = 987654321;
144
  uint64_t rotl(uint64_t x, unsigned int k) const
145
0
  {
146
0
    return (x << k) | (x >> (64 - k));
147
0
  }
148
public:
149
  explicit Xoroshiro128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)
150
0
  {
151
0
    init(s0, s1);
152
0
  }
153
  void init(uint64_t s0 = seed0, uint64_t s1 = seed1)
154
0
  {
155
0
    s_[0] = s0;
156
0
    s_[1] = s1;
157
0
  }
158
  uint32_t get32()
159
0
  {
160
0
    return static_cast<uint32_t>(get64());
161
0
  }
162
0
  uint64_t operator()() { return get64(); }
163
  uint64_t get64()
164
0
  {
165
0
    uint64_t s0 = s_[0];
166
0
    uint64_t s1 = s_[1];
167
0
    uint64_t result = s0 + s1;
168
0
    s1 ^= s0;
169
0
    s_[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
170
0
    s_[1] = rotl(s1, 36);
171
0
    return result;
172
0
  }
173
  template<class T>
174
  void read(bool *pb, T *p, size_t n)
175
  {
176
    xorshift_local::read_local(p, n * sizeof(T), *this, &Xoroshiro128Plus::get64);
177
    *pb = true;
178
  }
179
  template<class T>
180
  size_t read(T *p, size_t n)
181
  {
182
    bool b;
183
    read(&b, p, n);
184
    (void)b;
185
    return n;
186
  }
187
};
188
189
} // cybozu