numo-random 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4c6c4db2ffcb5672e571ad59dc94c36d51f87adb29007db4b9678b803840915
4
- data.tar.gz: c1debe024fe523f28d97a83f7eaee51dc27cf51acfd1efa1cc44cd2994659c72
3
+ metadata.gz: 9c0f7c2bfe21c7c499f2d18453607b78ccd48bfea287336a3ce8ca4bee1a30e0
4
+ data.tar.gz: cef6d2005611cabe21606d3b9e3fe31b82ee9e34e909206c6b0b89b6fc78115d
5
5
  SHA512:
6
- metadata.gz: 6364e78337ab7d87b0aa3cc18a2264992cb75ab15c65b0ce41065c78eacacbb96e21e55a5872a3878cb1ab143b4f8f7145ce4475e22eca725aef8a16fa0a8409
7
- data.tar.gz: c3dfbd3d29761f951176395b2c48c596efbb998b3d1650484da908e576624557c60e8aabf64b015096aa0fb33780929c5a78b598a206ea659fdb4d75cea020f3
6
+ metadata.gz: 7e42a2ecae4e48173c0f96a8d5170bed05165c378289a3b84c1fdad56bd8dcc392b53596c1d3501ddf151bfdd6b10ae82032b6b6ca4f1f03a38e87e8ff83f418
7
+ data.tar.gz: 96f8de00675b3762ed859a5a9afef3fa8f2fe8a7d48562a3aae267d78caa963e9ddc6c514a6c14a0121b4ab1d633d370a04b6fd64551a60b46e03f73c94682b9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,5 @@
1
- ## [Unreleased]
2
- - Bernoulli distribution.
1
+ ## [0.4.0]
2
+ - Add method for random number generation with bernoulli distribution: bernoulli, binomial, negative_binomial, and geometric.
3
3
 
4
4
  ## [0.3.0]
5
5
  - Change native extension filename.
@@ -58,6 +58,9 @@ public:
58
58
  rb_define_method(rb_cPCG64, "seed=", RUBY_METHOD_FUNC(_numo_random_pcg64_set_seed), 1);
59
59
  rb_define_method(rb_cPCG64, "seed", RUBY_METHOD_FUNC(_numo_random_pcg64_get_seed), 0);
60
60
  rb_define_method(rb_cPCG64, "random", RUBY_METHOD_FUNC(_numo_random_pcg64_random), 0);
61
+ rb_define_method(rb_cPCG64, "binomial", RUBY_METHOD_FUNC(_numo_random_pcg64_binomial), -1);
62
+ rb_define_method(rb_cPCG64, "negative_binomial", RUBY_METHOD_FUNC(_numo_random_pcg64_negative_binomial), -1);
63
+ rb_define_method(rb_cPCG64, "geometric", RUBY_METHOD_FUNC(_numo_random_pcg64_geometric), -1);
61
64
  rb_define_method(rb_cPCG64, "exponential", RUBY_METHOD_FUNC(_numo_random_pcg64_exponential), -1);
62
65
  rb_define_method(rb_cPCG64, "gamma", RUBY_METHOD_FUNC(_numo_random_pcg64_gamma), -1);
63
66
  rb_define_method(rb_cPCG64, "gumbel", RUBY_METHOD_FUNC(_numo_random_pcg64_gumbel), -1);
@@ -149,6 +152,157 @@ 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
+ pcg64* ptr = get_pcg64(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_pcg64_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
+ pcg64* ptr = get_pcg64(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_pcg64_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
+ pcg64* ptr = get_pcg64(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_pcg64_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) {
@@ -272,8 +426,8 @@ private:
272
426
  static VALUE _numo_random_pcg64_poisson(int argc, VALUE* argv, VALUE self) {
273
427
  VALUE x = Qnil;
274
428
  VALUE kw_args = Qnil;
275
- ID kw_table[2] = { rb_intern("mean") };
276
- VALUE kw_values[2] = { Qundef, Qundef };
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
 
@@ -57,6 +57,78 @@ module Numo
57
57
  rng.random
58
58
  end
59
59
 
60
+ # Generates array consists of random values according to the Bernoulli distribution.
61
+ #
62
+ # @example
63
+ # require 'numo/random'
64
+ #
65
+ # rng = Numo::Random::Generator.new(seed: 42)
66
+ # x = rng.bernoulli(shape: 1000, p: 0.4)
67
+ #
68
+ # @param shape [Integer | Array<Integer>] size of random array.
69
+ # @param p [Float] probability of success.
70
+ # @param dtype [Symbol] data type of random array.
71
+ # @return [Numo::IntX | Numo::UIntX]
72
+ def bernoulli(shape:, p:, dtype: :int32)
73
+ binomial(shape: shape, n: 1, p: p, dtype: dtype)
74
+ end
75
+
76
+ # Generates array consists of random values according to a binomial distribution.
77
+ #
78
+ # @example
79
+ # require 'numo/random'
80
+ #
81
+ # rng = Numo::Random::Generator.new(seed: 42)
82
+ # x = rng.binomial(shape: 1000, n: 10, p: 0.4)
83
+ #
84
+ # @param shape [Integer | Array<Integer>] size of random array.
85
+ # @param n [Integer] number of trials.
86
+ # @param p [Float] probability of success.
87
+ # @param dtype [Symbol] data type of random array.
88
+ # @return [Numo::IntX | Numo::UIntX]
89
+ def binomial(shape:, n:, p:, dtype: :int32)
90
+ x = klass(dtype).new(shape)
91
+ rng.binomial(x, n: n, p: p)
92
+ x
93
+ end
94
+
95
+ # Generates array consists of random values according to a negative binomial distribution.
96
+ #
97
+ # @example
98
+ # require 'numo/random'
99
+ #
100
+ # rng = Numo::Random::Generator.new(seed: 42)
101
+ # x = rng.negative_binomial(shape: 1000, n: 10, p: 0.4)
102
+ #
103
+ # @param shape [Integer | Array<Integer>] size of random array.
104
+ # @param n [Integer] number of trials.
105
+ # @param p [Float] probability of success.
106
+ # @param dtype [Symbol] data type of random array.
107
+ # @return [Numo::IntX | Numo::UIntX]
108
+ def negative_binomial(shape:, n:, p:, dtype: :int32)
109
+ x = klass(dtype).new(shape)
110
+ rng.negative_binomial(x, n: n, p: p)
111
+ x
112
+ end
113
+
114
+ # Generates array consists of random values according to a geometric distribution.
115
+ #
116
+ # @example
117
+ # require 'numo/random'
118
+ #
119
+ # rng = Numo::Random::Generator.new(seed: 42)
120
+ # x = rng.geometric(shape: 1000, p: 0.4)
121
+ #
122
+ # @param shape [Integer | Array<Integer>] size of random array.
123
+ # @param p [Float] probability of success on each trial.
124
+ # @param dtype [Symbol] data type of random array.
125
+ # @return [Numo::IntX | Numo::UIntX]
126
+ def geometric(shape:, p:, dtype: :int32)
127
+ x = klass(dtype).new(shape)
128
+ rng.geometric(x, p: p)
129
+ x
130
+ end
131
+
60
132
  # Generates array consists of random values with an exponential distribution.
61
133
  #
62
134
  # @example
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Random
5
5
  # The version of Numo::Random you install.
6
- VERSION = '0.3.0'
6
+ VERSION = '0.4.0'
7
7
  end
8
8
  end
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.3.0
4
+ version: 0.4.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-05 00:00:00.000000000 Z
11
+ date: 2022-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray