numo-random 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -2
- data/README.md +26 -0
- data/ext/numo/random/ext.cpp +4 -1
- data/ext/numo/random/ext.hpp +287 -77
- data/lib/numo/random/generator.rb +87 -4
- data/lib/numo/random/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9c0d26c2b1751451a84c8b53c6e38b9257a82ff7d2c3479bd94d7311cfb1628
|
4
|
+
data.tar.gz: ae9262ff84d81abb58af7d4856e0936160c33f3a824818515878ae97ce3c9ea0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f153a0090d65b3ee39d5f8cde36a3669e0d12b6e4f84c56045156c42c2f5fe7dfe3de7b6d649c994bafec730ff8bbcaff09e9befa6aba04e9b5fd0d77dae8d91
|
7
|
+
data.tar.gz: 27af398428b05b955c690f36d948112329484f47146631b2a4f58ef60551a84039144c387e96ad49ee0d13815225930100659823ece1040fb59898e73c13dc0d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
|
-
## [
|
2
|
-
-
|
1
|
+
## [0.5.0]
|
2
|
+
- Support 32-bit PCG and Mersenne Twister.
|
3
|
+
|
4
|
+
```ruby
|
5
|
+
require 'numo/random'
|
6
|
+
|
7
|
+
# specify the pseudo random number generation algorithm by setting the algorithm argument of constructor.
|
8
|
+
rng = Numo::Random::Generator.new(algorithm: 'pcg32')
|
9
|
+
rng = Numo::Random::Generator.new(algorithm: 'pcg64') # default
|
10
|
+
rng = Numo::Random::Generator.new(algorithm: 'mt32')
|
11
|
+
rng = Numo::Random::Generator.new(algorithm: 'mt64')
|
12
|
+
```
|
13
|
+
|
14
|
+
## [0.4.0]
|
15
|
+
- Add method for random number generation with bernoulli distribution: bernoulli, binomial, negative_binomial, and geometric.
|
3
16
|
|
4
17
|
## [0.3.0]
|
5
18
|
- Change native extension filename.
|
data/README.md
CHANGED
@@ -50,6 +50,32 @@ end
|
|
50
50
|
![normal2d.png](https://user-images.githubusercontent.com/5562409/197376738-ee8d2b12-1902-4a12-bcf3-757461f2f2db.png)
|
51
51
|
|
52
52
|
|
53
|
+
An example of generating random numbers according to the Poisson distribution:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require 'numo/narray'
|
57
|
+
require 'numo/gnuplot'
|
58
|
+
|
59
|
+
require 'numo/random'
|
60
|
+
|
61
|
+
# Creating random number generator.
|
62
|
+
rng = Numo::Random::Generator.new(seed: 9)
|
63
|
+
|
64
|
+
# Generating random numbers with Poisson distribution.
|
65
|
+
x = rng.poisson(shape: 10000, mean: 12)
|
66
|
+
|
67
|
+
# Plotting the generated result.
|
68
|
+
h = x.bincount
|
69
|
+
|
70
|
+
Numo.gnuplot do
|
71
|
+
set(terminal: 'png')
|
72
|
+
set(output: 'poisson2d.png')
|
73
|
+
plot(h, with: 'boxes')
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
![poisson2d.png](https://user-images.githubusercontent.com/5562409/201478863-61d31eb8-7c0b-4406-b255-fff29187a16a.png)
|
78
|
+
|
53
79
|
## Contributing
|
54
80
|
|
55
81
|
Bug reports and pull requests are welcome on GitHub at https://github.com/yoshoku/numo-random.
|
data/ext/numo/random/ext.cpp
CHANGED
@@ -22,5 +22,8 @@ extern "C" void Init_ext(void) {
|
|
22
22
|
rb_require("numo/narray");
|
23
23
|
|
24
24
|
VALUE rb_mNumoRandom = rb_define_module_under(mNumo, "Random");
|
25
|
-
|
25
|
+
RbNumoRandomPCG32::define_class(rb_mNumoRandom, "PCG32");
|
26
|
+
RbNumoRandomPCG64::define_class(rb_mNumoRandom, "PCG64");
|
27
|
+
RbNumoRandomMT32::define_class(rb_mNumoRandom, "MT32");
|
28
|
+
RbNumoRandomMT64::define_class(rb_mNumoRandom, "MT64");
|
26
29
|
}
|
data/ext/numo/random/ext.hpp
CHANGED
@@ -28,71 +28,74 @@
|
|
28
28
|
|
29
29
|
#include <pcg_random.hpp>
|
30
30
|
|
31
|
-
class
|
31
|
+
template<class Rng, class Impl> class RbNumoRandom {
|
32
32
|
public:
|
33
|
-
static
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
// static const rb_data_type_t rng_type;
|
34
|
+
|
35
|
+
static VALUE numo_random_alloc(VALUE self) {
|
36
|
+
Rng* ptr = (Rng*)ruby_xmalloc(sizeof(Rng));
|
37
|
+
new (ptr) Rng();
|
38
|
+
return TypedData_Wrap_Struct(self, &Impl::rng_type, ptr);
|
37
39
|
}
|
38
40
|
|
39
|
-
static void
|
40
|
-
((
|
41
|
+
static void numo_random_free(void* ptr) {
|
42
|
+
((Rng*)ptr)->~Rng();
|
41
43
|
ruby_xfree(ptr);
|
42
44
|
}
|
43
45
|
|
44
|
-
static size_t
|
45
|
-
return sizeof(*((
|
46
|
+
static size_t numo_random_size(const void* ptr) {
|
47
|
+
return sizeof(*((Rng*)ptr));
|
46
48
|
}
|
47
49
|
|
48
|
-
static
|
49
|
-
|
50
|
-
TypedData_Get_Struct(self,
|
50
|
+
static Rng* get_rng(VALUE self) {
|
51
|
+
Rng* ptr;
|
52
|
+
TypedData_Get_Struct(self, Rng, &Impl::rng_type, ptr);
|
51
53
|
return ptr;
|
52
54
|
}
|
53
55
|
|
54
|
-
static VALUE define_class(VALUE rb_mNumoRandom) {
|
55
|
-
VALUE
|
56
|
-
rb_define_alloc_func(
|
57
|
-
rb_define_method(
|
58
|
-
rb_define_method(
|
59
|
-
rb_define_method(
|
60
|
-
rb_define_method(
|
61
|
-
rb_define_method(
|
62
|
-
rb_define_method(
|
63
|
-
rb_define_method(
|
64
|
-
rb_define_method(
|
65
|
-
rb_define_method(
|
66
|
-
rb_define_method(
|
67
|
-
rb_define_method(
|
68
|
-
rb_define_method(
|
69
|
-
rb_define_method(
|
70
|
-
rb_define_method(
|
71
|
-
rb_define_method(
|
72
|
-
rb_define_method(
|
73
|
-
rb_define_method(
|
74
|
-
|
56
|
+
static VALUE define_class(VALUE rb_mNumoRandom, const char* class_name) {
|
57
|
+
VALUE rb_cRng = rb_define_class_under(rb_mNumoRandom, class_name, rb_cObject);
|
58
|
+
rb_define_alloc_func(rb_cRng, numo_random_alloc);
|
59
|
+
rb_define_method(rb_cRng, "initialize", RUBY_METHOD_FUNC(_numo_random_init), -1);
|
60
|
+
rb_define_method(rb_cRng, "seed=", RUBY_METHOD_FUNC(_numo_random_set_seed), 1);
|
61
|
+
rb_define_method(rb_cRng, "seed", RUBY_METHOD_FUNC(_numo_random_get_seed), 0);
|
62
|
+
rb_define_method(rb_cRng, "random", RUBY_METHOD_FUNC(_numo_random_random), 0);
|
63
|
+
rb_define_method(rb_cRng, "binomial", RUBY_METHOD_FUNC(_numo_random_binomial), -1);
|
64
|
+
rb_define_method(rb_cRng, "negative_binomial", RUBY_METHOD_FUNC(_numo_random_negative_binomial), -1);
|
65
|
+
rb_define_method(rb_cRng, "geometric", RUBY_METHOD_FUNC(_numo_random_geometric), -1);
|
66
|
+
rb_define_method(rb_cRng, "exponential", RUBY_METHOD_FUNC(_numo_random_exponential), -1);
|
67
|
+
rb_define_method(rb_cRng, "gamma", RUBY_METHOD_FUNC(_numo_random_gamma), -1);
|
68
|
+
rb_define_method(rb_cRng, "gumbel", RUBY_METHOD_FUNC(_numo_random_gumbel), -1);
|
69
|
+
rb_define_method(rb_cRng, "poisson", RUBY_METHOD_FUNC(_numo_random_poisson), -1);
|
70
|
+
rb_define_method(rb_cRng, "weibull", RUBY_METHOD_FUNC(_numo_random_weibull), -1);
|
71
|
+
rb_define_method(rb_cRng, "discrete", RUBY_METHOD_FUNC(_numo_random_discrete), -1);
|
72
|
+
rb_define_method(rb_cRng, "uniform", RUBY_METHOD_FUNC(_numo_random_uniform), -1);
|
73
|
+
rb_define_method(rb_cRng, "cauchy", RUBY_METHOD_FUNC(_numo_random_cauchy), -1);
|
74
|
+
rb_define_method(rb_cRng, "chisquare", RUBY_METHOD_FUNC(_numo_random_chisquare), -1);
|
75
|
+
rb_define_method(rb_cRng, "f", RUBY_METHOD_FUNC(_numo_random_f), -1);
|
76
|
+
rb_define_method(rb_cRng, "normal", RUBY_METHOD_FUNC(_numo_random_normal), -1);
|
77
|
+
rb_define_method(rb_cRng, "lognormal", RUBY_METHOD_FUNC(_numo_random_lognormal), -1);
|
78
|
+
rb_define_method(rb_cRng, "standard_t", RUBY_METHOD_FUNC(_numo_random_standard_t), -1);
|
79
|
+
return rb_cRng;
|
75
80
|
}
|
76
81
|
|
77
82
|
private:
|
78
|
-
static const rb_data_type_t pcg64_type;
|
79
|
-
|
80
83
|
// #initialize
|
81
84
|
|
82
|
-
static VALUE
|
85
|
+
static VALUE _numo_random_init(int argc, VALUE* argv, VALUE self) {
|
83
86
|
VALUE kw_args = Qnil;
|
84
87
|
ID kw_table[1] = { rb_intern("seed") };
|
85
88
|
VALUE kw_values[1] = { Qundef };
|
86
89
|
rb_scan_args(argc, argv, ":", &kw_args);
|
87
90
|
rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values);
|
88
|
-
|
91
|
+
Rng* ptr = get_rng(self);
|
89
92
|
if (kw_values[0] == Qundef || NIL_P(kw_values[0])) {
|
90
93
|
std::random_device rd;
|
91
94
|
const unsigned int seed = rd();
|
92
|
-
new (ptr)
|
95
|
+
new (ptr) Rng(seed);
|
93
96
|
rb_iv_set(self, "seed", UINT2NUM(seed));
|
94
97
|
} else {
|
95
|
-
new (ptr)
|
98
|
+
new (ptr) Rng(NUM2LONG(kw_values[0]));
|
96
99
|
rb_iv_set(self, "seed", kw_values[0]);
|
97
100
|
}
|
98
101
|
return Qnil;
|
@@ -100,23 +103,23 @@ private:
|
|
100
103
|
|
101
104
|
// #seed=
|
102
105
|
|
103
|
-
static VALUE
|
104
|
-
|
106
|
+
static VALUE _numo_random_set_seed(VALUE self, VALUE seed) {
|
107
|
+
get_rng(self)->seed(NUM2LONG(seed));
|
105
108
|
rb_iv_set(self, "seed", seed);
|
106
109
|
return Qnil;
|
107
110
|
}
|
108
111
|
|
109
112
|
// #seed
|
110
113
|
|
111
|
-
static VALUE
|
114
|
+
static VALUE _numo_random_get_seed(VALUE self) {
|
112
115
|
return rb_iv_get(self, "seed");
|
113
116
|
}
|
114
117
|
|
115
118
|
// #random
|
116
119
|
|
117
|
-
static VALUE
|
120
|
+
static VALUE _numo_random_random(VALUE self) {
|
118
121
|
std::uniform_real_distribution<double> uniform_dist(0, 1);
|
119
|
-
|
122
|
+
Rng* ptr = get_rng(self);
|
120
123
|
const double x = uniform_dist(*ptr);
|
121
124
|
return DBL2NUM(x);
|
122
125
|
}
|
@@ -125,7 +128,7 @@ private:
|
|
125
128
|
|
126
129
|
template<class D> struct rand_opt_t {
|
127
130
|
D dist;
|
128
|
-
|
131
|
+
Rng* rnd;
|
129
132
|
};
|
130
133
|
|
131
134
|
template<class D, typename T> static void _iter_rand(na_loop_t* const lp) {
|
@@ -149,10 +152,161 @@ private:
|
|
149
152
|
}
|
150
153
|
}
|
151
154
|
|
155
|
+
// #binomial
|
156
|
+
|
157
|
+
template<typename T> static void _rand_binomial(VALUE& self, VALUE& x, const long n, const double& p) {
|
158
|
+
Rng* ptr = get_rng(self);
|
159
|
+
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
160
|
+
std::binomial_distribution<T> binomial_dist(n, p);
|
161
|
+
ndfunc_t ndf = { _iter_rand<std::binomial_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
162
|
+
rand_opt_t<std::binomial_distribution<T>> opt = { binomial_dist, ptr };
|
163
|
+
na_ndloop3(&ndf, &opt, 1, x);
|
164
|
+
}
|
165
|
+
|
166
|
+
static VALUE _numo_random_binomial(int argc, VALUE* argv, VALUE self) {
|
167
|
+
VALUE x = Qnil;
|
168
|
+
VALUE kw_args = Qnil;
|
169
|
+
ID kw_table[2] = { rb_intern("n"), rb_intern("p") };
|
170
|
+
VALUE kw_values[2] = { Qundef, Qundef };
|
171
|
+
rb_scan_args(argc, argv, "1:", &x, &kw_args);
|
172
|
+
rb_get_kwargs(kw_args, kw_table, 2, 0, kw_values);
|
173
|
+
|
174
|
+
const VALUE klass = rb_obj_class(x);
|
175
|
+
if (klass != numo_cInt8 && klass != numo_cInt16 && klass != numo_cInt32 && klass != numo_cInt64
|
176
|
+
&& klass != numo_cUInt8 && klass != numo_cUInt16 && klass != numo_cUInt32 && klass != numo_cUInt64)
|
177
|
+
rb_raise(rb_eTypeError, "invalid NArray class, it must be integer typed array");
|
178
|
+
|
179
|
+
const long n = NUM2LONG(kw_values[0]);
|
180
|
+
const double p = NUM2DBL(kw_values[1]);
|
181
|
+
if (n < 0) rb_raise(rb_eArgError, "n must be a non-negative value");
|
182
|
+
if (p < 0.0 || p > 1.0) rb_raise(rb_eArgError, "p must be >= 0 and <= 1");
|
183
|
+
|
184
|
+
if (klass == numo_cInt8) {
|
185
|
+
_rand_binomial<int8_t>(self, x, n, p);
|
186
|
+
} else if (klass == numo_cInt16) {
|
187
|
+
_rand_binomial<int16_t>(self, x, n, p);
|
188
|
+
} else if (klass == numo_cInt32) {
|
189
|
+
_rand_binomial<int32_t>(self, x, n, p);
|
190
|
+
} else if (klass == numo_cInt64) {
|
191
|
+
_rand_binomial<int64_t>(self, x, n, p);
|
192
|
+
} else if (klass == numo_cUInt8) {
|
193
|
+
_rand_binomial<uint8_t>(self, x, n, p);
|
194
|
+
} else if (klass == numo_cUInt16) {
|
195
|
+
_rand_binomial<uint16_t>(self, x, n, p);
|
196
|
+
} else if (klass == numo_cUInt32) {
|
197
|
+
_rand_binomial<uint32_t>(self, x, n, p);
|
198
|
+
} else if (klass == numo_cUInt64) {
|
199
|
+
_rand_binomial<uint64_t>(self, x, n, p);
|
200
|
+
}
|
201
|
+
|
202
|
+
RB_GC_GUARD(x);
|
203
|
+
return Qnil;
|
204
|
+
}
|
205
|
+
|
206
|
+
// #negative_binomial
|
207
|
+
|
208
|
+
template<typename T> static void _rand_negative_binomial(VALUE& self, VALUE& x, const long n, const double& p) {
|
209
|
+
Rng* ptr = get_rng(self);
|
210
|
+
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
211
|
+
std::negative_binomial_distribution<T> negative_binomial_dist(n, p);
|
212
|
+
ndfunc_t ndf = { _iter_rand<std::negative_binomial_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
213
|
+
rand_opt_t<std::negative_binomial_distribution<T>> opt = { negative_binomial_dist, ptr };
|
214
|
+
na_ndloop3(&ndf, &opt, 1, x);
|
215
|
+
}
|
216
|
+
|
217
|
+
static VALUE _numo_random_negative_binomial(int argc, VALUE* argv, VALUE self) {
|
218
|
+
VALUE x = Qnil;
|
219
|
+
VALUE kw_args = Qnil;
|
220
|
+
ID kw_table[2] = { rb_intern("n"), rb_intern("p") };
|
221
|
+
VALUE kw_values[2] = { Qundef, Qundef };
|
222
|
+
rb_scan_args(argc, argv, "1:", &x, &kw_args);
|
223
|
+
rb_get_kwargs(kw_args, kw_table, 2, 0, kw_values);
|
224
|
+
|
225
|
+
const VALUE klass = rb_obj_class(x);
|
226
|
+
if (klass != numo_cInt8 && klass != numo_cInt16 && klass != numo_cInt32 && klass != numo_cInt64
|
227
|
+
&& klass != numo_cUInt8 && klass != numo_cUInt16 && klass != numo_cUInt32 && klass != numo_cUInt64)
|
228
|
+
rb_raise(rb_eTypeError, "invalid NArray class, it must be integer typed array");
|
229
|
+
|
230
|
+
const long n = NUM2LONG(kw_values[0]);
|
231
|
+
const double p = NUM2DBL(kw_values[1]);
|
232
|
+
if (n < 0) rb_raise(rb_eArgError, "n must be a non-negative value");
|
233
|
+
if (p <= 0.0 || p > 1.0) rb_raise(rb_eArgError, "p must be > 0 and <= 1");
|
234
|
+
|
235
|
+
if (klass == numo_cInt8) {
|
236
|
+
_rand_negative_binomial<int8_t>(self, x, n, p);
|
237
|
+
} else if (klass == numo_cInt16) {
|
238
|
+
_rand_negative_binomial<int16_t>(self, x, n, p);
|
239
|
+
} else if (klass == numo_cInt32) {
|
240
|
+
_rand_negative_binomial<int32_t>(self, x, n, p);
|
241
|
+
} else if (klass == numo_cInt64) {
|
242
|
+
_rand_negative_binomial<int64_t>(self, x, n, p);
|
243
|
+
} else if (klass == numo_cUInt8) {
|
244
|
+
_rand_negative_binomial<uint8_t>(self, x, n, p);
|
245
|
+
} else if (klass == numo_cUInt16) {
|
246
|
+
_rand_negative_binomial<uint16_t>(self, x, n, p);
|
247
|
+
} else if (klass == numo_cUInt32) {
|
248
|
+
_rand_negative_binomial<uint32_t>(self, x, n, p);
|
249
|
+
} else if (klass == numo_cUInt64) {
|
250
|
+
_rand_negative_binomial<uint64_t>(self, x, n, p);
|
251
|
+
}
|
252
|
+
|
253
|
+
RB_GC_GUARD(x);
|
254
|
+
return Qnil;
|
255
|
+
}
|
256
|
+
|
257
|
+
// #geometric
|
258
|
+
|
259
|
+
template<typename T> static void _rand_geometric(VALUE& self, VALUE& x, const double& p) {
|
260
|
+
Rng* ptr = get_rng(self);
|
261
|
+
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
262
|
+
std::geometric_distribution<T> geometric_dist(p);
|
263
|
+
ndfunc_t ndf = { _iter_rand<std::geometric_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
264
|
+
rand_opt_t<std::geometric_distribution<T>> opt = { geometric_dist, ptr };
|
265
|
+
na_ndloop3(&ndf, &opt, 1, x);
|
266
|
+
}
|
267
|
+
|
268
|
+
static VALUE _numo_random_geometric(int argc, VALUE* argv, VALUE self) {
|
269
|
+
VALUE x = Qnil;
|
270
|
+
VALUE kw_args = Qnil;
|
271
|
+
ID kw_table[1] = { rb_intern("p") };
|
272
|
+
VALUE kw_values[1] = { Qundef };
|
273
|
+
rb_scan_args(argc, argv, "1:", &x, &kw_args);
|
274
|
+
rb_get_kwargs(kw_args, kw_table, 1, 0, kw_values);
|
275
|
+
|
276
|
+
const VALUE klass = rb_obj_class(x);
|
277
|
+
if (klass != numo_cInt8 && klass != numo_cInt16 && klass != numo_cInt32 && klass != numo_cInt64
|
278
|
+
&& klass != numo_cUInt8 && klass != numo_cUInt16 && klass != numo_cUInt32 && klass != numo_cUInt64)
|
279
|
+
rb_raise(rb_eTypeError, "invalid NArray class, it must be integer typed array");
|
280
|
+
|
281
|
+
const double p = NUM2DBL(kw_values[0]);
|
282
|
+
if (p <= 0.0 || p >= 1.0) rb_raise(rb_eArgError, "p must be > 0 and < 1");
|
283
|
+
|
284
|
+
if (klass == numo_cInt8) {
|
285
|
+
_rand_geometric<int8_t>(self, x, p);
|
286
|
+
} else if (klass == numo_cInt16) {
|
287
|
+
_rand_geometric<int16_t>(self, x, p);
|
288
|
+
} else if (klass == numo_cInt32) {
|
289
|
+
_rand_geometric<int32_t>(self, x, p);
|
290
|
+
} else if (klass == numo_cInt64) {
|
291
|
+
_rand_geometric<int64_t>(self, x, p);
|
292
|
+
} else if (klass == numo_cUInt8) {
|
293
|
+
_rand_geometric<uint8_t>(self, x, p);
|
294
|
+
} else if (klass == numo_cUInt16) {
|
295
|
+
_rand_geometric<uint16_t>(self, x, p);
|
296
|
+
} else if (klass == numo_cUInt32) {
|
297
|
+
_rand_geometric<uint32_t>(self, x, p);
|
298
|
+
} else if (klass == numo_cUInt64) {
|
299
|
+
_rand_geometric<uint64_t>(self, x, p);
|
300
|
+
}
|
301
|
+
|
302
|
+
RB_GC_GUARD(x);
|
303
|
+
return Qnil;
|
304
|
+
}
|
305
|
+
|
152
306
|
// #exponential
|
153
307
|
|
154
308
|
template<typename T> static void _rand_exponential(VALUE& self, VALUE& x, const double& lam) {
|
155
|
-
|
309
|
+
Rng* ptr = get_rng(self);
|
156
310
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
157
311
|
std::exponential_distribution<T> exponential_dist(lam);
|
158
312
|
ndfunc_t ndf = { _iter_rand<std::exponential_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -160,7 +314,7 @@ private:
|
|
160
314
|
na_ndloop3(&ndf, &opt, 1, x);
|
161
315
|
}
|
162
316
|
|
163
|
-
static VALUE
|
317
|
+
static VALUE _numo_random_exponential(int argc, VALUE* argv, VALUE self) {
|
164
318
|
VALUE x = Qnil;
|
165
319
|
VALUE kw_args = Qnil;
|
166
320
|
ID kw_table[1] = { rb_intern("scale") };
|
@@ -188,7 +342,7 @@ private:
|
|
188
342
|
// #gamma
|
189
343
|
|
190
344
|
template<typename T> static void _rand_gamma(VALUE& self, VALUE& x, const double& k, const double&scale) {
|
191
|
-
|
345
|
+
Rng* ptr = get_rng(self);
|
192
346
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
193
347
|
std::gamma_distribution<T> gamma_dist(k, scale);
|
194
348
|
ndfunc_t ndf = { _iter_rand<std::gamma_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -196,7 +350,7 @@ private:
|
|
196
350
|
na_ndloop3(&ndf, &opt, 1, x);
|
197
351
|
}
|
198
352
|
|
199
|
-
static VALUE
|
353
|
+
static VALUE _numo_random_gamma(int argc, VALUE* argv, VALUE self) {
|
200
354
|
VALUE x = Qnil;
|
201
355
|
VALUE kw_args = Qnil;
|
202
356
|
ID kw_table[2] = { rb_intern("k"), rb_intern("scale") };
|
@@ -225,7 +379,7 @@ private:
|
|
225
379
|
// #gumbel
|
226
380
|
|
227
381
|
template<typename T> static void _rand_gumbel(VALUE& self, VALUE& x, const double& loc, const double&scale) {
|
228
|
-
|
382
|
+
Rng* ptr = get_rng(self);
|
229
383
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
230
384
|
std::extreme_value_distribution<T> extreme_value_dist(loc, scale);
|
231
385
|
ndfunc_t ndf = { _iter_rand<std::extreme_value_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -233,7 +387,7 @@ private:
|
|
233
387
|
na_ndloop3(&ndf, &opt, 1, x);
|
234
388
|
}
|
235
389
|
|
236
|
-
static VALUE
|
390
|
+
static VALUE _numo_random_gumbel(int argc, VALUE* argv, VALUE self) {
|
237
391
|
VALUE x = Qnil;
|
238
392
|
VALUE kw_args = Qnil;
|
239
393
|
ID kw_table[2] = { rb_intern("loc"), rb_intern("scale") };
|
@@ -261,7 +415,7 @@ private:
|
|
261
415
|
// #poisson
|
262
416
|
|
263
417
|
template<typename T> static void _rand_poisson(VALUE& self, VALUE& x, const double& mean) {
|
264
|
-
|
418
|
+
Rng* ptr = get_rng(self);
|
265
419
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
266
420
|
std::poisson_distribution<T> poisson_dist(mean);
|
267
421
|
ndfunc_t ndf = { _iter_rand<std::poisson_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -269,11 +423,11 @@ private:
|
|
269
423
|
na_ndloop3(&ndf, &opt, 1, x);
|
270
424
|
}
|
271
425
|
|
272
|
-
static VALUE
|
426
|
+
static VALUE _numo_random_poisson(int argc, VALUE* argv, VALUE self) {
|
273
427
|
VALUE x = Qnil;
|
274
428
|
VALUE kw_args = Qnil;
|
275
|
-
ID kw_table[
|
276
|
-
VALUE kw_values[
|
429
|
+
ID kw_table[1] = { rb_intern("mean") };
|
430
|
+
VALUE kw_values[1] = { Qundef };
|
277
431
|
rb_scan_args(argc, argv, "1:", &x, &kw_args);
|
278
432
|
rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values);
|
279
433
|
|
@@ -310,7 +464,7 @@ private:
|
|
310
464
|
// #weibull
|
311
465
|
|
312
466
|
template<typename T> static void _rand_weibull(VALUE& self, VALUE& x, const double& k, const double&scale) {
|
313
|
-
|
467
|
+
Rng* ptr = get_rng(self);
|
314
468
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
315
469
|
std::weibull_distribution<T> weibull_dist(k, scale);
|
316
470
|
ndfunc_t ndf = { _iter_rand<std::weibull_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -318,7 +472,7 @@ private:
|
|
318
472
|
na_ndloop3(&ndf, &opt, 1, x);
|
319
473
|
}
|
320
474
|
|
321
|
-
static VALUE
|
475
|
+
static VALUE _numo_random_weibull(int argc, VALUE* argv, VALUE self) {
|
322
476
|
VALUE x = Qnil;
|
323
477
|
VALUE kw_args = Qnil;
|
324
478
|
ID kw_table[2] = { rb_intern("k"), rb_intern("scale") };
|
@@ -347,7 +501,7 @@ private:
|
|
347
501
|
// #discrete
|
348
502
|
|
349
503
|
template<typename T, typename P> static void _rand_discrete(VALUE& self, VALUE& x, const std::vector<P>& weight) {
|
350
|
-
|
504
|
+
Rng* ptr = get_rng(self);
|
351
505
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
352
506
|
std::discrete_distribution<T> discrete_dist(weight.begin(), weight.end());
|
353
507
|
ndfunc_t ndf = { _iter_rand<std::discrete_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -355,7 +509,7 @@ private:
|
|
355
509
|
na_ndloop3(&ndf, &opt, 1, x);
|
356
510
|
}
|
357
511
|
|
358
|
-
static VALUE
|
512
|
+
static VALUE _numo_random_discrete(int argc, VALUE* argv, VALUE self) {
|
359
513
|
VALUE x = Qnil;
|
360
514
|
VALUE kw_args = Qnil;
|
361
515
|
ID kw_table[1] = { rb_intern("weight") };
|
@@ -430,7 +584,7 @@ private:
|
|
430
584
|
// #uniform
|
431
585
|
|
432
586
|
template<typename T> static void _rand_uniform(VALUE& self, VALUE& x, const double& low, const double& high) {
|
433
|
-
|
587
|
+
Rng* ptr = get_rng(self);
|
434
588
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
435
589
|
std::uniform_real_distribution<T> uniform_dist(low, high);
|
436
590
|
ndfunc_t ndf = { _iter_rand<std::uniform_real_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -438,7 +592,7 @@ private:
|
|
438
592
|
na_ndloop3(&ndf, &opt, 1, x);
|
439
593
|
}
|
440
594
|
|
441
|
-
static VALUE
|
595
|
+
static VALUE _numo_random_uniform(int argc, VALUE* argv, VALUE self) {
|
442
596
|
VALUE x = Qnil;
|
443
597
|
VALUE kw_args = Qnil;
|
444
598
|
ID kw_table[2] = { rb_intern("low"), rb_intern("high") };
|
@@ -466,7 +620,7 @@ private:
|
|
466
620
|
// #cauchy
|
467
621
|
|
468
622
|
template<typename T> static void _rand_cauchy(VALUE& self, VALUE& x, const double& loc, const double& scale) {
|
469
|
-
|
623
|
+
Rng* ptr = get_rng(self);
|
470
624
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
471
625
|
std::cauchy_distribution<T> cauchy_dist(loc, scale);
|
472
626
|
ndfunc_t ndf = { _iter_rand<std::cauchy_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -474,7 +628,7 @@ private:
|
|
474
628
|
na_ndloop3(&ndf, &opt, 1, x);
|
475
629
|
}
|
476
630
|
|
477
|
-
static VALUE
|
631
|
+
static VALUE _numo_random_cauchy(int argc, VALUE* argv, VALUE self) {
|
478
632
|
VALUE x = Qnil;
|
479
633
|
VALUE kw_args = Qnil;
|
480
634
|
ID kw_table[2] = { rb_intern("loc"), rb_intern("scale") };
|
@@ -502,7 +656,7 @@ private:
|
|
502
656
|
// #chisqure
|
503
657
|
|
504
658
|
template<typename T> static void _rand_chisquare(VALUE& self, VALUE& x, const double& df) {
|
505
|
-
|
659
|
+
Rng* ptr = get_rng(self);
|
506
660
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
507
661
|
std::chi_squared_distribution<T> chisquare_dist(df);
|
508
662
|
ndfunc_t ndf = { _iter_rand<std::chi_squared_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -510,7 +664,7 @@ private:
|
|
510
664
|
na_ndloop3(&ndf, &opt, 1, x);
|
511
665
|
}
|
512
666
|
|
513
|
-
static VALUE
|
667
|
+
static VALUE _numo_random_chisquare(int argc, VALUE* argv, VALUE self) {
|
514
668
|
VALUE x = Qnil;
|
515
669
|
VALUE kw_args = Qnil;
|
516
670
|
ID kw_table[1] = { rb_intern("df") };
|
@@ -537,7 +691,7 @@ private:
|
|
537
691
|
// #f
|
538
692
|
|
539
693
|
template<typename T> static void _rand_f(VALUE& self, VALUE& x, const double& dfnum, const double& dfden) {
|
540
|
-
|
694
|
+
Rng* ptr = get_rng(self);
|
541
695
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
542
696
|
std::fisher_f_distribution<T> f_dist(dfnum, dfden);
|
543
697
|
ndfunc_t ndf = { _iter_rand<std::fisher_f_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -545,7 +699,7 @@ private:
|
|
545
699
|
na_ndloop3(&ndf, &opt, 1, x);
|
546
700
|
}
|
547
701
|
|
548
|
-
static VALUE
|
702
|
+
static VALUE _numo_random_f(int argc, VALUE* argv, VALUE self) {
|
549
703
|
VALUE x = Qnil;
|
550
704
|
VALUE kw_args = Qnil;
|
551
705
|
ID kw_table[2] = { rb_intern("dfnum"), rb_intern("dfden") };
|
@@ -574,7 +728,7 @@ private:
|
|
574
728
|
// #normal
|
575
729
|
|
576
730
|
template<typename T> static void _rand_normal(VALUE& self, VALUE& x, const double& loc, const double& scale) {
|
577
|
-
|
731
|
+
Rng* ptr = get_rng(self);
|
578
732
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
579
733
|
std::normal_distribution<T> normal_dist(loc, scale);
|
580
734
|
ndfunc_t ndf = { _iter_rand<std::normal_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -582,7 +736,7 @@ private:
|
|
582
736
|
na_ndloop3(&ndf, &opt, 1, x);
|
583
737
|
}
|
584
738
|
|
585
|
-
static VALUE
|
739
|
+
static VALUE _numo_random_normal(int argc, VALUE* argv, VALUE self) {
|
586
740
|
VALUE x = Qnil;
|
587
741
|
VALUE kw_args = Qnil;
|
588
742
|
ID kw_table[2] = { rb_intern("loc"), rb_intern("scale") };
|
@@ -610,7 +764,7 @@ private:
|
|
610
764
|
// #lognormal
|
611
765
|
|
612
766
|
template<typename T> static void _rand_lognormal(VALUE& self, VALUE& x, const double& mean, const double& sigma) {
|
613
|
-
|
767
|
+
Rng* ptr = get_rng(self);
|
614
768
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
615
769
|
std::lognormal_distribution<T> lognormal_dist(mean, sigma);
|
616
770
|
ndfunc_t ndf = { _iter_rand<std::lognormal_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -618,7 +772,7 @@ private:
|
|
618
772
|
na_ndloop3(&ndf, &opt, 1, x);
|
619
773
|
}
|
620
774
|
|
621
|
-
static VALUE
|
775
|
+
static VALUE _numo_random_lognormal(int argc, VALUE* argv, VALUE self) {
|
622
776
|
VALUE x = Qnil;
|
623
777
|
VALUE kw_args = Qnil;
|
624
778
|
ID kw_table[2] = { rb_intern("mean"), rb_intern("sigma") };
|
@@ -646,7 +800,7 @@ private:
|
|
646
800
|
// #standard_t
|
647
801
|
|
648
802
|
template<typename T> static void _rand_t(VALUE& self, VALUE& x, const double& df) {
|
649
|
-
|
803
|
+
Rng* ptr = get_rng(self);
|
650
804
|
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
|
651
805
|
std::student_t_distribution<T> t_dist(df);
|
652
806
|
ndfunc_t ndf = { _iter_rand<std::student_t_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
|
@@ -654,7 +808,7 @@ private:
|
|
654
808
|
na_ndloop3(&ndf, &opt, 1, x);
|
655
809
|
}
|
656
810
|
|
657
|
-
static VALUE
|
811
|
+
static VALUE _numo_random_standard_t(int argc, VALUE* argv, VALUE self) {
|
658
812
|
VALUE x = Qnil;
|
659
813
|
VALUE kw_args = Qnil;
|
660
814
|
ID kw_table[1] = { rb_intern("df") };
|
@@ -679,16 +833,72 @@ private:
|
|
679
833
|
}
|
680
834
|
};
|
681
835
|
|
682
|
-
|
836
|
+
class RbNumoRandomPCG32 : public RbNumoRandom<pcg32, RbNumoRandomPCG32> {
|
837
|
+
public:
|
838
|
+
static const rb_data_type_t rng_type;
|
839
|
+
};
|
840
|
+
|
841
|
+
const rb_data_type_t RbNumoRandomPCG32::rng_type = {
|
842
|
+
"RbNumoRandomPCG32",
|
843
|
+
{
|
844
|
+
NULL,
|
845
|
+
RbNumoRandomPCG32::numo_random_free,
|
846
|
+
RbNumoRandomPCG32::numo_random_size
|
847
|
+
},
|
848
|
+
NULL,
|
849
|
+
NULL,
|
850
|
+
0
|
851
|
+
};
|
852
|
+
|
853
|
+
class RbNumoRandomPCG64 : public RbNumoRandom<pcg64, RbNumoRandomPCG64> {
|
854
|
+
public:
|
855
|
+
static const rb_data_type_t rng_type;
|
856
|
+
};
|
857
|
+
|
858
|
+
const rb_data_type_t RbNumoRandomPCG64::rng_type = {
|
683
859
|
"RbNumoRandomPCG64",
|
684
860
|
{
|
685
861
|
NULL,
|
686
|
-
RbNumoRandomPCG64::
|
687
|
-
RbNumoRandomPCG64::
|
862
|
+
RbNumoRandomPCG64::numo_random_free,
|
863
|
+
RbNumoRandomPCG64::numo_random_size
|
864
|
+
},
|
865
|
+
NULL,
|
866
|
+
NULL,
|
867
|
+
0
|
868
|
+
};
|
869
|
+
|
870
|
+
class RbNumoRandomMT32 : public RbNumoRandom<std::mt19937, RbNumoRandomMT32> {
|
871
|
+
public:
|
872
|
+
static const rb_data_type_t rng_type;
|
873
|
+
};
|
874
|
+
|
875
|
+
const rb_data_type_t RbNumoRandomMT32::rng_type = {
|
876
|
+
"RbNumoRandomMT32",
|
877
|
+
{
|
878
|
+
NULL,
|
879
|
+
RbNumoRandomMT32::numo_random_free,
|
880
|
+
RbNumoRandomMT32::numo_random_size
|
881
|
+
},
|
882
|
+
NULL,
|
883
|
+
NULL,
|
884
|
+
0
|
885
|
+
};
|
886
|
+
|
887
|
+
class RbNumoRandomMT64 : public RbNumoRandom<std::mt19937_64, RbNumoRandomMT64> {
|
888
|
+
public:
|
889
|
+
static const rb_data_type_t rng_type;
|
890
|
+
};
|
891
|
+
|
892
|
+
const rb_data_type_t RbNumoRandomMT64::rng_type = {
|
893
|
+
"RbNumoRandomMT64",
|
894
|
+
{
|
895
|
+
NULL,
|
896
|
+
RbNumoRandomMT64::numo_random_free,
|
897
|
+
RbNumoRandomMT64::numo_random_size
|
688
898
|
},
|
689
899
|
NULL,
|
690
900
|
NULL,
|
691
|
-
|
901
|
+
0
|
692
902
|
};
|
693
903
|
|
694
904
|
#endif /* NUMO_RANDOM_EXT_HPP */
|
@@ -24,10 +24,21 @@ module Numo
|
|
24
24
|
# Creates a new random number generator.
|
25
25
|
#
|
26
26
|
# @param seed [Integer] random seed used to initialize the random number generator.
|
27
|
-
# @param algorithm [String] random number generation algorithm.
|
28
|
-
def initialize(seed: nil, algorithm: 'pcg64') # rubocop:disable
|
29
|
-
@algorithm =
|
30
|
-
@rng =
|
27
|
+
# @param algorithm [String] random number generation algorithm ('mt32', 'mt64', 'pcg32', and 'pcg64').
|
28
|
+
def initialize(seed: nil, algorithm: 'pcg64') # rubocop:disable Metrics/MethodLength
|
29
|
+
@algorithm = algorithm.to_s
|
30
|
+
@rng = case @algorithm
|
31
|
+
when 'mt32'
|
32
|
+
MT32.new(seed: seed)
|
33
|
+
when 'mt64'
|
34
|
+
MT64.new(seed: seed)
|
35
|
+
when 'pcg32'
|
36
|
+
PCG32.new(seed: seed)
|
37
|
+
when 'pcg64'
|
38
|
+
PCG64.new(seed: seed)
|
39
|
+
else
|
40
|
+
raise ArgumentError, "Numo::Random::Generator does not support '#{@algorithm}' algorithm"
|
41
|
+
end
|
31
42
|
end
|
32
43
|
|
33
44
|
# Returns the seed of random number generator.
|
@@ -57,6 +68,78 @@ module Numo
|
|
57
68
|
rng.random
|
58
69
|
end
|
59
70
|
|
71
|
+
# Generates array consists of random values according to the Bernoulli distribution.
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# require 'numo/random'
|
75
|
+
#
|
76
|
+
# rng = Numo::Random::Generator.new(seed: 42)
|
77
|
+
# x = rng.bernoulli(shape: 1000, p: 0.4)
|
78
|
+
#
|
79
|
+
# @param shape [Integer | Array<Integer>] size of random array.
|
80
|
+
# @param p [Float] probability of success.
|
81
|
+
# @param dtype [Symbol] data type of random array.
|
82
|
+
# @return [Numo::IntX | Numo::UIntX]
|
83
|
+
def bernoulli(shape:, p:, dtype: :int32)
|
84
|
+
binomial(shape: shape, n: 1, p: p, dtype: dtype)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Generates array consists of random values according to a binomial distribution.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# require 'numo/random'
|
91
|
+
#
|
92
|
+
# rng = Numo::Random::Generator.new(seed: 42)
|
93
|
+
# x = rng.binomial(shape: 1000, n: 10, p: 0.4)
|
94
|
+
#
|
95
|
+
# @param shape [Integer | Array<Integer>] size of random array.
|
96
|
+
# @param n [Integer] number of trials.
|
97
|
+
# @param p [Float] probability of success.
|
98
|
+
# @param dtype [Symbol] data type of random array.
|
99
|
+
# @return [Numo::IntX | Numo::UIntX]
|
100
|
+
def binomial(shape:, n:, p:, dtype: :int32)
|
101
|
+
x = klass(dtype).new(shape)
|
102
|
+
rng.binomial(x, n: n, p: p)
|
103
|
+
x
|
104
|
+
end
|
105
|
+
|
106
|
+
# Generates array consists of random values according to a negative binomial distribution.
|
107
|
+
#
|
108
|
+
# @example
|
109
|
+
# require 'numo/random'
|
110
|
+
#
|
111
|
+
# rng = Numo::Random::Generator.new(seed: 42)
|
112
|
+
# x = rng.negative_binomial(shape: 1000, n: 10, p: 0.4)
|
113
|
+
#
|
114
|
+
# @param shape [Integer | Array<Integer>] size of random array.
|
115
|
+
# @param n [Integer] number of trials.
|
116
|
+
# @param p [Float] probability of success.
|
117
|
+
# @param dtype [Symbol] data type of random array.
|
118
|
+
# @return [Numo::IntX | Numo::UIntX]
|
119
|
+
def negative_binomial(shape:, n:, p:, dtype: :int32)
|
120
|
+
x = klass(dtype).new(shape)
|
121
|
+
rng.negative_binomial(x, n: n, p: p)
|
122
|
+
x
|
123
|
+
end
|
124
|
+
|
125
|
+
# Generates array consists of random values according to a geometric distribution.
|
126
|
+
#
|
127
|
+
# @example
|
128
|
+
# require 'numo/random'
|
129
|
+
#
|
130
|
+
# rng = Numo::Random::Generator.new(seed: 42)
|
131
|
+
# x = rng.geometric(shape: 1000, p: 0.4)
|
132
|
+
#
|
133
|
+
# @param shape [Integer | Array<Integer>] size of random array.
|
134
|
+
# @param p [Float] probability of success on each trial.
|
135
|
+
# @param dtype [Symbol] data type of random array.
|
136
|
+
# @return [Numo::IntX | Numo::UIntX]
|
137
|
+
def geometric(shape:, p:, dtype: :int32)
|
138
|
+
x = klass(dtype).new(shape)
|
139
|
+
rng.geometric(x, p: p)
|
140
|
+
x
|
141
|
+
end
|
142
|
+
|
60
143
|
# Generates array consists of random values with an exponential distribution.
|
61
144
|
#
|
62
145
|
# @example
|
data/lib/numo/random/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: numo-random
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshoku
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: numo-narray
|