numo-random 0.1.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: d990f496714f1d2a594e3f9a919f65d4458d6e9ae455bbff9fc4a118aa059770
4
- data.tar.gz: 1017db53d848fb8e3c4d6724b51527d7d46974d813a93a2eb623270f24edb919
3
+ metadata.gz: a4c6c4db2ffcb5672e571ad59dc94c36d51f87adb29007db4b9678b803840915
4
+ data.tar.gz: c1debe024fe523f28d97a83f7eaee51dc27cf51acfd1efa1cc44cd2994659c72
5
5
  SHA512:
6
- metadata.gz: 7df9d692aa5222adb12ff53768eb804027333f381012e3c137232d847f05bc53514193f2c566092bceedc2ec863e14d100415a6a3fb70f1de08bbf8a78f89286
7
- data.tar.gz: 153d4fb9f6fc18f24e29c14b3f519dadfb0e8f979a1d4b60c31eac667c54e2d75cdaa937700f6fce9e73dc97f368dc08a4b7f2a92f77a241b909825cc573627a
6
+ metadata.gz: 6364e78337ab7d87b0aa3cc18a2264992cb75ab15c65b0ce41065c78eacacbb96e21e55a5872a3878cb1ab143b4f8f7145ce4475e22eca725aef8a16fa0a8409
7
+ data.tar.gz: c3dfbd3d29761f951176395b2c48c596efbb998b3d1650484da908e576624557c60e8aabf64b015096aa0fb33780929c5a78b598a206ea659fdb4d75cea020f3
data/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
1
  ## [Unreleased]
2
- - Sampling distribution.
3
2
  - Bernoulli distribution.
4
- - Poisson distribution.
3
+
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.
7
+
8
+ ## [0.2.0]
9
+ - Add discrete method.
10
+
11
+ ### Breaking Changes
12
+ - Change to return array for all methods that fill array with random numbers in Generator class.
5
13
 
6
14
  ## [0.1.0]
7
15
  - Initial release.
data/README.md CHANGED
@@ -33,14 +33,11 @@ require 'numo/gnuplot'
33
33
 
34
34
  require 'numo/random'
35
35
 
36
- # Prepareing array to be filled with random numbers.
37
- x = Numo::DFloat.new(5000, 2)
38
-
39
36
  # Creating random number generator.
40
37
  rng = Numo::Random::Generator.new(seed: 42)
41
38
 
42
39
  # Generating random numbers with a normal distribution.
43
- rng.normal(x, loc: 0.0, scale: 1.0)
40
+ x = rng.normal(shape: [5000, 2], loc: 0.0, scale: 1.0)
44
41
 
45
42
  # Plotting the generated result.
46
43
  Numo.gnuplot do
@@ -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,12 @@ 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);
66
+ rb_define_method(rb_cPCG64, "discrete", RUBY_METHOD_FUNC(_numo_random_pcg64_discrete), -1);
61
67
  rb_define_method(rb_cPCG64, "uniform", RUBY_METHOD_FUNC(_numo_random_pcg64_uniform), -1);
62
68
  rb_define_method(rb_cPCG64, "cauchy", RUBY_METHOD_FUNC(_numo_random_pcg64_cauchy), -1);
63
69
  rb_define_method(rb_cPCG64, "chisquare", RUBY_METHOD_FUNC(_numo_random_pcg64_chisquare), -1);
@@ -143,6 +149,284 @@ private:
143
149
  }
144
150
  }
