numo-random 0.2.0 → 0.3.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: 18a6bedc77eb910e04462508a925d336fe2e5e8c29f9c159643adea1e0988a88
4
- data.tar.gz: 728c52eb3e9f390cae89d149e6d4305228be5330e90fa39494ac0a1ffa546126
3
+ metadata.gz: a4c6c4db2ffcb5672e571ad59dc94c36d51f87adb29007db4b9678b803840915
4
+ data.tar.gz: c1debe024fe523f28d97a83f7eaee51dc27cf51acfd1efa1cc44cd2994659c72
5
5
  SHA512:
6
- metadata.gz: cd851012b81e6cec4d4dc7e37113ca9c6d5e0a56604107bba201a67cc4935f3618f887285a0c745adf3ad6c25493bbe6bd5fe4af49cac08eead625cb0c6afa78
7
- data.tar.gz: 88f85185352601de72dbf8889095e2603c0b581750c11d683eddab26ab313f30c1b38577a1a3a099d2dc6834d29e0fbe2e53052e05918e5de00648adfcf9930d
6
+ metadata.gz: 6364e78337ab7d87b0aa3cc18a2264992cb75ab15c65b0ce41065c78eacacbb96e21e55a5872a3878cb1ab143b4f8f7145ce4475e22eca725aef8a16fa0a8409
7
+ data.tar.gz: c3dfbd3d29761f951176395b2c48c596efbb998b3d1650484da908e576624557c60e8aabf64b015096aa0fb33780929c5a78b598a206ea659fdb4d75cea020f3
data/CHANGELOG.md CHANGED
@@ -1,9 +1,11 @@
1
1
  ## [Unreleased]
2
2
  - Bernoulli distribution.
3
- - Poisson distribution.
4
3
 
5
- ## [0.2.0]
4
+ ## [0.3.0]
5
+ - Change native extension filename.
6
+ - Add methods for random number generation with poisson distributions: poisson, exponential, gamma, gumbel, and weibull.
6
7
 
8
+ ## [0.2.0]
7
9
  - Add discrete method.
8
10
 
9
11
  ### Breaking Changes
@@ -16,9 +16,9 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- #include "randomext.hpp"
19
+ #include "ext.hpp"
20
20
 
21
- extern "C" void Init_randomext(void) {
21
+ 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");
@@ -16,8 +16,8 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- #ifndef NUMO_RANDOMEXT_HPP
20
- #define NUMO_RANDOMEXT_HPP 1
19
+ #ifndef NUMO_RANDOM_EXT_HPP
20
+ #define NUMO_RANDOM_EXT_HPP 1
21
21
 
22
22
  #include <ruby.h>
23
23
 
@@ -58,6 +58,11 @@ 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, "exponential", RUBY_METHOD_FUNC(_numo_random_pcg64_exponential), -1);
62
+ rb_define_method(rb_cPCG64, "gamma", RUBY_METHOD_FUNC(_numo_random_pcg64_gamma), -1);
63
+ rb_define_method(rb_cPCG64, "gumbel", RUBY_METHOD_FUNC(_numo_random_pcg64_gumbel), -1);
64
+ rb_define_method(rb_cPCG64, "poisson", RUBY_METHOD_FUNC(_numo_random_pcg64_poisson), -1);
65
+ rb_define_method(rb_cPCG64, "weibull", RUBY_METHOD_FUNC(_numo_random_pcg64_weibull), -1);
61
66
  rb_define_method(rb_cPCG64, "discrete", RUBY_METHOD_FUNC(_numo_random_pcg64_discrete), -1);
62
67
  rb_define_method(rb_cPCG64, "uniform", RUBY_METHOD_FUNC(_numo_random_pcg64_uniform), -1);
63
68
  rb_define_method(rb_cPCG64, "cauchy", RUBY_METHOD_FUNC(_numo_random_pcg64_cauchy), -1);
@@ -144,6 +149,201 @@ private:
144
149
  }
145
150
  }
146
151
 
