enumerable-statistics 2.0.1 → 2.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +64 -0
- data/CHANGELOG.md +32 -0
- data/Rakefile +9 -0
- data/enumerable-statistics.gemspec +2 -1
- data/ext/enumerable/statistics/extension/array_ext.c +60 -0
- data/ext/enumerable/statistics/extension/statistics.c +349 -133
- data/lib/enumerable_statistics/array_ext.rb +37 -0
- data/lib/enumerable_statistics/histogram.rb +2 -1
- data/lib/enumerable_statistics/version.rb +1 -1
- data/lib/enumerable_statistics.rb +1 -0
- metadata +22 -8
- data/.travis.yml +0 -32
- data/ext/-bench-/extconf.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 815b5f1b539e61935a709b7f859aeae73dd379959d8aa5e56551b650d20c7abc
|
4
|
+
data.tar.gz: be09795e4203a023e23a20b99c2bdd051ace5292ea7c67d6000cda0c3ed7c822
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b2af05ed047b86529af90b7c18091d04055b1ded985614a6e4c7422706bd1453bb993a3b84e4b2821c8ff725efc62edb09505e1f3e59865faa71921296cd45d
|
7
|
+
data.tar.gz: 97d2f6044a4ebb1a1ca4d068f999192c3255bf8213262c6d038007404be79ca36cc6eaeefab0830e0aa45a658d4e083024ad3a116040ee75e9acbda31984b69a
|
@@ -0,0 +1,64 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
- push
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
cruby:
|
8
|
+
name: Test
|
9
|
+
runs-on: ${{ matrix.os }}
|
10
|
+
|
11
|
+
strategy:
|
12
|
+
fail-fast: false
|
13
|
+
matrix:
|
14
|
+
os:
|
15
|
+
- ubuntu-latest
|
16
|
+
- macos-latest
|
17
|
+
- windows-latest
|
18
|
+
ruby:
|
19
|
+
- 3.3
|
20
|
+
- 3.2
|
21
|
+
- 3.1
|
22
|
+
- 3.0
|
23
|
+
- 2.7
|
24
|
+
- 2.6
|
25
|
+
- 2.5
|
26
|
+
- 2.4
|
27
|
+
- debug
|
28
|
+
exclude:
|
29
|
+
- os: macos-latest
|
30
|
+
ruby: 2.5
|
31
|
+
- os: macos-latest
|
32
|
+
ruby: 2.4
|
33
|
+
- os: windows-latest
|
34
|
+
ruby: debug
|
35
|
+
|
36
|
+
steps:
|
37
|
+
- uses: actions/checkout@v2
|
38
|
+
|
39
|
+
- name: Setup Ruby
|
40
|
+
uses: ruby/setup-ruby@v1
|
41
|
+
with:
|
42
|
+
ruby-version: ${{ matrix.ruby }}
|
43
|
+
|
44
|
+
- name: Detect installable bundler version
|
45
|
+
run: |
|
46
|
+
case "${{ matrix.ruby }}" in
|
47
|
+
2.7|2.6) bundler_version="2.4.22" ;;
|
48
|
+
2.5|2.4) bundler_version="2.3.27" ;;
|
49
|
+
*) bundler_version="" ;;
|
50
|
+
esac
|
51
|
+
echo "bundler_version=$bundler_version" >> $GITHUB_ENV
|
52
|
+
shell: bash
|
53
|
+
|
54
|
+
- run: gem install bundler${bundler_version:+ -v $bundler_version}
|
55
|
+
shell: bash
|
56
|
+
|
57
|
+
- run: bundle install
|
58
|
+
|
59
|
+
- run: rake --trace compile
|
60
|
+
|
61
|
+
- run: rake build
|
62
|
+
- run: gem install pkg/*gem
|
63
|
+
|
64
|
+
- run: rake
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
# 2.0.8
|
2
|
+
|
3
|
+
- Prohibit the use of both `nbins` and `edges` kwargs simultaneously in the `histogram` method.
|
4
|
+
- Support `skip_na` kwarg in `sum` and related methods.
|
5
|
+
- Support Ruby 3.4+.
|
6
|
+
|
7
|
+
# 2.0.7
|
8
|
+
|
9
|
+
- Fix the bug of histogram with bin range that is smaller than value range
|
10
|
+
|
11
|
+
# 2.0.6
|
12
|
+
|
13
|
+
- Add edges parameter in histogram
|
14
|
+
- Rename parameter in histogram to fix typo: `weight` to `weights`
|
15
|
+
|
16
|
+
# 2.0.5
|
17
|
+
|
18
|
+
- Add weighted histogram support
|
19
|
+
|
20
|
+
# 2.0.4
|
21
|
+
|
22
|
+
- Add `find_min`, `find_max`, `argmin`, `argmax` methods
|
23
|
+
- Fix `nbin=:auto` case in `histogram` method
|
24
|
+
|
25
|
+
# 2.0.3
|
26
|
+
|
27
|
+
- Ractor-safe version
|
28
|
+
|
29
|
+
# 2.0.2
|
30
|
+
|
31
|
+
- Support Ruby 3.0
|
32
|
+
|
1
33
|
# 2.0.1
|
2
34
|
|
3
35
|
- Fix a bug of `histogram` (#9)
|
data/Rakefile
CHANGED
@@ -8,7 +8,14 @@ Rake::ExtensionTask.new('enumerable/statistics/extension')
|
|
8
8
|
|
9
9
|
directory 'lib/enumerable/statistics'
|
10
10
|
|
11
|
+
desc "Run test"
|
12
|
+
task :test do
|
13
|
+
ruby("test/run-test.rb")
|
14
|
+
end
|
15
|
+
task :test => :compile
|
16
|
+
|
11
17
|
RSpec::Core::RakeTask.new(:spec)
|
18
|
+
task :spec => :compile
|
12
19
|
|
13
20
|
task :bench do
|
14
21
|
puts "# sum\n"
|
@@ -20,3 +27,5 @@ task :bench do
|
|
20
27
|
puts "# variance\n"
|
21
28
|
system('benchmark-driver bench/variance.yml')
|
22
29
|
end
|
30
|
+
|
31
|
+
task default: [:test, :spec]
|
@@ -27,10 +27,11 @@ Gem::Specification.new do |spec|
|
|
27
27
|
|
28
28
|
spec.required_ruby_version = '>= 2.4'
|
29
29
|
|
30
|
-
spec.add_development_dependency "bundler"
|
30
|
+
spec.add_development_dependency "bundler"
|
31
31
|
spec.add_development_dependency "rake"
|
32
32
|
spec.add_development_dependency "rake-compiler", ">= 0.9.8"
|
33
33
|
spec.add_development_dependency "rspec", ">= 3.4"
|
34
|
+
spec.add_development_dependency "test-unit"
|
34
35
|
spec.add_development_dependency "fuubar"
|
35
36
|
spec.add_development_dependency "yard"
|
36
37
|
spec.add_development_dependency "benchmark-driver"
|
@@ -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
|
+
}
|
@@ -44,7 +44,7 @@ struct RRational {
|
|
44
44
|
#endif
|
45
45
|
|
46
46
|
#ifndef RRATIONAL
|
47
|
-
# define RRATIONAL(obj) (
|
47
|
+
# define RRATIONAL(obj) ((struct RRational *)(obj))
|
48
48
|
#endif
|
49
49
|
|
50
50
|
#ifndef RRATIONAL_SET_NUM
|
@@ -64,7 +64,7 @@ struct RComplex {
|
|
64
64
|
#endif
|
65
65
|
|
66
66
|
#ifndef RCOMPLEX
|
67
|
-
# define RCOMPLEX(obj) (
|
67
|
+
# define RCOMPLEX(obj) ((struct RComplex *)(obj))
|
68
68
|
#endif
|
69
69
|
|
70
70
|
#ifndef RCOMPLEX_SET_REAL
|
@@ -96,11 +96,14 @@ static VALUE half_in_rational;
|
|
96
96
|
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
|
+
static ID id_skip_na;
|
99
100
|
|
100
|
-
static VALUE sym_left, sym_right;
|
101
|
+
static VALUE sym_auto, sym_left, sym_right, sym_sturges;
|
101
102
|
|
102
103
|
static VALUE cHistogram;
|
103
104
|
|
105
|
+
static VALUE orig_enum_sum, orig_ary_sum;
|
106
|
+
|
104
107
|
inline static VALUE
|
105
108
|
f_add(VALUE x, VALUE y)
|
106
109
|
{
|
@@ -135,7 +138,7 @@ complex_new(VALUE klass, VALUE real, VALUE imag)
|
|
135
138
|
{
|
136
139
|
assert(!RB_TYPE_P(real, T_COMPLEX));
|
137
140
|
|
138
|
-
|
141
|
+
VALUE obj = rb_get_alloc_func(klass)(klass);
|
139
142
|
|
140
143
|
RCOMPLEX_SET_REAL(obj, real);
|
141
144
|
RCOMPLEX_SET_IMAG(obj, imag);
|
@@ -535,9 +538,11 @@ f_gcd(VALUE x, VALUE y)
|
|
535
538
|
inline static VALUE
|
536
539
|
nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
|
537
540
|
{
|
538
|
-
|
541
|
+
VALUE obj = rb_get_alloc_func(klass)(klass);
|
542
|
+
|
539
543
|
RRATIONAL_SET_NUM(obj, num);
|
540
544
|
RRATIONAL_SET_DEN(obj, den);
|
545
|
+
|
541
546
|
return (VALUE)obj;
|
542
547
|
}
|
543
548
|
|
@@ -632,39 +637,67 @@ rb_rational_plus(VALUE self, VALUE other)
|
|
632
637
|
}
|
633
638
|
#endif
|
634
639
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
640
|
+
static inline int
|
641
|
+
is_na(VALUE v)
|
642
|
+
{
|
643
|
+
if (NIL_P(v))
|
644
|
+
return 1;
|
645
|
+
|
646
|
+
if (RB_FLOAT_TYPE_P(v) && isnan(RFLOAT_VALUE(v)))
|
647
|
+
return 1;
|
648
|
+
|
649
|
+
if (rb_respond_to(v, id_nan_p) && RTEST(rb_funcall(v, id_nan_p, 0)))
|
650
|
+
return 1;
|
651
|
+
|
652
|
+
return 0;
|
653
|
+
}
|
654
|
+
|
655
|
+
static int opt_skip_na(VALUE opts)
|
656
|
+
{
|
657
|
+
VALUE skip_na = Qfalse;
|
658
|
+
|
659
|
+
if (!NIL_P(opts)) {
|
660
|
+
#ifdef HAVE_RB_GET_KWARGS
|
661
|
+
ID kwargs = id_skip_na;
|
662
|
+
rb_get_kwargs(opts, &kwargs, 0, 1, &skip_na);
|
663
|
+
#else
|
664
|
+
VALUE val = rb_hash_aref(opts, ID2SYM(id_skip_na));
|
665
|
+
skip_na = NIL_P(val) ? skip_na : val;
|
666
|
+
#endif
|
667
|
+
}
|
668
|
+
|
669
|
+
return RTEST(skip_na);
|
670
|
+
}
|
671
|
+
|
672
|
+
VALUE
|
673
|
+
ary_calculate_sum(VALUE ary, VALUE init, int skip_na, long *na_count_out)
|
649
674
|
{
|
650
675
|
VALUE e, v, r;
|
651
676
|
long i, n;
|
652
677
|
int block_given;
|
653
|
-
|
654
|
-
if (rb_scan_args(argc, argv, "01", &v) == 0)
|
655
|
-
v = LONG2FIX(0);
|
678
|
+
long na_count = 0;
|
656
679
|
|
657
680
|
block_given = rb_block_given_p();
|
658
681
|
|
659
|
-
if (RARRAY_LEN(ary) == 0)
|
660
|
-
|
682
|
+
if (RARRAY_LEN(ary) == 0) {
|
683
|
+
if (na_count_out != NULL) {
|
684
|
+
*na_count_out = 0;
|
685
|
+
}
|
686
|
+
return init;
|
687
|
+
}
|
661
688
|
|
662
689
|
n = 0;
|
663
690
|
r = Qundef;
|
691
|
+
v = init;
|
664
692
|
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
665
693
|
e = RARRAY_AREF(ary, i);
|
666
694
|
if (block_given)
|
667
695
|
e = rb_yield(e);
|
696
|
+
if (skip_na && is_na(e)) {
|
697
|
+
++na_count;
|
698
|
+
continue;
|
699
|
+
}
|
700
|
+
|
668
701
|
if (FIXNUM_P(e)) {
|
669
702
|
n += FIX2LONG(e); /* should not overflow long type */
|
670
703
|
if (!FIXABLE(n)) {
|
@@ -688,7 +721,7 @@ ary_sum(int argc, VALUE* argv, VALUE ary)
|
|
688
721
|
v = rb_fix_plus(LONG2FIX(n), v);
|
689
722
|
if (r != Qundef)
|
690
723
|
v = rb_rational_plus(r, v);
|
691
|
-
|
724
|
+
goto finish;
|
692
725
|
|
693
726
|
not_exact:
|
694
727
|
if (n != 0)
|
@@ -708,6 +741,11 @@ not_exact:
|
|
708
741
|
e = RARRAY_AREF(ary, i);
|
709
742
|
if (block_given)
|
710
743
|
e = rb_yield(e);
|
744
|
+
if (skip_na && is_na(e)) {
|
745
|
+
++na_count;
|
746
|
+
continue;
|
747
|
+
}
|
748
|
+
|
711
749
|
if (RB_FLOAT_TYPE_P(e))
|
712
750
|
has_float_value:
|
713
751
|
x = RFLOAT_VALUE(e);
|
@@ -725,7 +763,9 @@ not_exact:
|
|
725
763
|
c = (t - f) - y;
|
726
764
|
f = t;
|
727
765
|
}
|
728
|
-
|
766
|
+
|
767
|
+
v = DBL2NUM(f);
|
768
|
+
goto finish;
|
729
769
|
|
730
770
|
not_float:
|
731
771
|
v = DBL2NUM(f);
|
@@ -736,13 +776,53 @@ not_exact:
|
|
736
776
|
e = RARRAY_AREF(ary, i);
|
737
777
|
if (block_given)
|
738
778
|
e = rb_yield(e);
|
779
|
+
if (skip_na && is_na(e)) {
|
780
|
+
++na_count;
|
781
|
+
continue;
|
782
|
+
}
|
739
783
|
has_some_value:
|
740
784
|
v = rb_funcall(v, idPLUS, 1, e);
|
741
785
|
}
|
742
786
|
|
787
|
+
finish:
|
788
|
+
if (na_count_out != NULL) {
|
789
|
+
*na_count_out = na_count;
|
790
|
+
}
|
743
791
|
return v;
|
744
792
|
}
|
745
793
|
|
794
|
+
/* call-seq:
|
795
|
+
* ary.sum(skip_na: false)
|
796
|
+
*
|
797
|
+
* Calculate the sum of the values in `ary`.
|
798
|
+
* This method utilizes
|
799
|
+
* [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
800
|
+
* to compensate the result precision when the `ary` includes Float values.
|
801
|
+
*
|
802
|
+
* Note that This library does not redefine `sum` method introduced in Ruby 2.4.
|
803
|
+
*
|
804
|
+
* @return [Number] A summation value
|
805
|
+
*/
|
806
|
+
static VALUE
|
807
|
+
ary_sum(int argc, VALUE* argv, VALUE ary)
|
808
|
+
{
|
809
|
+
VALUE v, opts;
|
810
|
+
int skip_na;
|
811
|
+
|
812
|
+
if (rb_scan_args(argc, argv, "01:", &v, &opts) == 0) {
|
813
|
+
v = LONG2FIX(0);
|
814
|
+
}
|
815
|
+
skip_na = opt_skip_na(opts);
|
816
|
+
|
817
|
+
#ifndef HAVE_ENUM_SUM
|
818
|
+
if (!skip_na) {
|
819
|
+
return rb_funcall(orig_ary_sum, rb_intern("call"), argc, &v);
|
820
|
+
}
|
821
|
+
#endif
|
822
|
+
|
823
|
+
return ary_calculate_sum(ary, v, skip_na, NULL);
|
824
|
+
}
|
825
|
+
|
746
826
|
static void
|
747
827
|
calculate_and_set_mean(VALUE *mean_ptr, VALUE sum, long const n)
|
748
828
|
{
|
@@ -771,9 +851,10 @@ calculate_and_set_mean(VALUE *mean_ptr, VALUE sum, long const n)
|
|
771
851
|
}
|
772
852
|
|
773
853
|
static void
|
774
|
-
ary_mean_variance(VALUE ary, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
854
|
+
ary_mean_variance(VALUE ary, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof, int skip_na)
|
775
855
|
{
|
776
856
|
long i;
|
857
|
+
long na_count;
|
777
858
|
size_t n = 0;
|
778
859
|
double m = 0.0, m2 = 0.0, f = 0.0, c = 0.0;
|
779
860
|
|
@@ -797,8 +878,8 @@ ary_mean_variance(VALUE ary, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
797
878
|
|
798
879
|
if (variance_ptr == NULL) {
|
799
880
|
VALUE init = DBL2NUM(0.0);
|
800
|
-
VALUE const sum =
|
801
|
-
long const n = RARRAY_LEN(ary);
|
881
|
+
VALUE const sum = ary_calculate_sum(ary, init, skip_na, &na_count);
|
882
|
+
long const n = RARRAY_LEN(ary) - na_count;
|
802
883
|
calculate_and_set_mean(mean_ptr, sum, n);
|
803
884
|
return;
|
804
885
|
}
|
@@ -839,26 +920,46 @@ ary_mean_variance(VALUE ary, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
839
920
|
}
|
840
921
|
}
|
841
922
|
|
842
|
-
|
843
|
-
|
923
|
+
struct variance_opts {
|
924
|
+
int population;
|
925
|
+
int skip_na;
|
926
|
+
};
|
927
|
+
|
928
|
+
static void
|
929
|
+
get_variance_opts(VALUE opts, struct variance_opts *out)
|
844
930
|
{
|
845
|
-
|
931
|
+
assert(out != NULL);
|
932
|
+
|
933
|
+
out->population = 0;
|
934
|
+
out->skip_na = 0;
|
846
935
|
|
847
936
|
if (!NIL_P(opts)) {
|
848
937
|
#ifdef HAVE_RB_GET_KWARGS
|
849
|
-
ID
|
850
|
-
|
938
|
+
static ID kwarg_keys[2];
|
939
|
+
VALUE kwarg_vals;
|
940
|
+
|
941
|
+
if (!kwarg_keys[0]) {
|
942
|
+
kwarg_keys[0] = id_population;
|
943
|
+
kwarg_keys[1] = id_skip_na;
|
944
|
+
}
|
945
|
+
|
946
|
+
rb_get_kwargs(opts, &kwarg_keys, 0, 2, kwarg_vals);
|
947
|
+
out->population = (kwarg_vals[0] != Qundef) ? RTEST(kwarg_vals[0]) : out->population;
|
948
|
+
out->skip_na = (kwarg_vals[1] != Qundef) ? RTEST(kwarg_vals[1]) : out->skip_na;
|
851
949
|
#else
|
852
|
-
VALUE val
|
853
|
-
|
950
|
+
VALUE val;
|
951
|
+
|
952
|
+
val = rb_hash_aref(opts, ID2SYM(id_population));
|
953
|
+
out->population = NIL_P(val) ? out->population : RTEST(val);
|
954
|
+
|
955
|
+
val = rb_hash_aref(opts, ID2SYM(id_skip_na));
|
956
|
+
out->skip_na = NIL_P(val) ? out->skip_na : RTEST(val);
|
854
957
|
#endif
|
855
958
|
}
|
856
|
-
|
857
|
-
return RTEST(population);
|
858
959
|
}
|
859
960
|
|
860
961
|
/* call-seq:
|
861
|
-
* ary.mean_variance(population: false)
|
962
|
+
* ary.mean_variance(population: false, skip_na: false)
|
862
963
|
*
|
863
964
|
* Calculate a mean and a variance of the values in `ary`.
|
864
965
|
* The first element of the result array is the mean, and the second is the variance.
|
@@ -876,19 +977,21 @@ opt_population_p(VALUE opts)
|
|
876
977
|
static VALUE
|
877
978
|
ary_mean_variance_m(int argc, VALUE* argv, VALUE ary)
|
878
979
|
{
|
879
|
-
|
980
|
+
struct variance_opts options;
|
981
|
+
VALUE opts, mean = Qnil, variance = Qnil;
|
880
982
|
size_t ddof = 1;
|
881
983
|
|
882
984
|
rb_scan_args(argc, argv, "0:", &opts);
|
883
|
-
|
985
|
+
get_variance_opts(opts, &options);
|
986
|
+
if (options.population)
|
884
987
|
ddof = 0;
|
885
988
|
|
886
|
-
ary_mean_variance(ary, &mean, &variance, ddof);
|
989
|
+
ary_mean_variance(ary, &mean, &variance, ddof, options.skip_na);
|
887
990
|
return rb_assoc_new(mean, variance);
|
888
991
|
}
|
889
992
|
|
890
993
|
/* call-seq:
|
891
|
-
* ary.mean
|
994
|
+
* ary.mean(skip_na: false)
|
892
995
|
*
|
893
996
|
* Calculate a mean of the values in `ary`.
|
894
997
|
* This method utilizes
|
@@ -898,15 +1001,20 @@ ary_mean_variance_m(int argc, VALUE* argv, VALUE ary)
|
|
898
1001
|
* @return [Number] A mean value
|
899
1002
|
*/
|
900
1003
|
static VALUE
|
901
|
-
ary_mean(VALUE ary)
|
1004
|
+
ary_mean(int argc, VALUE *argv, VALUE ary)
|
902
1005
|
{
|
903
|
-
VALUE mean;
|
904
|
-
|
1006
|
+
VALUE mean = Qnil, opts;
|
1007
|
+
int skip_na;
|
1008
|
+
|
1009
|
+
rb_scan_args(argc, argv, ":", &opts);
|
1010
|
+
skip_na = opt_skip_na(opts);
|
1011
|
+
|
1012
|
+
ary_mean_variance(ary, &mean, NULL, 1, skip_na);
|
905
1013
|
return mean;
|
906
1014
|
}
|
907
1015
|
|
908
1016
|
/* call-seq:
|
909
|
-
* ary.variance(population: false)
|
1017
|
+
* ary.variance(population: false, skip_na: false)
|
910
1018
|
*
|
911
1019
|
* Calculate a variance of the values in `ary`.
|
912
1020
|
* This method scan values in `ary` only once,
|
@@ -922,14 +1030,16 @@ ary_mean(VALUE ary)
|
|
922
1030
|
static VALUE
|
923
1031
|
ary_variance(int argc, VALUE* argv, VALUE ary)
|
924
1032
|
{
|
1033
|
+
struct variance_opts options;
|
925
1034
|
VALUE opts, variance;
|
926
1035
|
size_t ddof = 1;
|
927
1036
|
|
928
1037
|
rb_scan_args(argc, argv, "0:", &opts);
|
929
|
-
|
1038
|
+
get_variance_opts(opts, &options);
|
1039
|
+
if (options.population)
|
930
1040
|
ddof = 0;
|
931
1041
|
|
932
|
-
ary_mean_variance(ary, NULL, &variance, ddof);
|
1042
|
+
ary_mean_variance(ary, NULL, &variance, ddof, options.skip_na);
|
933
1043
|
return variance;
|
934
1044
|
}
|
935
1045
|
|
@@ -943,6 +1053,7 @@ struct enum_sum_memo {
|
|
943
1053
|
double f, c;
|
944
1054
|
int block_given;
|
945
1055
|
int float_value;
|
1056
|
+
int skip_na;
|
946
1057
|
};
|
947
1058
|
|
948
1059
|
static void
|
@@ -956,8 +1067,12 @@ sum_iter(VALUE e, struct enum_sum_memo *memo)
|
|
956
1067
|
double f = memo->f;
|
957
1068
|
double c = memo->c;
|
958
1069
|
|
959
|
-
if (memo->block_given)
|
1070
|
+
if (memo->block_given) {
|
960
1071
|
e = rb_yield(e);
|
1072
|
+
}
|
1073
|
+
if (memo->skip_na && is_na(e)) {
|
1074
|
+
return;
|
1075
|
+
}
|
961
1076
|
|
962
1077
|
memo->count += 1;
|
963
1078
|
|
@@ -1090,7 +1205,7 @@ int_range_sum_count(VALUE beg, VALUE end, int excl,
|
|
1090
1205
|
}
|
1091
1206
|
|
1092
1207
|
static void
|
1093
|
-
enum_sum_count(VALUE obj, VALUE init, VALUE *sum_ptr, long *count_ptr)
|
1208
|
+
enum_sum_count(VALUE obj, VALUE init, int skip_na, VALUE *sum_ptr, long *count_ptr)
|
1094
1209
|
{
|
1095
1210
|
struct enum_sum_memo memo;
|
1096
1211
|
VALUE beg, end;
|
@@ -1101,6 +1216,7 @@ enum_sum_count(VALUE obj, VALUE init, VALUE *sum_ptr, long *count_ptr)
|
|
1101
1216
|
memo.block_given = rb_block_given_p();
|
1102
1217
|
memo.n = 0;
|
1103
1218
|
memo.r = Qundef;
|
1219
|
+
memo.skip_na = skip_na;
|
1104
1220
|
|
1105
1221
|
if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
|
1106
1222
|
memo.f = RFLOAT_VALUE(memo.v);
|
@@ -1138,9 +1254,8 @@ enum_sum_count(VALUE obj, VALUE init, VALUE *sum_ptr, long *count_ptr)
|
|
1138
1254
|
*count_ptr = memo.count;
|
1139
1255
|
}
|
1140
1256
|
|
1141
|
-
#ifndef HAVE_ENUM_SUM
|
1142
1257
|
/* call-seq:
|
1143
|
-
* enum.sum
|
1258
|
+
* enum.sum(skip_na: false)
|
1144
1259
|
*
|
1145
1260
|
* Calculate the sum of the values in `enum`.
|
1146
1261
|
* This method utilizes
|
@@ -1154,16 +1269,27 @@ enum_sum_count(VALUE obj, VALUE init, VALUE *sum_ptr, long *count_ptr)
|
|
1154
1269
|
static VALUE
|
1155
1270
|
enum_sum(int argc, VALUE* argv, VALUE obj)
|
1156
1271
|
{
|
1157
|
-
VALUE sum, init;
|
1272
|
+
VALUE sum, init, opts;
|
1273
|
+
int skip_na;
|
1158
1274
|
|
1159
|
-
if (rb_scan_args(argc, argv, "01", &init) == 0)
|
1275
|
+
if (rb_scan_args(argc, argv, "01:", &init, &opts) == 0) {
|
1160
1276
|
init = LONG2FIX(0);
|
1277
|
+
}
|
1278
|
+
skip_na = opt_skip_na(opts);
|
1161
1279
|
|
1162
|
-
|
1280
|
+
#ifndef HAVE_ENUM_SUM
|
1281
|
+
if (skip_na) {
|
1282
|
+
enum_sum_count(obj, init, skip_na, &sum, NULL);
|
1283
|
+
}
|
1284
|
+
else {
|
1285
|
+
rb_funcall(orig_enum_sum, rb_intern("call"), argc, &init);
|
1286
|
+
}
|
1287
|
+
#else
|
1288
|
+
enum_sum_count(obj, init, skip_na, &sum, NULL);
|
1289
|
+
#endif
|
1163
1290
|
|
1164
1291
|
return sum;
|
1165
1292
|
}
|
1166
|
-
#endif
|
1167
1293
|
|
1168
1294
|
struct enum_mean_variance_memo {
|
1169
1295
|
int block_given;
|
@@ -1253,7 +1379,7 @@ enum_mean_variance(VALUE obj, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
1253
1379
|
long n;
|
1254
1380
|
VALUE sum;
|
1255
1381
|
VALUE init = DBL2NUM(0.0);
|
1256
|
-
enum_sum_count(obj, init, &sum, &n);
|
1382
|
+
enum_sum_count(obj, init, 0, &sum, &n); /* TODO: skip_na */
|
1257
1383
|
if (n > 0)
|
1258
1384
|
calculate_and_set_mean(mean_ptr, sum, n);
|
1259
1385
|
return;
|
@@ -1303,11 +1429,13 @@ enum_mean_variance(VALUE obj, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
1303
1429
|
static VALUE
|
1304
1430
|
enum_mean_variance_m(int argc, VALUE* argv, VALUE obj)
|
1305
1431
|
{
|
1432
|
+
struct variance_opts options;
|
1306
1433
|
VALUE opts, mean, variance;
|
1307
1434
|
size_t ddof = 1;
|
1308
1435
|
|
1309
1436
|
rb_scan_args(argc, argv, "0:", &opts);
|
1310
|
-
|
1437
|
+
get_variance_opts(opts, &options);
|
1438
|
+
if (options.population)
|
1311
1439
|
ddof = 0;
|
1312
1440
|
|
1313
1441
|
enum_mean_variance(obj, &mean, &variance, ddof);
|
@@ -1349,11 +1477,13 @@ enum_mean(VALUE obj)
|
|
1349
1477
|
static VALUE
|
1350
1478
|
enum_variance(int argc, VALUE* argv, VALUE obj)
|
1351
1479
|
{
|
1480
|
+
struct variance_opts options;
|
1352
1481
|
VALUE opts, variance;
|
1353
1482
|
size_t ddof = 1;
|
1354
1483
|
|
1355
1484
|
rb_scan_args(argc, argv, "0:", &opts);
|
1356
|
-
|
1485
|
+
get_variance_opts(opts, &options);
|
1486
|
+
if (options.population)
|
1357
1487
|
ddof = 0;
|
1358
1488
|
|
1359
1489
|
enum_mean_variance(obj, NULL, &variance, ddof);
|
@@ -1392,11 +1522,13 @@ sqrt_value(VALUE x)
|
|
1392
1522
|
static VALUE
|
1393
1523
|
enum_mean_stdev(int argc, VALUE* argv, VALUE obj)
|
1394
1524
|
{
|
1525
|
+
struct variance_opts options;
|
1395
1526
|
VALUE opts, mean, variance;
|
1396
1527
|
size_t ddof = 1;
|
1397
1528
|
|
1398
1529
|
rb_scan_args(argc, argv, "0:", &opts);
|
1399
|
-
|
1530
|
+
get_variance_opts(opts, &options);
|
1531
|
+
if (options.population)
|
1400
1532
|
ddof = 0;
|
1401
1533
|
|
1402
1534
|
enum_mean_variance(obj, &mean, &variance, ddof);
|
@@ -1446,14 +1578,16 @@ enum_stdev(int argc, VALUE* argv, VALUE obj)
|
|
1446
1578
|
static VALUE
|
1447
1579
|
ary_mean_stdev(int argc, VALUE* argv, VALUE ary)
|
1448
1580
|
{
|
1581
|
+
struct variance_opts options;
|
1449
1582
|
VALUE opts, mean, variance;
|
1450
1583
|
size_t ddof = 1;
|
1451
1584
|
|
1452
1585
|
rb_scan_args(argc, argv, "0:", &opts);
|
1453
|
-
|
1586
|
+
get_variance_opts(opts, &options);
|
1587
|
+
if (options.population)
|
1454
1588
|
ddof = 0;
|
1455
1589
|
|
1456
|
-
ary_mean_variance(ary, &mean, &variance, ddof);
|
1590
|
+
ary_mean_variance(ary, &mean, &variance, ddof, options.skip_na);
|
1457
1591
|
VALUE stdev = sqrt_value(variance);
|
1458
1592
|
return rb_assoc_new(mean, stdev);
|
1459
1593
|
}
|
@@ -1479,21 +1613,6 @@ ary_stdev(int argc, VALUE* argv, VALUE ary)
|
|
1479
1613
|
return stdev;
|
1480
1614
|
}
|
1481
1615
|
|
1482
|
-
static inline int
|
1483
|
-
is_na(VALUE v)
|
1484
|
-
{
|
1485
|
-
if (NIL_P(v))
|
1486
|
-
return 1;
|
1487
|
-
|
1488
|
-
if (RB_FLOAT_TYPE_P(v) && isnan(RFLOAT_VALUE(v)))
|
1489
|
-
return 1;
|
1490
|
-
|
1491
|
-
if (rb_respond_to(v, id_nan_p) && RTEST(rb_funcall(v, id_nan_p, 0)))
|
1492
|
-
return 1;
|
1493
|
-
|
1494
|
-
return 0;
|
1495
|
-
}
|
1496
|
-
|
1497
1616
|
static int
|
1498
1617
|
ary_percentile_sort_cmp(const void *ap, const void *bp, void *dummy)
|
1499
1618
|
{
|
@@ -1900,7 +2019,7 @@ any_value_counts(int argc, VALUE *argv, VALUE obj,
|
|
1900
2019
|
struct value_counts_opts opts;
|
1901
2020
|
struct value_counts_memo memo;
|
1902
2021
|
|
1903
|
-
rb_scan_args(argc, argv, ":", &kwargs);
|
2022
|
+
rb_scan_args(argc, argv, "0:", &kwargs);
|
1904
2023
|
value_counts_extract_opts(kwargs, &opts);
|
1905
2024
|
|
1906
2025
|
memo.result = rb_hash_new();
|
@@ -2102,50 +2221,67 @@ histogram_edge_bin_index(VALUE edge, VALUE rb_x, int left_p)
|
|
2102
2221
|
}
|
2103
2222
|
|
2104
2223
|
static void
|
2105
|
-
histogram_weights_push_values(VALUE
|
2224
|
+
histogram_weights_push_values(VALUE bin_weights, VALUE edge, VALUE values, VALUE weight_array, int left_p)
|
2106
2225
|
{
|
2226
|
+
const VALUE one = INT2FIX(1);
|
2227
|
+
long bi, i, n, n_bins, weighted = 0;
|
2107
2228
|
VALUE x, cur;
|
2108
|
-
|
2229
|
+
|
2230
|
+
assert(RB_TYPE_P(edge, T_ARRAY));
|
2231
|
+
assert(RB_TYPE_P(values, T_ARRAY));
|
2109
2232
|
|
2110
2233
|
n = RARRAY_LEN(values);
|
2234
|
+
n_bins = RARRAY_LEN(edge) - 1;
|
2235
|
+
|
2236
|
+
if (! NIL_P(weight_array)) {
|
2237
|
+
assert(RB_TYPE_P(weight_array, T_ARRAY));
|
2238
|
+
assert(RARRAY_LEN(weight_array) == n);
|
2239
|
+
weighted = 1;
|
2240
|
+
}
|
2241
|
+
|
2111
2242
|
for (i = 0; i < n; ++i) {
|
2112
2243
|
x = RARRAY_AREF(values, i);
|
2113
2244
|
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2245
|
+
VALUE w;
|
2246
|
+
if (weighted) {
|
2247
|
+
w = RARRAY_AREF(weight_array, i);
|
2248
|
+
if (RB_TYPE_P(w, T_COMPLEX)) {
|
2249
|
+
VALUE imag = RCOMPLEX(w)->imag;
|
2250
|
+
if (! RTEST(f_zero_p(imag))) {
|
2251
|
+
goto type_error;
|
2252
|
+
}
|
2253
|
+
}
|
2254
|
+
else if (rb_obj_is_kind_of(w, rb_cNumeric)) {
|
2255
|
+
if (!RTEST(f_real_p(w))) {
|
2256
|
+
goto type_error;
|
2257
|
+
}
|
2258
|
+
}
|
2259
|
+
else {
|
2260
|
+
goto type_error;
|
2261
|
+
}
|
2119
2262
|
}
|
2120
2263
|
else {
|
2121
|
-
|
2264
|
+
w = one;
|
2122
2265
|
}
|
2123
2266
|
|
2124
|
-
|
2125
|
-
}
|
2126
|
-
}
|
2267
|
+
bi = histogram_edge_bin_index(edge, x, left_p);
|
2127
2268
|
|
2128
|
-
|
2129
|
-
|
2130
|
-
{
|
2131
|
-
|
2269
|
+
if (0 <= bi && bi < n_bins) {
|
2270
|
+
cur = rb_ary_entry(bin_weights, bi);
|
2271
|
+
if (NIL_P(cur)) {
|
2272
|
+
cur = w;
|
2273
|
+
}
|
2274
|
+
else {
|
2275
|
+
cur = rb_funcall(cur, idPLUS, 1, w);
|
2276
|
+
}
|
2132
2277
|
|
2133
|
-
|
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);
|
2278
|
+
rb_ary_store(bin_weights, bi, cur);
|
2145
2279
|
}
|
2146
2280
|
}
|
2281
|
+
return;
|
2147
2282
|
|
2148
|
-
|
2283
|
+
type_error:
|
2284
|
+
rb_raise(rb_eTypeError, "weight array must have only real numbers");
|
2149
2285
|
}
|
2150
2286
|
|
2151
2287
|
static inline long
|
@@ -2238,9 +2374,9 @@ ary_histogram_calculate_edge_lo_hi(const double lo, const double hi, const long
|
|
2238
2374
|
}
|
2239
2375
|
|
2240
2376
|
static VALUE
|
2241
|
-
ary_histogram_calculate_edge(VALUE ary,
|
2377
|
+
ary_histogram_calculate_edge(VALUE ary, VALUE arg0, const int left_p)
|
2242
2378
|
{
|
2243
|
-
long n;
|
2379
|
+
long n, nbins;
|
2244
2380
|
VALUE minmax;
|
2245
2381
|
VALUE edge = Qnil;
|
2246
2382
|
double lo, hi;
|
@@ -2248,6 +2384,22 @@ ary_histogram_calculate_edge(VALUE ary, const long nbins, const int left_p)
|
|
2248
2384
|
Check_Type(ary, T_ARRAY);
|
2249
2385
|
n = RARRAY_LEN(ary);
|
2250
2386
|
|
2387
|
+
if (NIL_P(arg0)) {
|
2388
|
+
arg0 = sym_auto;
|
2389
|
+
}
|
2390
|
+
|
2391
|
+
if (RB_TYPE_P(arg0, T_SYMBOL)) {
|
2392
|
+
if (arg0 != sym_auto && arg0 != sym_sturges) {
|
2393
|
+
rb_raise(rb_eArgError, "Unknown method to calculate bin width: %+"PRIsVALUE, arg0);
|
2394
|
+
}
|
2395
|
+
else {
|
2396
|
+
nbins = sturges(n);
|
2397
|
+
}
|
2398
|
+
}
|
2399
|
+
else {
|
2400
|
+
nbins = NUM2LONG(arg0);
|
2401
|
+
}
|
2402
|
+
|
2251
2403
|
if (n == 0 && nbins < 0) {
|
2252
2404
|
rb_raise(rb_eArgError, "nbins must be >= 0 for an empty array, got %ld", nbins);
|
2253
2405
|
}
|
@@ -2269,10 +2421,47 @@ ary_histogram_calculate_edge(VALUE ary, const long nbins, const int left_p)
|
|
2269
2421
|
return edge;
|
2270
2422
|
}
|
2271
2423
|
|
2424
|
+
static VALUE
|
2425
|
+
check_histogram_weight_array(VALUE weight_array, const long ary_len)
|
2426
|
+
{
|
2427
|
+
if (weight_array == Qundef) return Qnil;
|
2428
|
+
|
2429
|
+
weight_array = rb_check_convert_type(weight_array, T_ARRAY, "Array", "to_ary");
|
2430
|
+
if (RARRAY_LEN(weight_array) != ary_len) {
|
2431
|
+
rb_raise(rb_eArgError, "weight array must have the same number of items as the receiver array");
|
2432
|
+
}
|
2433
|
+
|
2434
|
+
return weight_array;
|
2435
|
+
}
|
2436
|
+
|
2437
|
+
static VALUE
|
2438
|
+
check_histogram_edges(VALUE edges)
|
2439
|
+
{
|
2440
|
+
if (edges == Qundef) return Qnil;
|
2441
|
+
return rb_check_convert_type(edges, T_ARRAY, "Array", "to_ary");
|
2442
|
+
}
|
2443
|
+
|
2444
|
+
static int
|
2445
|
+
check_histogram_left_p(VALUE closed)
|
2446
|
+
{
|
2447
|
+
int left_p = (closed != sym_right);
|
2448
|
+
if (left_p && closed != Qundef && closed != sym_left) {
|
2449
|
+
rb_raise(rb_eArgError, "invalid value for :closed keyword "
|
2450
|
+
"(%"PRIsVALUE" for :left or :right)", closed);
|
2451
|
+
}
|
2452
|
+
return left_p;
|
2453
|
+
}
|
2454
|
+
|
2272
2455
|
/* call-seq:
|
2273
|
-
* ary.histogram(nbins=:auto, closed: :left)
|
2456
|
+
* ary.histogram(nbins=:auto, weight: nil, closed: :left)
|
2274
2457
|
*
|
2275
2458
|
* @param [Integer] nbins The approximate number of bins
|
2459
|
+
* @params [Array<Numeric>] weights
|
2460
|
+
* An optional weight array, that has the same length as the receiver.
|
2461
|
+
* `weight[i]` means the weight value of the i-th element in the receiver.
|
2462
|
+
* @params [Array<Numeric>] edges
|
2463
|
+
* An optional edge array, that specify the bin edges.
|
2464
|
+
* This array must be sorted.
|
2276
2465
|
* @param [:left, :right] closed
|
2277
2466
|
* If :left (the default), the bin interval are left-closed.
|
2278
2467
|
* If :right, the bin interval are right-closed.
|
@@ -2282,30 +2471,49 @@ ary_histogram_calculate_edge(VALUE ary, const long nbins, const int left_p)
|
|
2282
2471
|
static VALUE
|
2283
2472
|
ary_histogram(int argc, VALUE *argv, VALUE ary)
|
2284
2473
|
{
|
2285
|
-
VALUE arg0,
|
2286
|
-
|
2287
|
-
long nbins, nweights, i;
|
2474
|
+
VALUE arg0, kwargs, bin_weights;
|
2475
|
+
long n_bin_weights, i;
|
2288
2476
|
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2477
|
+
VALUE weight_array = Qnil;
|
2478
|
+
VALUE edges = Qnil;
|
2479
|
+
int left_p = 1;
|
2480
|
+
|
2481
|
+
rb_scan_args(argc, argv, "01:", &arg0, &kwargs);
|
2482
|
+
|
2483
|
+
if (!NIL_P(kwargs)) {
|
2484
|
+
enum { kw_weights, kw_edges, kw_closed };
|
2485
|
+
static ID kwarg_keys[3];
|
2486
|
+
VALUE kwarg_vals[3];
|
2487
|
+
|
2488
|
+
if (!kwarg_keys[0]) {
|
2489
|
+
kwarg_keys[kw_weights] = rb_intern("weights");
|
2490
|
+
kwarg_keys[kw_edges] = rb_intern("edges");
|
2491
|
+
kwarg_keys[kw_closed] = rb_intern("closed");
|
2492
|
+
}
|
2493
|
+
|
2494
|
+
rb_get_kwargs(kwargs, kwarg_keys, 0, 3, kwarg_vals);
|
2495
|
+
|
2496
|
+
weight_array = check_histogram_weight_array(kwarg_vals[kw_weights], RARRAY_LEN(ary));
|
2497
|
+
edges = check_histogram_edges(kwarg_vals[kw_edges]);
|
2498
|
+
left_p = check_histogram_left_p(kwarg_vals[kw_closed]);
|
2295
2499
|
}
|
2296
|
-
left_p = opt_closed_left_p(opts);
|
2297
2500
|
|
2298
|
-
|
2501
|
+
if (NIL_P(edges)) {
|
2502
|
+
edges = ary_histogram_calculate_edge(ary, arg0, left_p);
|
2503
|
+
}
|
2504
|
+
else if (! NIL_P(arg0)) {
|
2505
|
+
rb_raise(rb_eArgError, "Unable to use both `nbins` and `edges` together");
|
2506
|
+
}
|
2299
2507
|
|
2300
|
-
|
2301
|
-
|
2302
|
-
for (i = 0; i <
|
2303
|
-
rb_ary_store(
|
2508
|
+
n_bin_weights = RARRAY_LEN(edges) - 1;
|
2509
|
+
bin_weights = rb_ary_new_capa(n_bin_weights);
|
2510
|
+
for (i = 0; i < n_bin_weights; ++i) {
|
2511
|
+
rb_ary_store(bin_weights, i, INT2FIX(0));
|
2304
2512
|
}
|
2305
2513
|
|
2306
|
-
histogram_weights_push_values(
|
2514
|
+
histogram_weights_push_values(bin_weights, edges, ary, weight_array, left_p);
|
2307
2515
|
|
2308
|
-
return rb_struct_new(cHistogram,
|
2516
|
+
return rb_struct_new(cHistogram, edges, bin_weights,
|
2309
2517
|
left_p ? sym_left : sym_right,
|
2310
2518
|
Qfalse);
|
2311
2519
|
}
|
@@ -2315,10 +2523,16 @@ Init_extension(void)
|
|
2315
2523
|
{
|
2316
2524
|
VALUE mEnumerableStatistics;
|
2317
2525
|
|
2318
|
-
#
|
2319
|
-
|
2526
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
2527
|
+
rb_ext_ractor_safe(true);
|
2320
2528
|
#endif
|
2321
2529
|
|
2530
|
+
mEnumerableStatistics = rb_const_get_at(rb_cObject, rb_intern("EnumerableStatistics"));
|
2531
|
+
|
2532
|
+
orig_enum_sum = rb_funcall(rb_mEnumerable, rb_intern("public_instance_method"), 1, rb_str_new_cstr("sum"));
|
2533
|
+
orig_ary_sum = rb_funcall(rb_cArray, rb_intern("public_instance_method"), 1, rb_str_new_cstr("sum"));
|
2534
|
+
|
2535
|
+
rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
|
2322
2536
|
rb_define_method(rb_mEnumerable, "mean_variance", enum_mean_variance_m, -1);
|
2323
2537
|
rb_define_method(rb_mEnumerable, "mean", enum_mean, 0);
|
2324
2538
|
rb_define_method(rb_mEnumerable, "variance", enum_variance, -1);
|
@@ -2326,11 +2540,9 @@ Init_extension(void)
|
|
2326
2540
|
rb_define_method(rb_mEnumerable, "stdev", enum_stdev, -1);
|
2327
2541
|
rb_define_method(rb_mEnumerable, "value_counts", enum_value_counts, -1);
|
2328
2542
|
|
2329
|
-
#ifndef HAVE_ARRAY_SUM
|
2330
2543
|
rb_define_method(rb_cArray, "sum", ary_sum, -1);
|
2331
|
-
#endif
|
2332
2544
|
rb_define_method(rb_cArray, "mean_variance", ary_mean_variance_m, -1);
|
2333
|
-
rb_define_method(rb_cArray, "mean", ary_mean,
|
2545
|
+
rb_define_method(rb_cArray, "mean", ary_mean, -1);
|
2334
2546
|
rb_define_method(rb_cArray, "variance", ary_variance, -1);
|
2335
2547
|
rb_define_method(rb_cArray, "mean_stdev", ary_mean_stdev, -1);
|
2336
2548
|
rb_define_method(rb_cArray, "stdev", ary_stdev, -1);
|
@@ -2343,11 +2555,13 @@ Init_extension(void)
|
|
2343
2555
|
half_in_rational = nurat_s_new_internal(rb_cRational, INT2FIX(1), INT2FIX(2));
|
2344
2556
|
rb_gc_register_mark_object(half_in_rational);
|
2345
2557
|
|
2346
|
-
mEnumerableStatistics = rb_const_get_at(rb_cObject, rb_intern("EnumerableStatistics"));
|
2347
2558
|
cHistogram = rb_const_get_at(mEnumerableStatistics, rb_intern("Histogram"));
|
2348
2559
|
|
2349
2560
|
rb_define_method(rb_cArray, "histogram", ary_histogram, -1);
|
2350
2561
|
|
2562
|
+
void Init_array_extension(void);
|
2563
|
+
Init_array_extension();
|
2564
|
+
|
2351
2565
|
idPLUS = '+';
|
2352
2566
|
idMINUS = '-';
|
2353
2567
|
idSTAR = '*';
|
@@ -2366,7 +2580,9 @@ Init_extension(void)
|
|
2366
2580
|
id_population = rb_intern("population");
|
2367
2581
|
id_closed = rb_intern("closed");
|
2368
2582
|
id_edge = rb_intern("edge");
|
2583
|
+
id_skip_na = rb_intern("skip_na");
|
2369
2584
|
|
2585
|
+
sym_auto = ID2SYM(rb_intern("auto"));
|
2370
2586
|
sym_left = ID2SYM(rb_intern("left"));
|
2371
2587
|
sym_right = ID2SYM(rb_intern("right"));
|
2372
2588
|
}
|
@@ -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
|
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.
|
4
|
+
version: 2.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenta Murata
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: test-unit
|
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'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: fuubar
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,12 +128,11 @@ email:
|
|
114
128
|
executables: []
|
115
129
|
extensions:
|
116
130
|
- ext/enumerable/statistics/extension/extconf.rb
|
117
|
-
- ext/-bench-/extconf.rb
|
118
131
|
extra_rdoc_files: []
|
119
132
|
files:
|
133
|
+
- ".github/workflows/ci.yml"
|
120
134
|
- ".gitignore"
|
121
135
|
- ".rspec"
|
122
|
-
- ".travis.yml"
|
123
136
|
- ".yardopts"
|
124
137
|
- CHANGELOG.md
|
125
138
|
- Gemfile
|
@@ -136,12 +149,13 @@ files:
|
|
136
149
|
- bin/rspec
|
137
150
|
- bin/setup
|
138
151
|
- enumerable-statistics.gemspec
|
139
|
-
- ext
|
152
|
+
- ext/enumerable/statistics/extension/array_ext.c
|
140
153
|
- ext/enumerable/statistics/extension/extconf.rb
|
141
154
|
- ext/enumerable/statistics/extension/statistics.c
|
142
155
|
- images/benchmark.png
|
143
156
|
- lib/enumerable/statistics.rb
|
144
157
|
- lib/enumerable_statistics.rb
|
158
|
+
- lib/enumerable_statistics/array_ext.rb
|
145
159
|
- lib/enumerable_statistics/histogram.rb
|
146
160
|
- lib/enumerable_statistics/version.rb
|
147
161
|
- templates/default/layout/html/headers.erb
|
@@ -275,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
289
|
- !ruby/object:Gem::Version
|
276
290
|
version: '0'
|
277
291
|
requirements: []
|
278
|
-
rubygems_version: 3.
|
292
|
+
rubygems_version: 3.5.9
|
279
293
|
signing_key:
|
280
294
|
specification_version: 4
|
281
295
|
summary: Statistics features for Enumerable
|
data/.travis.yml
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
---
|
2
|
-
notification:
|
3
|
-
email:
|
4
|
-
- mrkn@ruby-lang.org
|
5
|
-
|
6
|
-
language: ruby
|
7
|
-
|
8
|
-
before_install:
|
9
|
-
- yes | gem update --system
|
10
|
-
- gem install bundler
|
11
|
-
|
12
|
-
install:
|
13
|
-
- bundle install
|
14
|
-
|
15
|
-
script:
|
16
|
-
- bundle exec rake --trace clobber compile
|
17
|
-
- bundle exec rake spec
|
18
|
-
|
19
|
-
matrix:
|
20
|
-
include:
|
21
|
-
- name: "2.3"
|
22
|
-
rvm: 2.3
|
23
|
-
- name: "2.4"
|
24
|
-
rvm: 2.4.5
|
25
|
-
- name: "2.5"
|
26
|
-
rvm: 2.5.2
|
27
|
-
- name: "2.6"
|
28
|
-
rvm: 2.6
|
29
|
-
- name: "trunk"
|
30
|
-
rvm: ruby-head
|
31
|
-
allow_failures:
|
32
|
-
- rvm: 2.3
|
data/ext/-bench-/extconf.rb
DELETED