145
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
+
347
+ // #discrete
348
+
349
+ template<typename T, typename P> static void _rand_discrete(VALUE& self, VALUE& x, const std::vector<P>& weight) {
350
+ pcg64* ptr = get_pcg64(self);
351
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 0 } };
352
+ std::discrete_distribution<T> discrete_dist(weight.begin(), weight.end());
353
+ ndfunc_t ndf = { _iter_rand<std::discrete_distribution<T>, T>, FULL_LOOP, 1, 0, ain, 0 };
354
+ rand_opt_t<std::discrete_distribution<T>> opt = { discrete_dist, ptr };
355
+ na_ndloop3(&ndf, &opt, 1, x);
356
+ }
357
+
358
+ static VALUE _numo_random_pcg64_discrete(int argc, VALUE* argv, VALUE self) {
359
+ VALUE x = Qnil;
360
+ VALUE kw_args = Qnil;
361
+ ID kw_table[1] = { rb_intern("weight") };
362
+ VALUE kw_values[1] = { Qundef };
363
+ rb_scan_args(argc, argv, "1:", &x, &kw_args);
364
+ rb_get_kwargs(kw_args, kw_table, 1, 0, kw_values);
365
+
366
+ VALUE klass = rb_obj_class(x);
367
+ if (klass != numo_cInt8 && klass != numo_cInt16 && klass != numo_cInt32 && klass != numo_cInt64
368
+ && klass != numo_cUInt8 && klass != numo_cUInt16 && klass != numo_cUInt32 && klass != numo_cUInt64)
369
+ rb_raise(rb_eTypeError, "invalid NArray class, it must be integer typed array");
370
+
371
+ VALUE w = kw_values[0];
372
+ VALUE w_klass = rb_obj_class(w);
373
+ if (w_klass != numo_cSFloat && w_klass != numo_cDFloat) rb_raise(rb_eTypeError, "weight must be Numo::DFloat or Numo::SFloat");
374
+
375
+ if (!RTEST(nary_check_contiguous(w))) w = nary_dup(w);
376
+ narray_t* w_nary;
377
+ GetNArray(w, w_nary);
378
+ if (NA_NDIM(w_nary) != 1) rb_raise(rb_eArgError, "weight must be 1-dimensional array");
379
+
380
+ const size_t w_len = NA_SHAPE(w_nary)[0];
381
+ if (w_len < 1) rb_raise(rb_eArgError, "length of weight must be > 0");
382
+
383
+ if (w_klass == numo_cSFloat) {
384
+ const float* w_ptr = (float*)na_get_pointer_for_read(w);
385
+ std::vector<float> w_vec(w_ptr, w_ptr + w_len);
386
+ if (klass == numo_cInt8) {
387
+ _rand_discrete<int8_t, float>(self, x, w_vec);
388
+ } else if (klass == numo_cInt16) {
389
+ _rand_discrete<int16_t, float>(self, x, w_vec);
390
+ } else if (klass == numo_cInt32) {
391
+ _rand_discrete<int32_t, float>(self, x, w_vec);
392
+ } else if (klass == numo_cInt64) {
393
+ _rand_discrete<int64_t, float>(self, x, w_vec);
394
+ } else if (klass == numo_cUInt8) {
395
+ _rand_discrete<uint8_t, float>(self, x, w_vec);
396
+ } else if (klass == numo_cUInt16) {
397
+ _rand_discrete<uint16_t, float>(self, x, w_vec);
398
+ } else if (klass == numo_cUInt32) {
399
+ _rand_discrete<uint32_t, float>(self, x, w_vec);
400
+ } else if (klass == numo_cUInt64) {
401
+ _rand_discrete<uint64_t, float>(self, x, w_vec);
402
+ }
403
+ } else {
404
+ const double* w_ptr = (double*)na_get_pointer_for_read(w);
405
+ std::vector<double> w_vec(w_ptr, w_ptr + w_len);
406
+ if (klass == numo_cInt8) {
407
+ _rand_discrete<int8_t, double>(self, x, w_vec);
408
+ } else if (klass == numo_cInt16) {
409
+ _rand_discrete<int16_t, double>(self, x, w_vec);
410
+ } else if (klass == numo_cInt32) {
411
+ _rand_discrete<int32_t, double>(self, x, w_vec);
412
+ } else if (klass == numo_cInt64) {
413
+ _rand_discrete<int64_t, double>(self, x, w_vec);
414
+ } else if (klass == numo_cUInt8) {
415
+ _rand_discrete<uint8_t, double>(self, x, w_vec);
416
+ } else if (klass == numo_cUInt16) {
417
+ _rand_discrete<uint16_t, double>(self, x, w_vec);
418
+ } else if (klass == numo_cUInt32) {
419
+ _rand_discrete<uint32_t, double>(self, x, w_vec);
420
+ } else if (klass == numo_cUInt64) {
421
+ _rand_discrete<uint64_t, double>(self, x, w_vec);
422
+ }
423
+ }
424
+
425
+ RB_GC_GUARD(w);
426
+ RB_GC_GUARD(x);
427
+ return Qnil;
428
+ }
429
+
146
430
  // #uniform
147
431
 