152
+ // #exponential
153
+
154
+ template<typename T> static void _rand_exponential(VALUE& self, VALUE& x, const double& lam) {
155
+ pcg64* ptr = get_pcg64(self);
156
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
157
+ std::exponential_distribution<T> exponential_dist(lam);
158
+ ndfunc_t ndf = { _iter_rand<std::exponential_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
159
+ rand_opt_t<std::exponential_distribution<T>> opt = { exponential_dist, ptr };
160
+ na_ndloop3(&ndf, &opt, 1, x);
161
+ }
162
+
163
+ static VALUE _numo_random_pcg64_exponential(int argc, VALUE* argv, VALUE self) {
164
+ VALUE x = Qnil;
165
+ VALUE kw_args = Qnil;
166
+ ID kw_table[1] = { rb_intern("scale") };
167
+ VALUE kw_values[1] = { Qundef };
168
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
169
+ rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values);
170
+
171
+ const VALUE klass = rb_obj_class(x);
172
+ if (klass != numo_cSFloat && klass != numo_cDFloat) rb_raise(rb_eTypeError, "invalid NArray class, it must be DFloat or SFloat");
173
+
174
+ const double scale = kw_values[0] == Qundef ? 1.0 : NUM2DBL(kw_values[0]);
175
+ if (scale <= 0) rb_raise(rb_eArgError, "scale must be > 0");
176
+
177
+ const double lam = 1.0 / scale;
178
+ if (klass == numo_cSFloat) {
179
+ _rand_exponential<float>(self, x, lam);
180
+ } else {
181
+ _rand_exponential<double>(self, x, lam);
182
+ }
183
+
184
+ RB_GC_GUARD(x);
185
+ return Qnil;
186
+ }
187
+
188
+ // #gamma
189
+
190
+ template<typename T> static void _rand_gamma(VALUE& self, VALUE& x, const double& k, const double&scale) {
191
+ pcg64* ptr = get_pcg64(self);
192
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
193
+ std::gamma_distribution<T> gamma_dist(k, scale);
194
+ ndfunc_t ndf = { _iter_rand<std::gamma_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
195
+ rand_opt_t<std::gamma_distribution<T>> opt = { gamma_dist, ptr };
196
+ na_ndloop3(&ndf, &opt, 1, x);
197
+ }
198
+
199
+ static VALUE _numo_random_pcg64_gamma(int argc, VALUE* argv, VALUE self) {
200
+ VALUE x = Qnil;
201
+ VALUE kw_args = Qnil;
202
+ ID kw_table[2] = { rb_intern("k"), rb_intern("scale") };
203
+ VALUE kw_values[2] = { Qundef, Qundef };
204
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
205
+ rb_get_kwargs(kw_args, kw_table, 1, 1, kw_values);
206
+
207
+ const VALUE klass = rb_obj_class(x);
208
+ if (klass != numo_cSFloat && klass != numo_cDFloat) rb_raise(rb_eTypeError, "invalid NArray class, it must be DFloat or SFloat");
209
+
210
+ const double k = NUM2DBL(kw_values[0]);
211
+ if (k <= 0) rb_raise(rb_eArgError, "k must be > 0");
212
+ const double scale = kw_values[1] == Qundef ? 1.0 : NUM2DBL(kw_values[1]);
213
+ if (scale <= 0) rb_raise(rb_eArgError, "scale must be > 0");
214
+
215
+ if (klass == numo_cSFloat) {
216
+ _rand_gamma<float>(self, x, k, scale);
217
+ } else {
218
+ _rand_gamma<double>(self, x, k, scale);
219
+ }
220
+
221
+ RB_GC_GUARD(x);
222
+ return Qnil;
223
+ }
224
+
225
+ // #gumbel
226
+
227
+ template<typename T> static void _rand_gumbel(VALUE& self, VALUE& x, const double& loc, const double&scale) {
228
+ pcg64* ptr = get_pcg64(self);
229
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
230
+ std::extreme_value_distribution<T> extreme_value_dist(loc, scale);
231
+ ndfunc_t ndf = { _iter_rand<std::extreme_value_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
232
+ rand_opt_t<std::extreme_value_distribution<T>> opt = { extreme_value_dist, ptr };
233
+ na_ndloop3(&ndf, &opt, 1, x);
234
+ }
235
+
236
+ static VALUE _numo_random_pcg64_gumbel(int argc, VALUE* argv, VALUE self) {
237
+ VALUE x = Qnil;
238
+ VALUE kw_args = Qnil;
239
+ ID kw_table[2] = { rb_intern("loc"), rb_intern("scale") };
240
+ VALUE kw_values[2] = { Qundef, Qundef };
241
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
242
+ rb_get_kwargs(kw_args, kw_table, 0, 2, kw_values);
243
+
244
+ const VALUE klass = rb_obj_class(x);
245
+ if (klass != numo_cSFloat && klass != numo_cDFloat) rb_raise(rb_eTypeError, "invalid NArray class, it must be DFloat or SFloat");
246
+
247
+ const double loc = kw_values[0] == Qundef ? 0.0 : NUM2DBL(kw_values[0]);
248
+ const double scale = kw_values[1] == Qundef ? 1.0 : NUM2DBL(kw_values[1]);
249
+ if (scale <= 0) rb_raise(rb_eArgError, "scale must be > 0");
250
+
251
+ if (klass == numo_cSFloat) {
252
+ _rand_gumbel<float>(self, x, loc, scale);
253
+ } else {
254
+ _rand_gumbel<double>(self, x, loc, scale);
255
+ }
256
+
257
+ RB_GC_GUARD(x);
258
+ return Qnil;
259
+ }
260
+
261
+ // #poisson
262
+
263
+ template<typename T> static void _rand_poisson(VALUE& self, VALUE& x, const double& mean) {
264
+ pcg64* ptr = get_pcg64(self);
265
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
266
+ std::poisson_distribution<T> poisson_dist(mean);
267
+ ndfunc_t ndf = { _iter_rand<std::poisson_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
268
+ rand_opt_t<std::poisson_distribution<T>> opt = { poisson_dist, ptr };
269
+ na_ndloop3(&ndf, &opt, 1, x);
270
+ }
271
+
272
+ static VALUE _numo_random_pcg64_poisson(int argc, VALUE* argv, VALUE self) {
273
+ VALUE x = Qnil;
274
+ VALUE kw_args = Qnil;
275
+ ID kw_table[2] = { rb_intern("mean") };
276
+ VALUE kw_values[2] = { Qundef, Qundef };
277
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
278
+ rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values);
279
+
280
+ const VALUE klass = rb_obj_class(x);
281
+ if (klass != numo_cInt8 && klass != numo_cInt16 && klass != numo_cInt32 && klass != numo_cInt64
282
+ && klass != numo_cUInt8 && klass != numo_cUInt16 && klass != numo_cUInt32 && klass != numo_cUInt64)
283
+ rb_raise(rb_eTypeError, "invalid NArray class, it must be integer typed array");
284
+
285
+ const double mean = kw_values[0] == Qundef ? 0.0 : NUM2DBL(kw_values[0]);
286
+ if (mean <= 0.0) rb_raise(rb_eArgError, "mean must be > 0");
287
+
288
+ if (klass == numo_cInt8) {
289
+ _rand_poisson<int8_t>(self, x, mean);
290
+ } else if (klass == numo_cInt16) {
291
+ _rand_poisson<int16_t>(self, x, mean);
292
+ } else if (klass == numo_cInt32) {
293
+ _rand_poisson<int32_t>(self, x, mean);
294
+ } else if (klass == numo_cInt64) {
295
+ _rand_poisson<int64_t>(self, x, mean);
296
+ } else if (klass == numo_cUInt8) {
297
+ _rand_poisson<uint8_t>(self, x, mean);
298
+ } else if (klass == numo_cUInt16) {
299
+ _rand_poisson<uint16_t>(self, x, mean);
300
+ } else if (klass == numo_cUInt32) {
301
+ _rand_poisson<uint32_t>(self, x, mean);
302
+ } else if (klass == numo_cUInt64) {
303
+ _rand_poisson<uint64_t>(self, x, mean);
304
+ }
305
+
306
+ RB_GC_GUARD(x);
307
+ return Qnil;
308
+ }
309
+
310
+ // #weibull
311
+
312
+ template<typename T> static void _rand_weibull(VALUE& self, VALUE& x, const double& k, const double&scale) {
313
+ pcg64* ptr = get_pcg64(self);
314
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
315
+ std::weibull_distribution<T> weibull_dist(k, scale);
316
+ ndfunc_t ndf = { _iter_rand<std::weibull_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
317
+ rand_opt_t<std::weibull_distribution<T>> opt = { weibull_dist, ptr };
318
+ na_ndloop3(&ndf, &opt, 1, x);
319
+ }
320
+
321
+ static VALUE _numo_random_pcg64_weibull(int argc, VALUE* argv, VALUE self) {
322
+ VALUE x = Qnil;
323
+ VALUE kw_args = Qnil;
324
+ ID kw_table[2] = { rb_intern("k"), rb_intern("scale") };
325
+ VALUE kw_values[2] = { Qundef, Qundef };
326
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
327
+ rb_get_kwargs(kw_args, kw_table, 1, 1, kw_values);
328
+
329
+ const VALUE klass = rb_obj_class(x);
330
+ if (klass != numo_cSFloat && klass != numo_cDFloat) rb_raise(rb_eTypeError, "invalid NArray class, it must be DFloat or SFloat");
331
+
332
+ const double k = NUM2DBL(kw_values[0]);
333
+ if (k <= 0) rb_raise(rb_eArgError, "k must be > 0");
334
+ const double scale = kw_values[1] == Qundef ? 1.0 : NUM2DBL(kw_values[1]);
335
+ if (scale <= 0) rb_raise(rb_eArgError, "scale must be > 0");
336
+
337
+ if (klass == numo_cSFloat) {
338
+ _rand_weibull<float>(self, x, k, scale);
339
+ } else {
340
+ _rand_weibull<double>(self, x, k, scale);
341
+ }
342
+
343
+ RB_GC_GUARD(x);
344
+ return Qnil;
345
+ }
346
+
147
347
  // #discrete
148
348
 
149
349
  template<typename T, typename P> static void _rand_discrete(VALUE& self, VALUE& x, const std::vector<P>& weight) {
@@ -491,4 +691,4 @@ const rb_data_type_t RbNumoRandomPCG64::pcg64_type = {
491
691
  RUBY_TYPED_FREE_IMMEDIATELY
492
692
  };
493
693
 
494
- #endif /* NUMO_RANDOMEXT_HPP */
694
+ #endif /* NUMO_RANDOM_EXT_HPP */
@@ -26,4 +26,4 @@ $CXXFLAGS << " -std=c++11"
26
26
  $INCFLAGS << " -I$(srcdir)/src"
27
27
  $VPATH << "$(srcdir)/src"
28
28
 
29
- create_makefile("numo/random/randomext")
29
+ create_makefile("numo/random/ext")
@@ -16,7 +16,7 @@ module Numo
16
16
  # # Numo::DFloat#shape=[2,5]
17
17
  # # [[1.90546, -0.543299, 0.673332, 0.759583, -0.40945],
18
18
  # # [0.334635, -0.0558342, 1.28115, 1.93644, -0.0689543]]
19
- class Generator
19
+ class Generator # rubocop:disable Metrics/ClassLength
20
20
  # Returns random number generation algorithm.
21
21
  # @return [String]
22
22
  attr_accessor :algorithm
@@ -57,6 +57,99 @@ module Numo
57
57
  rng.random
58
58
  end
59
59
 
60
+ # Generates array consists of random values with an exponential distribution.
61
+ #
62
+ # @example
63
+ # require 'numo/random'
64
+ #
65
+ # rng = Numo::Random::Generator.new
66
+ # x = rng.exponential(shape: 100, scale: 2)
67
+ #
68
+ # @param shape [Integer | Array<Integer>] size of random array.
69
+ # @param scale [Float] scale parameter, lambda = 1.fdiv(scale).
70
+ # @param dtype [Symbol] data type of random array.
71
+ # @return [Numo::DFloat | Numo::SFloat]
72
+ def exponential(shape:, scale: 1.0, dtype: :float64)
73
+ x = klass(dtype).new(shape)
74
+ rng.exponential(x, scale: scale)
75
+ x
76
+ end
77
+
78
+ # Generates array consists of random values with a gamma distribution.
79
+ #
80
+ # @example
81
+ # require 'numo/random'
82
+ #
83
+ # rng = Numo::Random::Generator.new
84
+ # x = rng.gamma(shape: 100, k: 9, scale: 0.5)
85
+ #
86
+ # @param shape [Integer | Array<Integer>] size of random array.
87
+ # @param k [Float] shape parameter.
88
+ # @param scale [Float] scale parameter.
89
+ # @param dtype [Symbol] data type of random array.
90
+ # @return [Numo::DFloat | Numo::SFloat]
91
+ def gamma(shape:, k:, scale: 1.0, dtype: :float64)
92
+ x = klass(dtype).new(shape)
93
+ rng.gamma(x, k: k, scale: scale)
94
+ x
95
+ end
96
+
97
+ # Generates array consists of random values according to the Gumbel distribution.
98
+ #
99
+ # @example
100
+ # require 'numo/random'
101
+ #
102
+ # rng = Numo::Random::Generator.new
103
+ # x = rng.gumbel(shape: 100, loc: 0.0, scale: 1.0)
104
+ #
105
+ # @param shape [Integer | Array<Integer>] size of random array.
106
+ # @param loc [Float] location parameter.
107
+ # @param scale [Float] scale parameter.
108
+ # @param dtype [Symbol] data type of random array.
109
+ # @return [Numo::DFloat | Numo::SFloat]
110
+ def gumbel(shape:, loc: 0.0, scale: 1.0, dtype: :float64)
111
+ x = klass(dtype).new(shape)
112
+ rng.gumbel(x, loc: loc, scale: scale)
113
+ x
114
+ end
115
+
116
+ # Generates array consists of random values according to the Poisson distribution.
117
+ #
118
+ # @example
119
+ # require 'numo/random'
120
+ #
121
+ # rng = Numo::Random::Generator.new(seed: 42)
122
+ # x = rng.poisson(shape: 1000, mean: 4)
123
+ #
124
+ # @param shape [Integer | Array<Integer>] size of random array.
125
+ # @param mean [Float] mean of poisson distribution.
126
+ # @param dtype [Symbol] data type of random array.
127
+ # @return [Numo::IntX | Numo::UIntX]
128
+ def poisson(shape:, mean: 1.0, dtype: :int32)
129
+ x = klass(dtype).new(shape)
130
+ rng.poisson(x, mean: mean)
131
+ x
132
+ end
133
+
134
+ # Generates array consists of random values with the Weibull distribution.
135
+ #
136
+ # @example
137
+ # require 'numo/random'
138
+ #
139
+ # rng = Numo::Random::Generator.new
140
+ # x = rng.weibull(shape: 100, k: 5, scale: 2)
141
+ #
142
+ # @param shape [Integer | Array<Integer>] size of random array.
143
+ # @param k [Float] shape parameter.
144
+ # @param scale [Float] scale parameter.
145
+ # @param dtype [Symbol] data type of random array.
146
+ # @return [Numo::DFloat | Numo::SFloat]
147
+ def weibull(shape:, k:, scale: 1.0, dtype: :float64)
148
+ x = klass(dtype).new(shape)
149
+ rng.weibull(x, k: k, scale: scale)
150
+ x
151
+ end
152
+
60
153
  # Generates array consists of random integer values in the interval [0, n).
61
154
  #
62
155
  # @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.2.0'
6
+ VERSION = '0.3.0'
7
7
  end
8
8
  end
data/lib/numo/random.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  require 'numo/narray'
4
4
 
5
5
  require_relative 'random/version'
6
- require_relative 'random/randomext'
6
+ require_relative 'random/ext'
7
7
  require_relative 'random/generator'
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.2.0
4
+ version: 0.3.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-10-30 00:00:00.000000000 Z
11
+ date: 2022-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -37,9 +37,9 @@ files:
37
37
  - CODE_OF_CONDUCT.md
38
38
  - LICENSE.txt
39
39
  - README.md
40
+ - ext/numo/random/ext.cpp
41
+ - ext/numo/random/ext.hpp
40
42
  - ext/numo/random/extconf.rb
41
- - ext/numo/random/randomext.cpp
42
- - ext/numo/random/randomext.hpp
43
43
  - ext/numo/random/src/LICENSE.txt
44
44
  - ext/numo/random/src/pcg_extras.hpp
45
45
  - ext/numo/random/src/pcg_random.hpp