numo-random 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|

|
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
|
+

|
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
|