numo-random 0.3.0 → 0.4.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 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