numo-random 0.2.0 → 0.3.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: 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