148
432
  template<typename T> static void _rand_uniform(VALUE& self, VALUE& x, const double& low, const double& high) {
@@ -407,4 +691,4 @@ const rb_data_type_t RbNumoRandomPCG64::pcg64_type = {
407
691
  RUBY_TYPED_FREE_IMMEDIATELY
408
692
  };
409
693
 
410
- #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")
@@ -0,0 +1,342 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby/Numo (NUmerical MOdules)
4
+ module Numo
5
+ # Numo::Random provides random number generation with several distributions for Numo::NArray.
6
+ module Random
7
+ # Generator is a class that generates random number with several distributions.
8
+ #
9
+ # @example
10
+ # require 'numo/random'
11
+ #
12
+ # rng = Numo::Random::Generator.new(seed: 496)
13
+ # x = rng.uniform(shape: [2, 5], low: -1, high: 2)
14
+ #
15
+ # p x
16
+ # # Numo::DFloat#shape=[2,5]
17
+ # # [[1.90546, -0.543299, 0.673332, 0.759583, -0.40945],
18
+ # # [0.334635, -0.0558342, 1.28115, 1.93644, -0.0689543]]
19
+ class Generator # rubocop:disable Metrics/ClassLength
20
+ # Returns random number generation algorithm.
21
+ # @return [String]
22
+ attr_accessor :algorithm
23
+
24
+ # Creates a new random number generator.
25
+ #
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 Lint/UnusedMethodArgument
29
+ @algorithm = 'pcg64'
30
+ @rng = PCG64.new(seed: seed)
31
+ end
32
+
33
+ # Returns the seed of random number generator.
34
+ #
35
+ # @return [Integer]
36
+ def seed
37
+ rng.seed
38
+ end
39
+
40
+ # Sets the seed of random number generator.
41
+ #
42
+ # @param val [Integer] random seed.
43
+ def seed=(val)
44
+ rng.seed = val
45
+ end
46
+
47
+ # Returns random number with uniform distribution in the half-open interval [0, 1).
48
+ #
49
+ # @example
50
+ # require 'numo/random'
51
+ #
52
+ # rng = Numo::Random::Generator.new
53
+ # v = rng.random
54
+ #
55
+ # @return [Float]
56
+ def random
57
+ rng.random
58
+ end
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
+
153
+ # Generates array consists of random integer values in the interval [0, n).
154
+ #
155
+ # @example
156
+ # require 'numo/random'
157
+ #
158
+ # rng = Numo::Random::Generator.new(seed: 42)
159
+ # w = Numo::DFloat[0.1, 0.6, 0.2]
160
+ # x = rng.discrete(shape: [3, 10], weight: w)
161
+ #
162
+ # p x
163
+ #
164
+ # # Numo::Int32#shape=[3,10]
165
+ # # [[1, 1, 1, 1, 1, 1, 1, 1, 2, 1],
166
+ # # [0, 1, 0, 1, 1, 0, 1, 1, 2, 1],
167
+ # # [2, 1, 1, 1, 1, 2, 2, 1, 1, 2]]
168
+ #
169
+ # @param shape [Integer | Array<Integer>] size of random array.
170
+ # @param weight [Numo::DFloat | Numo::SFloat] (shape: [n]) list of probabilities of each integer being generated.
171
+ # @param dtype [Symbol] data type of random array.
172
+ # @return [Numo::IntX | Numo::UIntX]
173
+ def discrete(shape:, weight:, dtype: :int32)
174
+ x = klass(dtype).new(shape)
175
+ rng.discrete(x, weight: weight)
176
+ x
177
+ end
178
+
179
+ # Generates array consists of uniformly distributed random values in the interval [low, high).
180
+ #
181
+ # @example
182
+ # require 'numo/random'
183
+ #
184
+ # rng = Numo::Random::Generator.new
185
+ # x = rng.uniform(shape: 100, low: -1.5, high: 1.5)
186
+ #
187
+ # @param shape [Integer | Array<Integer>] size of random array.
188
+ # @param low [Float] lower boundary.
189
+ # @param high [Float] upper boundary.
190
+ # @param dtype [Symbol] data type of random array.
191
+ # @return [Numo::DFloat | Numo::SFloat]
192
+ def uniform(shape:, low: 0.0, high: 1.0, dtype: :float64)
193
+ x = klass(dtype).new(shape)
194
+ rng.uniform(x, low: low, high: high)
195
+ x
196
+ end
197
+
198
+ # Generates array consists of random values according to the Cauchy (Lorentz) distribution.
199
+ #
200
+ # @example
201
+ # require 'numo/random'
202
+ #
203
+ # rng = Numo::Random::Generator.new
204
+ # x = rng.cauchy(shape: 100, loc: 0.0, scale: 1.0)
205
+ #
206
+ # @param shape [Integer | Array<Integer>] size of random array.
207
+ # @param loc [Float] location parameter.
208
+ # @param scale [Float] scale parameter.
209
+ # @param dtype [Symbol] data type of random array.
210
+ # @return [Numo::DFloat | Numo::SFloat]
211
+ def cauchy(shape:, loc: 0.0, scale: 1.0, dtype: :float64)
212
+ x = klass(dtype).new(shape)
213
+ rng.cauchy(x, loc: loc, scale: scale)
214
+ x
215
+ end
216
+
217
+ # Generates array consists of random values according to the Chi-squared distribution.
218
+ #
219
+ # @example
220
+ # require 'numo/random'
221
+ #
222
+ # rng = Numo::Random::Generator.new
223
+ # x = rng.chisquare(shape: 100, df: 2.0)
224
+ #
225
+ # @param shape [Integer | Array<Integer>] size of random array.
226
+ # @param df [Float] degrees of freedom, must be > 0.
227
+ # @param dtype [Symbol] data type of random array.
228
+ # @return [Numo::DFloat | Numo::SFloat]
229
+ def chisquare(shape:, df:, dtype: :float64)
230
+ x = klass(dtype).new(shape)
231
+ rng.chisquare(x, df: df)
232
+ x
233
+ end
234
+
235
+ # Generates array consists of random values according to the F-distribution.
236
+ #
237
+ # @example
238
+ # require 'numo/random'
239
+ #
240
+ # rng = Numo::Random::Generator.new
241
+ # x = rng.f(shape: 100, dfnum: 2.0, dfden: 4.0)
242
+ #
243
+ # @param shape [Integer | Array<Integer>] size of random array.
244
+ # @param dfnum [Float] degrees of freedom in numerator, must be > 0.
245
+ # @param dfden [Float] degrees of freedom in denominator, must be > 0.
246
+ # @param dtype [Symbol] data type of random array.
247
+ # @return [Numo::DFloat | Numo::SFloat]
248
+ def f(shape:, dfnum:, dfden:, dtype: :float64)
249
+ x = klass(dtype).new(shape)
250
+ rng.f(x, dfnum: dfnum, dfden: dfden)
251
+ x
252
+ end
253
+
254
+ # Generates array consists of random values according to a normal (Gaussian) distribution.
255
+ #
256
+ # @example
257
+ # require 'numo/random'
258
+ #
259
+ # rng = Numo::Random::Generator.new
260
+ # x = rng.normal(shape: 100, loc: 0.0, scale: 1.0)
261
+ #
262
+ # @param shape [Integer | Array<Integer>] size of random array.
263
+ # @param loc [Float] location parameter.
264
+ # @param scale [Float] scale parameter.
265
+ # @param dtype [Symbol] data type of random array.
266
+ # @return [Numo::DFloat | Numo::SFloat]
267
+ def normal(shape:, loc: 0.0, scale: 1.0, dtype: :float64)
268
+ x = klass(dtype).new(shape)
269
+ rng.normal(x, loc: loc, scale: scale)
270
+ x
271
+ end
272
+
273
+ # Generates array consists of random values according to a log-normal distribution.
274
+ #
275
+ # @example
276
+ # require 'numo/random'
277
+ #
278
+ # rng = Numo::Random::Generator.new
279
+ # x = rng.lognormal(shape: 100, mean: 0.0, sigma: 1.0)
280
+ #
281
+ # @param shape [Integer | Array<Integer>] size of random array.
282
+ # @param mean [Float] mean of normal distribution.
283
+ # @param sigma [Float] standard deviation of normal distribution.
284
+ # @param dtype [Symbol] data type of random array.
285
+ # @return [Numo::DFloat | Numo::SFloat]
286
+ def lognormal(shape:, mean: 0.0, sigma: 1.0, dtype: :float64)
287
+ x = klass(dtype).new(shape)
288
+ rng.lognormal(x, mean: mean, sigma: sigma)
289
+ x
290
+ end
291
+
292
+ # Generates array consists of random values according to the Student's t-distribution.
293
+ #
294
+ # @example
295
+ # require 'numo/random'
296
+ #
297
+ # rng = Numo::Random::Generator.new
298
+ # x = rng.standard_t(shape: 100, df: 8.0)
299
+ #
300
+ # @param shape [Integer | Array<Integer>] size of random array.
301
+ # @param df [Float] degrees of freedom, must be > 0.
302
+ # @param dtype [Symbol] data type of random array.
303
+ # @return [Numo::DFloat | Numo::SFloat]
304
+ def standard_t(shape:, df:, dtype: :float64)
305
+ x = klass(dtype).new(shape)
306
+ rng.standard_t(x, df: df)
307
+ x
308
+ end
309
+
310
+ private
311
+
312
+ attr_reader :rng
313
+
314
+ def klass(dtype) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
315
+ case dtype.to_sym
316
+ when :int8
317
+ Numo::Int8
318
+ when :int16
319
+ Numo::Int16
320
+ when :int32
321
+ Numo::Int32
322
+ when :int64
323
+ Numo::Int64
324
+ when :uint8
325
+ Numo::UInt8
326
+ when :uint16
327
+ Numo::UInt16
328
+ when :uint32
329
+ Numo::UInt32
330
+ when :uint64
331
+ Numo::UInt64
332
+ when :float32, :sfloat
333
+ Numo::SFloat
334
+ when :float64, :dfloat
335
+ Numo::DFloat
336
+ else
337
+ raise ArgumentError, "wrong dtype is given: #{dtype}"
338
+ end
339
+ end
340
+ end
341
+ end
342
+ end
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Random
5
5
  # The version of Numo::Random you install.
6
- VERSION = '0.1.0'
6
+ VERSION = '0.3.0'
7
7
  end
8
8
  end
data/lib/numo/random.rb CHANGED
@@ -3,182 +3,5 @@
3
3
  require 'numo/narray'
4
4
 
5
5
  require_relative 'random/version'
6
- require_relative 'random/randomext'
7
-
8
- # Ruby/Numo (NUmerical MOdules)
9
- module Numo
10
- # Numo::Random provides random number generation with several distributions for Numo::NArray.
11
- module Random
12
- # Generator is a class that generates random number with several distributions.
13
- #
14
- # @example
15
- # require 'numo/random'
16
- #
17
- # x = Numo::DFloat.new(100)
18
- #
19
- # rng = Numo::Random::Generator.new
20
- # rng.uniform(x, low: -1, high: 2)
21
- class Generator
22
- # Returns random number generation algorithm.
23
- # @return [String]
24
- attr_accessor :algorithm
25
-
26
- # Creates a new random number generator.
27
- #
28
- # @param seed [Integer] random seed used to initialize the random number generator.
29
- # @param algorithm [String] random number generation algorithm.
30
- def initialize(seed: nil, algorithm: 'pcg64') # rubocop:disable Lint/UnusedMethodArgument
31
- @algorithm = 'pcg64'
32
- @rng = PCG64.new(seed: seed)
33
- end
34
-
35
- # Returns the seed of random number generator.
36
- #
37
- # @return [Integer]
38
- def seed
39
- rng.seed
40
- end
41
-
42
- # Sets the seed of random number generator.
43
- #
44
- # @param val [Integer] random seed.
45
- def seed=(val)
46
- rng.seed = val
47
- end
48
-
49
- # Returns random number with uniform distribution in the half-open interval [0, 1).
50
- #
51
- # @example
52
- # require 'numo/random'
53
- #
54
- # rng = Numo::Random::Generator.new
55
- # v = rng.random
56
- #
57
- # @return [Float]
58
- def random
59
- rng.random
60
- end
61
-
62
- # Fills given array with uniformly distributed random values in the interval [low, high).
63
- #
64
- # @example
65
- # require 'numo/random'
66
- #
67
- # x = Numo::DFloat.new(100)
68
- #
69
- # rng = Numo::Random::Generator.new
70
- # rng.uniform(x, low: -1.5, high: 1.5)
71
- #
72
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
73
- # @param low [Float] lower boundary.
74
- # @param high [Float] upper boundary.
75
- def uniform(x, low: 0.0, high: 1.0)
76
- rng.uniform(x, low: low, high: high)
77
- end
78
-
79
- # Fills given array with random values according to the Cauchy (Lorentz) distribution.
80
- #
81
- # @example
82
- # require 'numo/random'
83
- #
84
- # x = Numo::DFloat.new(100)
85
- #
86
- # rng = Numo::Random::Generator.new
87
- # rng.cauchy(x, loc: 0.0, scale: 1.0)
88
- #
89
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
90
- # @param loc [Float] location parameter.
91
- # @param scale [Float] scale parameter.
92
- def cauchy(x, loc: 0.0, scale: 1.0)
93
- rng.cauchy(x, loc: loc, scale: scale)
94
- end
95
-
96
- # Fills given array with random values according to the Chi-squared distribution.
97
- #
98
- # @example
99
- # require 'numo/random'
100
- #
101
- # x = Numo::DFloat.new(100)
102
- #
103
- # rng = Numo::Random::Generator.new
104
- # rng.chisquare(x, df: 2.0)
105
- #
106
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
107
- # @param df [Float] degrees of freedom, must be > 0.
108
- def chisquare(x, df:)
109
- rng.chisquare(x, df: df)
110
- end
111
-
112
- # Fills given array with random values according to the F-distribution.
113
- #
114
- # @example
115
- # require 'numo/random'
116
- #
117
- # x = Numo::DFloat.new(100)
118
- #
119
- # rng = Numo::Random::Generator.new
120
- # rng.f(x, dfnum: 2.0, dfden: 4.0)
121
- #
122
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
123
- # @param dfnum [Float] degrees of freedom in numerator, must be > 0.
124
- # @param dfden [Float] degrees of freedom in denominator, must be > 0.
125
- def f(x, dfnum:, dfden:)
126
- rng.f(x, dfnum: dfnum, dfden: dfden)
127
- end
128
-
129
- # Fills given array with random values according to a normal (Gaussian) distribution.
130
- #
131
- # @example
132
- # require 'numo/random'
133
- #
134
- # x = Numo::DFloat.new(100)
135
- #
136
- # rng = Numo::Random::Generator.new
137
- # rng.normal(x, loc: 0.0, scale: 1.0)
138
- #
139
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
140
- # @param loc [Float] location parameter.
141
- # @param scale [Float] scale parameter.
142
- def normal(x, loc: 0.0, scale: 1.0)
143
- rng.normal(x, loc: loc, scale: scale)
144
- end
145
-
146
- # Fills given array with random values according to a log-normal distribution.
147
- #
148
- # @example
149
- # require 'numo/random'
150
- #
151
- # x = Numo::DFloat.new(100)
152
- #
153
- # rng = Numo::Random::Generator.new
154
- # rng.lognormal(x, mean: 0.0, sigma: 1.0)
155
- #
156
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
157
- # @param mean [Float] mean of normal distribution.
158
- # @param sigma [Float] standard deviation of normal distribution.
159
- def lognormal(x, mean: 0.0, sigma: 1.0)
160
- rng.lognormal(x, mean: mean, sigma: sigma)
161
- end
162
-
163
- # Fills given array with random values according to the Student's t-distribution.
164
- #
165
- # @example
166
- # require 'numo/random'
167
- #
168
- # x = Numo::DFloat.new(100)
169
- #
170
- # rng = Numo::Random::Generator.new
171
- # rng.standard_t(x, df: 8.0)
172
- #
173
- # @param x [Numo::DFloat | Numo::SFloat] array filled with random values.
174
- # @param df [Float] degrees of freedom, must be > 0.
175
- def standard_t(x, df:)
176
- rng.standard_t(x, df: df)
177
- end
178
-
179
- private
180
-
181
- attr_reader :rng
182
- end
183
- end
184
- end
6
+ require_relative 'random/ext'
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.1.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-24 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,14 +37,15 @@ 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
46
46
  - ext/numo/random/src/pcg_uint128.hpp
47
47
  - lib/numo/random.rb
48
+ - lib/numo/random/generator.rb
48
49
  - lib/numo/random/version.rb
49
50
  homepage: https://github.com/yoshoku/numo-random
50
51
  licenses:
@@ -53,7 +54,7 @@ metadata:
53
54
  homepage_uri: https://github.com/yoshoku/numo-random
54
55
  source_code_uri: https://github.com/yoshoku/numo-random
55
56
  changelog_uri: https://github.com/yoshoku/numo-random/blob/main/CHANGELOG.md
56
- documentation_uri: https://www.rubydoc.info/gems/numo-random
57
+ documentation_uri: https://yoshoku.github.io/numo-random/doc/
57
58
  rubygems_mfa_required: 'true'
58
59
  post_install_message:
59
60
  rdoc_options: []