enumerable-statistics 2.0.3 → 2.0.5

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: 85d1034d8bb8062a6d2469ab813518af28acad6b3a4e47e04335e4509f17f830
4
- data.tar.gz: 9886d7f3e791960f499666c4925263a9c163129a9cb8957907ac431d837d5c71
3
+ metadata.gz: 3fa86766eb3c5369422d08bac77705368b0bde5faa216eecd9f78115eb7548b6
4
+ data.tar.gz: 313dc69fe5d6b193278489b576af4bb90679eebf6814c36a2924a1241cd5c8be
5
5
  SHA512:
6
- metadata.gz: 5ccdb91def90bb4740d65bb01bd67fe8bae3932f4e1bb61180862e0b509ab92f7efe4034fcb9855ae0314e009d093c1f2852fe9f3126733f29b68fa706f60a31
7
- data.tar.gz: 59cffac4f18c6dae5dee8da57c222ce1fbb14594ef3e6e43c53d28bf1f606512c4c7f75a585d8b529992df2eb0c173bbd355b5e7b505d63ef0befdf1168aff6c
6
+ metadata.gz: 13fd8a73ae4e83aa85210cbbec1882a2129802aa377f7100ffa72e48ec7df685ba5eff1553cd2ef0b29eddd2b13715769de822adcc881c6d57122212d4c8c13a
7
+ data.tar.gz: d4dc08f32d2d9a43d743e213b2725f0bc41ac7d6d14c68ccecd1b3563d022c8c1c8b60eea682bce554bc7b5425e3c4b552766bb8b3a7faa386164ee8f00303b7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 2.0.5
2
+
3
+ - Add weighted histogram support
4
+
5
+ # 2.0.4
6
+
7
+ - Add `find_min`, `find_max`, `argmin`, `argmax` methods
8
+ - Fix `nbin=:auto` case in `histogram` method
9
+
1
10
  # 2.0.3
2
11
 
3
12
  - Ractor-safe version
@@ -0,0 +1,60 @@
1
+ #include <ruby/ruby.h>
2
+
3
+ static VALUE
4
+ ary_find_max(VALUE ary)
5
+ {
6
+ const long n = RARRAY_LEN(ary);
7
+ if (n == 0) {
8
+ return Qnil;
9
+ }
10
+
11
+ long imax = 0;
12
+ VALUE max = RARRAY_AREF(ary, imax);
13
+
14
+ long i;
15
+ for (i = 1; i < n; ++i) {
16
+ VALUE v = RARRAY_AREF(ary, i);
17
+ if (RTEST(rb_funcall(v, '>', 1, max))) {
18
+ imax = i;
19
+ max = v;
20
+ }
21
+ }
22
+
23
+ return rb_assoc_new(max, LONG2NUM(imax));
24
+ }
25
+
26
+ static VALUE
27
+ ary_find_min(VALUE ary)
28
+ {
29
+ const long n = RARRAY_LEN(ary);
30
+ if (n == 0) {
31
+ return Qnil;
32
+ }
33
+
34
+ long imin = 0;
35
+ VALUE min = RARRAY_AREF(ary, imin);
36
+
37
+ long i;
38
+ for (i = 1; i < n; ++i) {
39
+ VALUE v = RARRAY_AREF(ary, i);
40
+ if (RTEST(rb_funcall(v, '<', 1, min))) {
41
+ imin = i;
42
+ min = v;
43
+ }
44
+ }
45
+
46
+ return rb_assoc_new(min, LONG2NUM(imin));
47
+ }
48
+
49
+ void
50
+ Init_array_extension(void)
51
+ {
52
+ VALUE mEnumerableStatistics = rb_const_get_at(rb_cObject, rb_intern("EnumerableStatistics"));
53
+ VALUE mArrayExtension = rb_const_get_at(mEnumerableStatistics, rb_intern("ArrayExtension"));
54
+
55
+ rb_undef_method(mArrayExtension, "find_max");
56
+ rb_define_method(mArrayExtension, "find_max", ary_find_max, 0);
57
+
58
+ rb_undef_method(mArrayExtension, "find_min");
59
+ rb_define_method(mArrayExtension, "find_min", ary_find_min, 0);
60
+ }
@@ -97,7 +97,7 @@ static ID idPow, idPLUS, idMINUS, idSTAR, idDIV, idGE;
97
97
  static ID id_eqeq_p, id_idiv, id_negate, id_to_f, id_cmp, id_nan_p;
