enumerable-statistics 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9bbba060f2298fae081d18782b237d693663558c
4
+ data.tar.gz: f4b5aa2e3bdaed71938a0bb4fb699f9d04daf3e5
5
+ SHA512:
6
+ metadata.gz: 6b2cc2848db0d8103e09bf770d565be0fcfe360f6dbb45b18ebbbca48027d0f96ae6488a90f3f0ddf3111a82200e14e3b07509f3f7e6cd5ce2fa115350f34224
7
+ data.tar.gz: 2fdc7b8b992a2194aabd6aa82af286d93d03772f385ed1927f2c412eaf2667dd9c9472a65b438c9a1a9660012a014bd879ec16e5dc934ac76d9a543a936539cd
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format Fuubar
@@ -0,0 +1,19 @@
1
+ ---
2
+ language: ruby
3
+
4
+ rvm:
5
+ - ruby-head
6
+ - 2.3.0
7
+ - 2.2.4
8
+ - 2.1
9
+
10
+ before_install:
11
+ - gem update --system
12
+ - gem update bundler
13
+
14
+ install:
15
+ - bundle install
16
+
17
+ script:
18
+ - bundle exec rake clobber compile
19
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in enumerable-statistics.gemspec
4
+ gemspec
@@ -0,0 +1,36 @@
1
+ # Enumerable::Statistics
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/enumerable/statistics`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'enumerable-statistics'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install enumerable-statistics
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/enumerable-statistics.
36
+
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+ require "rspec/core/rake_task"
4
+
5
+ task :default => :spec
6
+
7
+ Rake::ExtensionTask.new('enumerable/statistics/extension')
8
+
9
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "enumerable/statistics"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'enumerable/statistics/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "enumerable-statistics"
8
+ spec.version = Enumerable::Statistics::VERSION
9
+ spec.authors = ["Kenta Murata"]
10
+ spec.email = ["mrkn@mrkn.jp"]
11
+
12
+ spec.summary = %q{Statistics features for Enumerable}
13
+ spec.description = %q{This library provides statistics features for Enumerable}
14
+ spec.homepage = "https://github.com/mrkn/enumerable-statistics"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["ext", "lib"]
20
+ spec.extensions = Dir['ext/**/extconf.rb']
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rake-compiler", "~> 0.9.8"
25
+ spec.add_development_dependency "rspec", "~> 3.4"
26
+ spec.add_development_dependency "fuubar"
27
+ end
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ have_type('struct RRational')
4
+ have_type('struct RComplex')
5
+ create_makefile('enumerable/statistics/extension')
@@ -0,0 +1,765 @@
1
+ #include <ruby/ruby.h>
2
+ #include <ruby/version.h>
3
+ #include <assert.h>
4
+
5
+ #if RUBY_API_VERSION_CODE >= 20400
6
+ /* for 2.4.0 or higher */
7
+ # define HAVE_ARRAY_SUM
8
+ # undef HAVE_RB_FIX_PLUS
9
+ # undef HAVE_RB_RATIONAL_PLUS
10
+ #elif RUBY_API_VERSION_CODE >= 20200
11
+ /* for 2.3.0 and 2.2.0 */
12
+ # undef HAVE_ARRAY_SUM
13
+ # undef HAVE_RB_FIX_PLUS
14
+ # undef HAVE_RB_RATIONAL_PLUS
15
+ #endif
16
+
17
+ #ifndef HAVE_TYPE_STRUCT_RRATIONAL
18
+ struct RRational {
19
+ struct RBasic basic;
20
+ const VALUE num;
21
+ const VALUE den;
22
+ };
23
+ #endif
24
+
25
+ #ifndef RRATIONAL
26
+ # define RRATIONAL(obj) (R_CAST(RRational)(obj))
27
+ #endif
28
+
29
+ #ifndef RRATIONAL_SET_NUM
30
+ # define RRATIONAL_SET_NUM(rat, n) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->num,(n))
31
+ #endif
32
+
33
+ #ifndef RRATIONAL_SET_DEN
34
+ # define RRATIONAL_SET_DEN(rat, d) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->den,(d))
35
+ #endif
36
+
37
+ #ifndef HAVE_TYPE_STRUCT_RCOMPLEX
38
+ struct RComplex {
39
+ struct RBasic basic;
40
+ const VALUE real;
41
+ const VALUE imag;
42
+ };
43
+ #endif
44
+
45
+ #ifndef RCOMPLEX
46
+ # define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
47
+ #endif
48
+
49
+ #ifndef RCOMPLEX_SET_REAL
50
+ # define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->real,(r))
51
+ #endif
52
+
53
+ #ifndef RCOMPLEX_SET_IMAG
54
+ # define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->imag,(i))
55
+ #endif
56
+
57
+ #ifndef MUL_OVERFLOW_SIGNED_INTEGER_P
58
+ # define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
59
+ (a) == 0 ? 0 : \
60
+ (a) == -1 ? (b) < -(max) : \
61
+ (a) > 0 ? \
62
+ ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
63
+ ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
64
+ #endif
65
+
66
+ #ifndef MUL_OVERFLOW_LONG_P
67
+ # define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
68
+ #endif
69
+
70
+ static ID idPow, idPLUS, idMINUS, idSTAR, id_eqeq_p, id_idiv, id_negate, id_to_f, id_cmp;
71
+ static ID id_each, id_real_p;
72
+
73
+ inline static VALUE
74
+ f_add(VALUE x, VALUE y)
75
+ {
76
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
77
+ return x;
78
+ else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
79
+ return y;
80
+ return rb_funcall(x, idPLUS, 1, y);
81
+ }
82
+
83
+ inline static VALUE
84
+ f_sub(VALUE x, VALUE y)
85
+ {
86
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
87
+ return x;
88
+ return rb_funcall(x, idMINUS, 1, y);
89
+ }
90
+
91
+ inline static VALUE
92
+ f_real_p(VALUE x)
93
+ {
94
+ if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM) || RB_TYPE_P(x, T_RATIONAL) || RB_FLOAT_TYPE_P(x))
95
+ return Qtrue;
96
+ else if (RB_TYPE_P(x, T_COMPLEX))
97
+ return Qfalse;
98
+ else
99
+ return rb_funcall(x, id_real_p, 0);
100
+ }
101
+
102
+ #ifndef HAVE_RB_FIX_PLUS
103
+ static VALUE
104
+ complex_new(VALUE klass, VALUE real, VALUE imag)
105
+ {
106
+ assert(!RB_TYPE_P(real, T_COMPLEX));
107
+
108
+ NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0));
109
+
110
+ RCOMPLEX_SET_REAL(obj, real);
111
+ RCOMPLEX_SET_IMAG(obj, imag);
112
+
113
+ return (VALUE)obj;
114
+ }
115
+
116
+ static VALUE
117
+ complex_caonicalize_new(VALUE klass, VALUE real, VALUE imag)
118
+ {
119
+ if (f_real_p(real) && f_real_p(imag))
120
+ return complex_new(klass, real, imag);
121
+ else if (f_real_p(imag)) {
122
+ VALUE new_imag;
123
+
124
+ new_imag = f_add(RCOMPLEX(real)->imag, imag);
125
+
126
+ return complex_new(klass, RCOMPLEX(real)->real, new_imag);
127
+ }
128
+ else {
129
+ VALUE new_real, new_imag;
130
+
131
+ new_real = f_sub(RCOMPLEX(real)->real, RCOMPLEX(imag)->imag);
132
+ new_imag = f_add(RCOMPLEX(real)->imag, RCOMPLEX(imag)->real);
133
+
134
+ return complex_new(klass, new_real, new_imag);
135
+ }
136
+ }
137
+
138
+ static VALUE
139
+ complex_add(VALUE self, VALUE other)
140
+ {
141
+ if (RB_TYPE_P(other, T_COMPLEX)) {
142
+ VALUE real, imag;
143
+
144
+ real = f_add(RCOMPLEX(self)->real, RCOMPLEX(other)->real);
145
+ imag = f_add(RCOMPLEX(self)->imag, RCOMPLEX(other)->imag);
146
+
147
+ return complex_new(CLASS_OF(self), real, imag);
148
+ }
149
+ else if (rb_obj_is_kind_of(other, rb_cNumeric) && RTEST(f_real_p(other))) {
150
+ VALUE real;
151
+
152
+ real = f_add(RCOMPLEX(self)->real, other);
153
+
154
+ return complex_new(CLASS_OF(self), real, RCOMPLEX(other)->imag);
155
+ }
156
+ return rb_num_coerce_bin(self, other, idPLUS);
157
+ }
158
+
159
+ static VALUE
160
+ rb_fix_plus(VALUE x, VALUE y)
161
+ {
162
+ if (FIXNUM_P(y)) {
163
+ long a, b, c;
164
+ VALUE r;
165
+
166
+ a = FIX2LONG(x);
167
+ b = FIX2LONG(y);
168
+ c = a + b;
169
+ r = LONG2NUM(c);
170
+
171
+ return r;
172
+ }
173
+ else if (RB_TYPE_P(y, T_BIGNUM)) {
174
+ return rb_big_plus(y, x);
175
+ }
176
+ else if (RB_FLOAT_TYPE_P(y)) {
177
+ return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
178
+ }
179
+ else if (RB_TYPE_P(y, T_COMPLEX)) {
180
+ return complex_add(y, x);
181
+ }
182
+ else {
183
+ return rb_num_coerce_bin(x, y, '+');
184
+ }
185
+ }
186
+ #endif
187
+
188
+ #ifndef HAVE_RB_RATIONAL_PLUS
189
+ # define ZERO INT2FIX(0)
190
+ # define ONE INT2FIX(1)
191
+
192
+ # define f_boolcast(x) ((x) ? Qtrue : Qfalse)
193
+ #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
194
+
195
+ inline static VALUE
196
+ f_cmp(VALUE x, VALUE y)
197
+ {
198
+ if (FIXNUM_P(x) && FIXNUM_P(y)) {
199
+ long c = FIX2LONG(x) - FIX2LONG(y);
200
+ if (c > 0)
201
+ c = 1;
202
+ else if (c < 0)
203
+ c = -1;
204
+ return INT2FIX(c);
205
+ }
206
+ return rb_funcall(x, id_cmp, 1, y);
207
+ }
208
+
209
+ inline static VALUE
210
+ f_negative_p(VALUE x)
211
+ {
212
+ if (FIXNUM_P(x))
213
+ return f_boolcast(FIX2LONG(x) < 0);
214
+ return rb_funcall(x, '<', 1, ZERO);
215
+ }
216
+
217
+ inline static VALUE
218
+ f_zero_p(VALUE x)
219
+ {
220
+ if (FIXNUM_P(x)) {
221
+ return f_boolcast(FIX2LONG(x) == 0);
222
+ }
223
+ else if (RB_TYPE_P(x, T_BIGNUM)) {
224
+ return Qfalse;
225
+ }
226
+ else if (RB_TYPE_P(x, T_RATIONAL)) {
227
+ VALUE num = RRATIONAL(x)->num;
228
+ return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
229
+ }
230
+ return rb_funcall(x, id_eqeq_p, 1, ZERO);
231
+ }
232
+
233
+ inline static VALUE
234
+ f_negate(VALUE x)
235
+ {
236
+ return rb_funcall(x, id_negate, 0);
237
+ }
238
+
239
+ inline static VALUE
240
+ f_to_f(VALUE x)
241
+ {
242
+ if (RB_TYPE_P(x, T_STRING))
243
+ return DBL2NUM(rb_str_to_dbl(x, 0));
244
+ return rb_funcall(x, id_to_f, 0);
245
+ }
246
+
247
+ inline static long
248
+ i_gcd(long x, long y)
249
+ {
250
+ if (x < 0)
251
+ x = -x;
252
+ if (y < 0)
253
+ y = -y;
254
+
255
+ if (x == 0)
256
+ return y;
257
+ if (y == 0)
258
+ return x;
259
+
260
+ while (x > 0) {
261
+ long t = x;
262
+ x = y % x;
263
+ y = t;
264
+ }
265
+ return y;
266
+ }
267
+
268
+ inline static VALUE
269
+ f_imul(long a, long b)
270
+ {
271
+ VALUE r;
272
+
273
+ if (a == 0 || b == 0)
274
+ return ZERO;
275
+ else if (a == 1)
276
+ return LONG2NUM(b);
277
+ else if (b == 1)
278
+ return LONG2NUM(a);
279
+
280
+ if (MUL_OVERFLOW_LONG_P(a, b))
281
+ r = rb_big_mul(rb_int2big(a), rb_int2big(b));
282
+ else
283
+ r = LONG2NUM(a * b);
284
+
285
+ return r;
286
+ }
287
+
288
+ inline static VALUE
289
+ f_mul(VALUE x, VALUE y)
290
+ {
291
+ if (FIXNUM_P(y)) {
292
+ long iy = FIX2LONG(y);
293
+ if (iy == 0) {
294
+ if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
295
+ return ZERO;
296
+ }
297
+ else if (iy == 1)
298
+ return x;
299
+ }
300
+ if (FIXNUM_P(x)) {
301
+ long ix = FIX2LONG(x);
302
+ if (ix == 0) {
303
+ if (FIXNUM_P(y) || RB_TYPE_P(y, T_BIGNUM))
304
+ return ZERO;
305
+ }
306
+ else if (ix == 1)
307
+ return y;
308
+ }
309
+ return rb_funcall(x, '*', 1, y);
310
+ }
311
+
312
+ inline static VALUE
313
+ f_idiv(VALUE x, VALUE y)
314
+ {
315
+ return rb_funcall(x, id_idiv, 1, y);
316
+ }
317
+
318
+ inline static VALUE
319
+ f_mod(VALUE x, VALUE y)
320
+ {
321
+ return rb_funcall(x, '%', 1, y);
322
+ }
323
+
324
+ inline static VALUE
325
+ f_gcd_normal(VALUE x, VALUE y)
326
+ {
327
+ VALUE z;
328
+
329
+ if (FIXNUM_P(x) && FIXNUM_P(y))
330
+ return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
331
+
332
+ if (f_negative_p(x))
333
+ x = f_negate(x);
334
+ if (f_negative_p(y))
335
+ y = f_negate(y);
336
+
337
+ if (f_zero_p(x))
338
+ return y;
339
+ if (f_zero_p(y))
340
+ return x;
341
+
342
+ for (;;) {
343
+ if (FIXNUM_P(x)) {
344
+ if (FIX2LONG(x) == 0)
345
+ return y;
346
+ if (FIXNUM_P(y))
347
+ return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
348
+ }
349
+ z = x;
350
+ x = f_mod(y, x);
351
+ y = z;
352
+ }
353
+ /* NOTREACHED */
354
+ }
355
+
356
+ inline static VALUE
357
+ f_gcd(VALUE x, VALUE y)
358
+ {
359
+ return f_gcd_normal(x, y);
360
+ }
361
+
362
+ inline static VALUE
363
+ nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
364
+ {
365
+ NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0));
366
+ RRATIONAL_SET_NUM(obj, num);
367
+ RRATIONAL_SET_DEN(obj, den);
368
+ return (VALUE)obj;
369
+ }
370
+
371
+ inline static VALUE
372
+ nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
373
+ {
374
+ switch (FIX2INT(f_cmp(den, ZERO))) {
375
+ case -1:
376
+ num = f_negate(num);
377
+ den = f_negate(den);
378
+ break;
379
+ case 0:
380
+ rb_raise_zerodiv();
381
+ break;
382
+ }
383
+
384
+ return nurat_s_new_internal(klass, num, den);
385
+ }
386
+
387
+ inline static VALUE
388
+ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
389
+ {
390
+ VALUE num, den;
391
+
392
+ if (FIXNUM_P(anum) && FIXNUM_P(aden) && FIXNUM_P(bnum) && FIXNUM_P(bden)) {
393
+ long an = FIX2LONG(anum);
394
+ long ad = FIX2LONG(aden);
395
+ long bn = FIX2LONG(bnum);
396
+ long bd = FIX2LONG(bden);
397
+ long ig = i_gcd(ad, bd);
398
+
399
+ VALUE g = LONG2NUM(ig);
400
+ VALUE a = f_imul(an, bd / ig);
401
+ VALUE b = f_imul(bn, ad / ig);
402
+
403
+ VALUE c;
404
+ if (k == '+')
405
+ c = f_add(a, b);
406
+ else
407
+ c = f_sub(a, b);
408
+
409
+ b = f_idiv(aden, g);
410
+ g = f_gcd(c, g);
411
+ num = f_idiv(c, g);
412
+ a = f_idiv(bden, g);
413
+ den = f_mul(a, b);
414
+ }
415
+ else {
416
+ VALUE g = f_gcd(aden, bden);
417
+ VALUE a = f_mul(anum, f_idiv(bden, g));
418
+ VALUE b = f_mul(bnum, f_idiv(aden, g));
419
+
420
+ VALUE c;
421
+ if (k == '+')
422
+ c = f_add(a, b);
423
+ else
424
+ c = f_sub(a, b);
425
+
426
+ b = f_idiv(aden, g);
427
+ g = f_gcd(c, g);
428
+ num = f_idiv(c, g);
429
+ a = f_idiv(bden, g);
430
+ den = f_mul(a, b);
431
+ }
432
+
433
+ return nurat_s_canonicalize_internal_no_reduce(CLASS_OF(self), num, den);
434
+ }
435
+
436
+ static VALUE
437
+ rb_rational_plus(VALUE self, VALUE other)
438
+ {
439
+ if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
440
+ VALUE num = RRATIONAL(self)->num;
441
+ VALUE den = RRATIONAL(self)->den;
442
+
443
+ return f_addsub(self, num, den, other, ONE, idPLUS);
444
+ }
445
+ else if (RB_TYPE_P(other, T_FLOAT)) {
446
+ return f_add(f_to_f(self), other);
447
+ }
448
+ else if (RB_TYPE_P(other, T_RATIONAL)) {
449
+ VALUE anum = RRATIONAL(self)->num;
450
+ VALUE aden = RRATIONAL(self)->den;
451
+ VALUE bnum = RRATIONAL(other)->num;
452
+ VALUE bden = RRATIONAL(other)->den;
453
+
454
+ return f_addsub(self, anum, aden, bnum, bden, '+');
455
+ }
456
+ else {
457
+ return rb_num_coerce_bin(self, other, idPLUS);
458
+ }
459
+ }
460
+ #endif
461
+
462
+ #ifndef HAVE_ARRAY_SUM
463
+ static VALUE
464
+ ary_sum(int argc, VALUE* argv, VALUE ary)
465
+ {
466
+ VALUE e, v, r;
467
+ long i, n;
468
+ int block_given;
469
+
470
+ if (rb_scan_args(argc, argv, "01", &v) == 0)
471
+ v = LONG2FIX(0);
472
+
473
+ block_given = rb_block_given_p();
474
+
475
+ if (RARRAY_LEN(ary) == 0)
476
+ return v;
477
+
478
+ n = 0;
479
+ r = Qundef;
480
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
481
+ e = RARRAY_AREF(ary, i);
482
+ if (block_given)
483
+ e = rb_yield(e);
484
+ if (FIXNUM_P(e)) {
485
+ n += FIX2LONG(e); /* should not overflow long type */
486
+ if (!FIXABLE(n)) {
487
+ v = rb_big_plus(LONG2NUM(n), v);
488
+ n = 0;
489
+ }
490
+ }
491
+ else if (RB_TYPE_P(e, T_BIGNUM))
492
+ v = rb_big_plus(e, v);
493
+ else if (RB_TYPE_P(e, T_RATIONAL)) {
494
+ if (r == Qundef)
495
+ r = e;
496
+ else
497
+ r = rb_rational_plus(r, e);
498
+ }
499
+ else
500
+ goto not_exact;
501
+ }
502
+
503
+ if (n != 0)
504
+ v = rb_fix_plus(LONG2FIX(n), v);
505
+ if (r != Qundef)
506
+ v = rb_rational_plus(r, v);
507
+ return v;
508
+
509
+ not_exact:
510
+ if (n != 0)
511
+ v = rb_fix_plus(LONG2FIX(n), v);
512
+ if (r != Qundef)
513
+ v = rb_rational_plus(r, v);
514
+
515
+ if (RB_FLOAT_TYPE_P(e)) {
516
+ /* Kahan's compensated summation algorithm */
517
+ double f, c;
518
+
519
+ f = NUM2DBL(v);
520
+ c = 0.0;
521
+ goto has_float_value;
522
+ for (; i < RARRAY_LEN(ary); i++) {
523
+ double x, y, t;
524
+ e = RARRAY_AREF(ary, i);
525
+ if (block_given)
526
+ e = rb_yield(e);
527
+ if (RB_FLOAT_TYPE_P(e))
528
+ has_float_value:
529
+ x = RFLOAT_VALUE(e);
530
+ else if (FIXNUM_P(e))
531
+ x = FIX2LONG(e);
532
+ else if (RB_TYPE_P(e, T_BIGNUM))
533
+ x = rb_big2dbl(e);
534
+ else if (RB_TYPE_P(e, T_RATIONAL))
535
+ x = rb_num2dbl(e);
536
+ else
537
+ goto not_float;
538
+
539
+ y = x - c;
540
+ t = f + y;
541
+ c = (t - f) - y;
542
+ f = t;
543
+ }
544
+ return DBL2NUM(f);
545
+
546
+ not_float:
547
+ v = DBL2NUM(f);
548
+ }
549
+
550
+ goto has_some_value;
551
+ for (; i < RARRAY_LEN(ary); i++) {
552
+ e = RARRAY_AREF(ary, i);
553
+ if (block_given)
554
+ e = rb_yield(e);
555
+ has_some_value:
556
+ v = rb_funcall(v, idPLUS, 1, e);
557
+ }
558
+
559
+ return v;
560
+ }
561
+ #endif
562
+
563
+ #define ENUM_WANT_SVALUE() do { \
564
+ e = rb_enum_values_pack(argc, argv); \
565
+ } while (0)
566
+
567
+ struct enum_sum_memo {
568
+ VALUE v, r;
569
+ long n;
570
+ double f, c;
571
+ int block_given;
572
+ int float_value;
573
+ };
574
+
575
+ static VALUE
576
+ enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(e, args))
577
+ {
578
+ struct enum_sum_memo *memo = (struct enum_sum_memo *)args;
579
+ long n = memo->n;
580
+ VALUE v = memo->v;
581
+ VALUE r = memo->r;
582
+ double f = memo->f;
583
+ double c = memo->c;
584
+
585
+ ENUM_WANT_SVALUE();
586
+
587
+ if (memo->block_given)
588
+ e = rb_yield(e);
589
+
590
+ if (memo->float_value)
591
+ goto float_value;
592
+
593
+ if (FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || RB_TYPE_P(v, T_RATIONAL)) {
594
+ if (FIXNUM_P(e)) {
595
+ n += FIX2LONG(e); /* should not overflow long type */
596
+ if (!FIXABLE(n)) {
597
+ v = rb_big_plus(LONG2NUM(n), v);
598
+ n = 0;
599
+ }
600
+ }
601
+ else if (RB_TYPE_P(e, T_BIGNUM))
602
+ v = rb_big_plus(e, v);
603
+ else if (RB_TYPE_P(e, T_RATIONAL)) {
604
+ if (r == Qundef)
605
+ r = e;
606
+ else
607
+ r = rb_rational_plus(r, e);
608
+ }
609
+ else {
610
+ if (n != 0) {
611
+ v = rb_fix_plus(LONG2FIX(n), v);
612
+ n = 0;
613
+ }
614
+ if (r != Qundef) {
615
+ v = rb_rational_plus(r, v);
616
+ r = Qundef;
617
+ }
618
+ if (RB_FLOAT_TYPE_P(e)) {
619
+ f = NUM2DBL(v);
620
+ c = 0.0;
621
+ memo->float_value = 1;
622
+ goto float_value;
623
+ }
624
+ else
625
+ goto some_value;
626
+ }
627
+ }
628
+ else if (RB_FLOAT_TYPE_P(v)) {
629
+ /* Kahan's compensated summation algorithm */
630
+ double x, y, t;
631
+
632
+ float_value:
633
+ if (RB_FLOAT_TYPE_P(e))
634
+ x = RFLOAT_VALUE(e);
635
+ else if (FIXNUM_P(e))
636
+ x = FIX2LONG(e);
637
+ else if (RB_TYPE_P(e, T_BIGNUM))
638
+ x = rb_big2dbl(e);
639
+ else if (RB_TYPE_P(e, T_RATIONAL))
640
+ x = rb_num2dbl(e);
641
+ else {
642
+ v = DBL2NUM(f);
643
+ memo->float_value = 0;
644
+ goto some_value;
645
+ }
646
+
647
+ y = x - c;
648
+ t = f + y;
649
+ c = (t - f) - y;
650
+ f = t;
651
+ }
652
+ else {
653
+ some_value:
654
+ v = rb_funcall(v, idPLUS, 1, e);
655
+ }
656
+
657
+ memo->v = v;
658
+ memo->n = n;
659
+ memo->r = r;
660
+ memo->f = f;
661
+ memo->c = c;
662
+
663
+ return Qnil;
664
+ }
665
+
666
+ static VALUE
667
+ enum_stat_sum(int argc, VALUE* argv, VALUE obj)
668
+ {
669
+ struct enum_sum_memo memo;
670
+
671
+ if (rb_scan_args(argc, argv, "01", &memo.v) == 0)
672
+ memo.v = LONG2FIX(0);
673
+
674
+ memo.block_given = rb_block_given_p();
675
+
676
+ memo.n = 0;
677
+ memo.r = Qundef;
678
+
679
+ if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
680
+ memo.f = RFLOAT_VALUE(memo.v);
681
+ memo.c = 0.0;
682
+ }
683
+
684
+ rb_block_call(obj, id_each, 0, 0, enum_sum_iter_i, (VALUE)&memo);
685
+
686
+ if (memo.float_value) {
687
+ return DBL2NUM(memo.f);
688
+ }
689
+ else {
690
+ if (memo.n != 0)
691
+ memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
692
+ if (memo.r != Qundef)
693
+ memo.v = rb_rational_plus(memo.r, memo.v);
694
+ return memo.v;
695
+ }
696
+ }
697
+
698
+ static VALUE
699
+ enum_stat_mean_variance(VALUE obj)
700
+ {
701
+ return rb_assoc_new(INT2FIX(0), INT2FIX(0));
702
+ }
703
+
704
+ static VALUE
705
+ enum_stat_mean(VALUE obj)
706
+ {
707
+ VALUE ary = enum_stat_mean_variance(obj);
708
+ return RARRAY_AREF(ary, 0);
709
+ }
710
+
711
+ static VALUE
712
+ enum_stat_variance(VALUE obj)
713
+ {
714
+ VALUE ary = enum_stat_mean_variance(obj);
715
+ return RARRAY_AREF(ary, 1);
716
+ }
717
+
718
+ static VALUE
719
+ enum_stat_mean_stddev(VALUE obj)
720
+ {
721
+ VALUE ary = enum_stat_mean_variance(obj);
722
+ VALUE var = RARRAY_AREF(ary, 1);
723
+ VALUE stddev = rb_funcall(var, idPow, 1, DBL2NUM(0.5));
724
+ RARRAY_ASET(ary, 1, stddev);
725
+ return ary;
726
+ }
727
+
728
+ static VALUE
729
+ enum_stat_stddev(VALUE obj)
730
+ {
731
+ VALUE ary = enum_stat_mean_stddev(obj);
732
+ return RARRAY_AREF(ary, 1);
733
+ }
734
+
735
+ void
736
+ Init_extension(void)
737
+ {
738
+ rb_define_method(rb_mEnumerable, "sum", enum_stat_sum, -1);
739
+
740
+ #if 0
741
+ rb_define_method(rb_mEnumerable, "mean_variance", enum_stat_mean_variance, 0);
742
+ rb_define_method(rb_mEnumerable, "mean", enum_stat_mean, 0);
743
+ rb_define_alias(rb_mEnumerable, "average", "mean");
744
+ rb_define_method(rb_mEnumerable, "variance", enum_stat_variance, 0);
745
+ rb_define_alias(rb_mEnumerable, "var", "variance");
746
+ rb_define_method(rb_mEnumerable, "mean_stddev", enum_stat_mean_stddev, 0);
747
+ rb_define_method(rb_mEnumerable, "stddev", enum_stat_stddev, 0);
748
+ #endif
749
+
750
+ #ifndef HAVE_ARRAY_SUM
751
+ rb_define_method(rb_cArray, "sum", ary_sum, -1);
752
+ #endif
753
+
754
+ idPLUS = '+';
755
+ idMINUS = '-';
756
+ idSTAR = '*';
757
+ idPow = rb_intern("**");
758
+ id_eqeq_p = rb_intern("==");
759
+ id_idiv = rb_intern("div");
760
+ id_negate = rb_intern("-@");
761
+ id_to_f = rb_intern("to_f");
762
+ id_cmp = rb_intern("<=>");
763
+ id_each = rb_intern("each");
764
+ id_real_p = rb_intern("real?");
765
+ }
@@ -0,0 +1,2 @@
1
+ require "enumerable/statistics/extension"
2
+ require "enumerable/statistics/version"
@@ -0,0 +1,5 @@
1
+ module Enumerable
2
+ module Statistics
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumerable-statistics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kenta Murata
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.8
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.8
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fuubar
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: This library provides statistics features for Enumerable
84
+ email:
85
+ - mrkn@mrkn.jp
86
+ executables: []
87
+ extensions:
88
+ - ext/enumerable/statistics/extension/extconf.rb
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/rspec
99
+ - bin/setup
100
+ - enumerable-statistics.gemspec
101
+ - ext/enumerable/statistics/extension/extconf.rb
102
+ - ext/enumerable/statistics/extension/statistics.c
103
+ - lib/enumerable/statistics.rb
104
+ - lib/enumerable/statistics/version.rb
105
+ homepage: https://github.com/mrkn/enumerable-statistics
106
+ licenses: []
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - ext
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.6.3
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Statistics features for Enumerable
129
+ test_files: []