98
98
  static ID id_each, id_real_p, id_sum, id_population, id_closed, id_edge;
99
99
 
100
- static VALUE sym_left, sym_right;
100
+ static VALUE sym_auto, sym_left, sym_right;
101
101
 
102
102
  static VALUE cHistogram;
103
103
 
@@ -2102,50 +2102,61 @@ histogram_edge_bin_index(VALUE edge, VALUE rb_x, int left_p)
2102
2102
  }
2103
2103
 
2104
2104
  static void
2105
- histogram_weights_push_values(VALUE weights, VALUE edge, VALUE values, int left_p)
2105
+ histogram_weights_push_values(VALUE bin_weights, VALUE edge, VALUE values, VALUE weight_array, int left_p)
2106
2106
  {
2107
2107
  VALUE x, cur;
2108
- long i, n, bi;
2108
+ long i, n, bi, one, weighted = 0;
2109
2109
 
2110
2110
  n = RARRAY_LEN(values);
2111
+
2112
+ if (! NIL_P(weight_array)) {
2113
+ assert(RB_TYPE_P(weight_array, T_ARRAY));
2114
+ assert(RARRAY_LEN(weight_array) == n);
2115
+ weighted = 1;
2116
+ }
2117
+
2118
+ one = INT2FIX(1);
2111
2119
  for (i = 0; i < n; ++i) {
2112
2120
  x = RARRAY_AREF(values, i);
2113
2121
 
2122
+ VALUE w;
2123
+ if (weighted) {
2124
+ w = RARRAY_AREF(weight_array, i);
2125
+ if (RB_TYPE_P(w, T_COMPLEX)) {
2126
+ VALUE imag = RCOMPLEX(w)->imag;
2127
+ if (! RTEST(f_zero_p(imag))) {
2128
+ goto type_error;
2129
+ }
2130
+ }
2131
+ else if (rb_obj_is_kind_of(w, rb_cNumeric)) {
2132
+ if (!RTEST(f_real_p(w))) {
2133
+ goto type_error;
2134
+ }
2135
+ }
2136
+ else {
2137
+ goto type_error;
2138
+ }
2139
+ }
2140
+ else {
2141
+ w = one;
2142
+ }
2143
+
2114
2144
  bi = histogram_edge_bin_index(edge, x, left_p);
2115
2145
 
2116
- cur = rb_ary_entry(weights, bi);
2146
+ cur = rb_ary_entry(bin_weights, bi);
2117
2147
  if (NIL_P(cur)) {
2118
- cur = INT2FIX(1);
2148
+ cur = w;
2119
2149
  }
2120
2150
  else {
2121
- cur = rb_funcall(cur, idPLUS, 1, INT2FIX(1));
2151
+ cur = rb_funcall(cur, idPLUS, 1, w);
2122
2152
  }
2123
2153
 
2124
- rb_ary_store(weights, bi, cur);
2125
- }
2126
- }
2127
-
2128
- static int
2129
- opt_closed_left_p(VALUE opts)
2130
- {
2131
- int left_p = 1;
2132
-
2133
- if (!NIL_P(opts)) {
2134
- VALUE closed;
2135
- #ifdef HAVE_RB_GET_KWARGS
2136
- ID kwargs = id_closed;
2137
- rb_get_kwargs(opts, &kwargs, 0, 1, &closed);
2138
- #else
2139
- closed = rb_hash_lookup2(opts, ID2SYM(id_closed), sym_left);
2140
- #endif
2141
- left_p = (closed != sym_right);
2142
- if (left_p && closed != sym_left) {
2143
- rb_raise(rb_eArgError, "invalid value for :closed keyword "
2144
- "(%"PRIsVALUE" for :left or :right)", closed);
2145
- }
2154
+ rb_ary_store(bin_weights, bi, cur);
2146
2155
  }
2156
+ return;
2147
2157
 
2148
- return left_p;
2158
+ type_error:
2159
+ rb_raise(rb_eTypeError, "weight array must have only real numbers");
2149
2160
  }
2150
2161
 
2151
2162
  static inline long
@@ -2270,9 +2281,12 @@ ary_histogram_calculate_edge(VALUE ary, const long nbins, const int left_p)
2270
2281
  }
2271
2282
 
2272
2283
  /* call-seq:
2273
- * ary.histogram(nbins=:auto, closed: :left)
2284
+ * ary.histogram(nbins=:auto, weight: nil, closed: :left)
2274
2285
  *
2275
2286
  * @param [Integer] nbins The approximate number of bins
2287
+ * @params [Array<Numeric>] weight
2288
+ * An optional weight array, that has the same length as the receiver.
2289
+ * `weight[i]` means the weight value of the i-th element in the receiver.
2276
2290
  * @param [:left, :right] closed
2277
2291
  * If :left (the default), the bin interval are left-closed.
2278
2292
  * If :right, the bin interval are right-closed.
@@ -2282,30 +2296,63 @@ ary_histogram_calculate_edge(VALUE ary, const long nbins, const int left_p)
2282
2296
  static VALUE
2283
2297
  ary_histogram(int argc, VALUE *argv, VALUE ary)
2284
2298
  {
2285
- VALUE arg0, opts, edge, weights;
2286
- int left_p;
2287
- long nbins, nweights, i;
2299
+ VALUE arg0, kwargs, edge, bin_weights;
2300
+ long nbins, n_bin_weights, i;
2288
2301
 
2289
- rb_scan_args(argc, argv, "01:", &arg0, &opts);
2290
- if (NIL_P(arg0)) {
2302
+ VALUE weight_array = Qnil;
2303
+ int left_p = 1;
2304
+
2305
+ rb_scan_args(argc, argv, "01:", &arg0, &kwargs);
2306
+ if (NIL_P(arg0) || arg0 == sym_auto) {
2291
2307
  nbins = sturges(RARRAY_LEN(ary));
2292
2308
  }
2293
2309
  else {
2294
2310
  nbins = NUM2LONG(arg0);
2295
2311
  }
2296
- left_p = opt_closed_left_p(opts);
2312
+
2313
+ if (!NIL_P(kwargs)) {
2314
+ enum { kw_weight, kw_closed };
2315
+ static ID kwarg_keys[2];
2316
+ VALUE kwarg_vals[2];
2317
+ VALUE closed;
2318
+
2319
+ if (!kwarg_keys[0]) {
2320
+ kwarg_keys[kw_weight] = rb_intern("weight");
2321
+ kwarg_keys[kw_closed] = rb_intern("closed");
2322
+ }
2323
+
2324
+ rb_get_kwargs(kwargs, kwarg_keys, 0, 2, kwarg_vals);
2325
+
2326
+ weight_array = kwarg_vals[kw_weight];
2327
+ if (weight_array != Qundef) {
2328
+ weight_array = rb_check_convert_type(weight_array, T_ARRAY, "Array", "to_ary");
2329
+ if (RARRAY_LEN(weight_array) != RARRAY_LEN(ary)) {
2330
+ rb_raise(rb_eArgError, "weight array must have the same number of items as the receiver array");
2331
+ }
2332
+ }
2333
+ else {
2334
+ weight_array = Qnil;
2335
+ }
2336
+
2337
+ closed = kwarg_vals[kw_closed];
2338
+ left_p = (closed != sym_right);
2339
+ if (left_p && closed != Qundef && closed != sym_left) {
2340
+ rb_raise(rb_eArgError, "invalid value for :closed keyword "
2341
+ "(%"PRIsVALUE" for :left or :right)", closed);
2342
+ }
2343
+ }
2297
2344
 
2298
2345
  edge = ary_histogram_calculate_edge(ary, nbins, left_p);
2299
2346
 
2300
- nweights = RARRAY_LEN(edge) - 1;
2301
- weights = rb_ary_new_capa(nweights);
2302
- for (i = 0; i < nweights; ++i) {
2303
- rb_ary_store(weights, i, INT2FIX(0));
2347
+ n_bin_weights = RARRAY_LEN(edge) - 1;
2348
+ bin_weights = rb_ary_new_capa(n_bin_weights);
2349
+ for (i = 0; i < n_bin_weights; ++i) {
2350
+ rb_ary_store(bin_weights, i, INT2FIX(0));
2304
2351
  }
2305
2352
 
2306
- histogram_weights_push_values(weights, edge, ary, left_p);
2353
+ histogram_weights_push_values(bin_weights, edge, ary, weight_array, left_p);
2307
2354
 
2308
- return rb_struct_new(cHistogram, edge, weights,
2355
+ return rb_struct_new(cHistogram, edge, bin_weights,
2309
2356
  left_p ? sym_left : sym_right,
2310
2357
  Qfalse);
2311
2358
  }
@@ -2352,6 +2399,9 @@ Init_extension(void)
2352
2399
 
2353
2400
  rb_define_method(rb_cArray, "histogram", ary_histogram, -1);
2354
2401
 
2402
+ void Init_array_extension(void);
2403
+ Init_array_extension();
2404
+
2355
2405
  idPLUS = '+';
2356
2406
  idMINUS = '-';
2357
2407
  idSTAR = '*';
@@ -2371,6 +2421,7 @@ Init_extension(void)
2371
2421
  id_closed = rb_intern("closed");
2372
2422
  id_edge = rb_intern("edge");
2373
2423
 
2424
+ sym_auto = ID2SYM(rb_intern("auto"));
2374
2425
  sym_left = ID2SYM(rb_intern("left"));
2375
2426
  sym_right = ID2SYM(rb_intern("right"));
2376
2427
  }
@@ -1,2 +1,3 @@
1
1
  require_relative "enumerable_statistics/version"
2
+ require_relative "enumerable_statistics/array_ext"
2
3
  require_relative "enumerable_statistics/histogram"
@@ -0,0 +1,37 @@
1
+ module EnumerableStatistics
2
+ module ArrayExtension
3
+ def find_max
4
+ n = size
5
+ return nil if n == 0
6
+
7
+ imax, i = 0, 1
8
+ while i < n
9
+ imax = i if self[i] > self[imax]
10
+ i += 1
11
+ end
12
+ [self[imax], imax]
13
+ end
14
+
15
+ def argmax
16
+ find_max[1]
17
+ end
18
+
19
+ def find_min
20
+ n = size
21
+ return nil if n == 0
22
+
23
+ imin, i = 0, 1
24
+ while i < n
25
+ imin = i if self[i] < self[imax]
26
+ i += 1
27
+ end
28
+ [self[imin], imin]
29
+ end
30
+
31
+ def argmin
32
+ find_min[1]
33
+ end
34
+ end
35
+
36
+ Array.include ArrayExtension
37
+ end
@@ -1,5 +1,5 @@
1
1
  module EnumerableStatistics
2
- VERSION = '2.0.3'
2
+ VERSION = '2.0.5'
3
3
 
4
4
  module Version
5
5
  numbers, TAG = VERSION.split('-', 2)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumerable-statistics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-04 00:00:00.000000000 Z
11
+ date: 2021-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -149,11 +149,13 @@ files:
149
149
  - bin/rspec
150
150
  - bin/setup
151
151
  - enumerable-statistics.gemspec
152
+ - ext/enumerable/statistics/extension/array_ext.c
152
153
  - ext/enumerable/statistics/extension/extconf.rb
153
154
  - ext/enumerable/statistics/extension/statistics.c
154
155
  - images/benchmark.png
155
156
  - lib/enumerable/statistics.rb
156
157
  - lib/enumerable_statistics.rb
158
+ - lib/enumerable_statistics/array_ext.rb
157
159
  - lib/enumerable_statistics/histogram.rb
158
160
  - lib/enumerable_statistics/version.rb
159
161
  - templates/default/layout/html/headers.erb