enumerable-statistics 0.1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +15 -0
- data/LICENSE +21 -0
- data/README.md +60 -4
- data/Rakefile +11 -0
- data/bench/mean.rb +27 -0
- data/bench/sum.rb +26 -0
- data/bench/variance.rb +30 -0
- data/enumerable-statistics.gemspec +1 -0
- data/ext/enumerable/statistics/extension/statistics.c +811 -46
- data/images/benchmark.png +0 -0
- data/lib/enumerable/statistics/version.rb +1 -1
- data/yard/templates/mathjax/class/dot/setup.rb +6 -0
- data/yard/templates/mathjax/class/dot/superklass.erb +3 -0
- data/yard/templates/mathjax/class/html/constructor_details.erb +8 -0
- data/yard/templates/mathjax/class/html/setup.rb +1 -0
- data/yard/templates/mathjax/class/html/subclasses.erb +4 -0
- data/yard/templates/mathjax/class/setup.rb +36 -0
- data/yard/templates/mathjax/class/text/setup.rb +11 -0
- data/yard/templates/mathjax/class/text/subclasses.erb +5 -0
- data/yard/templates/mathjax/constant/text/header.erb +11 -0
- data/yard/templates/mathjax/constant/text/setup.rb +3 -0
- data/yard/templates/mathjax/docstring/html/abstract.erb +4 -0
- data/yard/templates/mathjax/docstring/html/deprecated.erb +1 -0
- data/yard/templates/mathjax/docstring/html/index.erb +5 -0
- data/yard/templates/mathjax/docstring/html/note.erb +6 -0
- data/yard/templates/mathjax/docstring/html/private.erb +4 -0
- data/yard/templates/mathjax/docstring/html/returns_void.erb +1 -0
- data/yard/templates/mathjax/docstring/html/text.erb +1 -0
- data/yard/templates/mathjax/docstring/html/todo.erb +6 -0
- data/yard/templates/mathjax/docstring/setup.rb +51 -0
- data/yard/templates/mathjax/docstring/text/abstract.erb +2 -0
- data/yard/templates/mathjax/docstring/text/deprecated.erb +2 -0
- data/yard/templates/mathjax/docstring/text/index.erb +2 -0
- data/yard/templates/mathjax/docstring/text/note.erb +4 -0
- data/yard/templates/mathjax/docstring/text/private.erb +2 -0
- data/yard/templates/mathjax/docstring/text/returns_void.erb +1 -0
- data/yard/templates/mathjax/docstring/text/text.erb +1 -0
- data/yard/templates/mathjax/docstring/text/todo.erb +4 -0
- data/yard/templates/mathjax/fulldoc/html/css/common.css +1 -0
- data/yard/templates/mathjax/fulldoc/html/css/full_list.css +58 -0
- data/yard/templates/mathjax/fulldoc/html/css/style.css +481 -0
- data/yard/templates/mathjax/fulldoc/html/frames.erb +17 -0
- data/yard/templates/mathjax/fulldoc/html/full_list.erb +37 -0
- data/yard/templates/mathjax/fulldoc/html/full_list_class.erb +2 -0
- data/yard/templates/mathjax/fulldoc/html/full_list_file.erb +7 -0
- data/yard/templates/mathjax/fulldoc/html/full_list_method.erb +10 -0
- data/yard/templates/mathjax/fulldoc/html/js/app.js +243 -0
- data/yard/templates/mathjax/fulldoc/html/js/full_list.js +216 -0
- data/yard/templates/mathjax/fulldoc/html/js/jquery.js +4 -0
- data/yard/templates/mathjax/fulldoc/html/setup.rb +242 -0
- data/yard/templates/mathjax/layout/dot/header.erb +6 -0
- data/yard/templates/mathjax/layout/dot/setup.rb +14 -0
- data/yard/templates/mathjax/layout/html/breadcrumb.erb +11 -0
- data/yard/templates/mathjax/layout/html/files.erb +11 -0
- data/yard/templates/mathjax/layout/html/footer.erb +5 -0
- data/yard/templates/mathjax/layout/html/headers.erb +15 -0
- data/yard/templates/mathjax/layout/html/index.erb +2 -0
- data/yard/templates/mathjax/layout/html/layout.erb +38 -0
- data/yard/templates/mathjax/layout/html/listing.erb +4 -0
- data/yard/templates/mathjax/layout/html/objects.erb +32 -0
- data/yard/templates/mathjax/layout/html/script_setup.erb +4 -0
- data/yard/templates/mathjax/layout/html/search.erb +13 -0
- data/yard/templates/mathjax/layout/html/setup.rb +87 -0
- data/yard/templates/mathjax/method/html/header.erb +17 -0
- data/yard/templates/mathjax/method/setup.rb +3 -0
- data/yard/templates/mathjax/method/text/header.erb +1 -0
- data/yard/templates/mathjax/method_details/html/header.erb +3 -0
- data/yard/templates/mathjax/method_details/html/method_signature.erb +25 -0
- data/yard/templates/mathjax/method_details/html/source.erb +10 -0
- data/yard/templates/mathjax/method_details/setup.rb +10 -0
- data/yard/templates/mathjax/method_details/text/header.erb +10 -0
- data/yard/templates/mathjax/method_details/text/method_signature.erb +12 -0
- data/yard/templates/mathjax/method_details/text/setup.rb +10 -0
- data/yard/templates/mathjax/module/dot/child.erb +1 -0
- data/yard/templates/mathjax/module/dot/dependencies.erb +3 -0
- data/yard/templates/mathjax/module/dot/header.erb +6 -0
- data/yard/templates/mathjax/module/dot/info.erb +14 -0
- data/yard/templates/mathjax/module/dot/setup.rb +14 -0
- data/yard/templates/mathjax/module/html/attribute_details.erb +10 -0
- data/yard/templates/mathjax/module/html/attribute_summary.erb +8 -0
- data/yard/templates/mathjax/module/html/box_info.erb +43 -0
- data/yard/templates/mathjax/module/html/children.erb +8 -0
- data/yard/templates/mathjax/module/html/constant_summary.erb +11 -0
- data/yard/templates/mathjax/module/html/defines.erb +3 -0
- data/yard/templates/mathjax/module/html/header.erb +5 -0
- data/yard/templates/mathjax/module/html/inherited_attributes.erb +14 -0
- data/yard/templates/mathjax/module/html/inherited_constants.erb +8 -0
- data/yard/templates/mathjax/module/html/inherited_methods.erb +19 -0
- data/yard/templates/mathjax/module/html/item_summary.erb +40 -0
- data/yard/templates/mathjax/module/html/method_details_list.erb +9 -0
- data/yard/templates/mathjax/module/html/method_summary.erb +14 -0
- data/yard/templates/mathjax/module/html/methodmissing.erb +12 -0
- data/yard/templates/mathjax/module/html/pre_docstring.erb +1 -0
- data/yard/templates/mathjax/module/setup.rb +164 -0
- data/yard/templates/mathjax/module/text/children.erb +10 -0
- data/yard/templates/mathjax/module/text/class_meths_list.erb +8 -0
- data/yard/templates/mathjax/module/text/extends.erb +8 -0
- data/yard/templates/mathjax/module/text/header.erb +7 -0
- data/yard/templates/mathjax/module/text/includes.erb +8 -0
- data/yard/templates/mathjax/module/text/instance_meths_list.erb +8 -0
- data/yard/templates/mathjax/module/text/setup.rb +12 -0
- data/yard/templates/mathjax/onefile/html/files.erb +5 -0
- data/yard/templates/mathjax/onefile/html/headers.erb +6 -0
- data/yard/templates/mathjax/onefile/html/layout.erb +29 -0
- data/yard/templates/mathjax/onefile/html/readme.erb +3 -0
- data/yard/templates/mathjax/onefile/html/setup.rb +61 -0
- data/yard/templates/mathjax/root/dot/child.erb +3 -0
- data/yard/templates/mathjax/root/dot/setup.rb +5 -0
- data/yard/templates/mathjax/root/html/setup.rb +1 -0
- data/yard/templates/mathjax/tags/html/example.erb +11 -0
- data/yard/templates/mathjax/tags/html/index.erb +3 -0
- data/yard/templates/mathjax/tags/html/option.erb +24 -0
- data/yard/templates/mathjax/tags/html/overload.erb +14 -0
- data/yard/templates/mathjax/tags/html/see.erb +8 -0
- data/yard/templates/mathjax/tags/html/tag.erb +20 -0
- data/yard/templates/mathjax/tags/setup.rb +55 -0
- data/yard/templates/mathjax/tags/text/example.erb +12 -0
- data/yard/templates/mathjax/tags/text/index.erb +1 -0
- data/yard/templates/mathjax/tags/text/option.erb +20 -0
- data/yard/templates/mathjax/tags/text/overload.erb +19 -0
- data/yard/templates/mathjax/tags/text/see.erb +11 -0
- data/yard/templates/mathjax/tags/text/tag.erb +13 -0
- metadata +134 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01d8583f76df44d84e20ab090a5589e44e33dacf
|
|
4
|
+
data.tar.gz: c070a1c7b007646ee0769b9e4924c0af0914341d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b3027aea941fa441b21c53ff8570b712cd576b42d97d9b7e3c421c92ad9c79552860a4f1c3bfd86da5c7f654d5396ab23415a0f861a4290ac1971ced29372e4
|
|
7
|
+
data.tar.gz: d082b4b5c2dd4c91b40400ccbbcd68859e6811bc14add0416133c8a70d67c97b4af10ae4f53fef4fc73efcc139d7f3d224baa5e7b983c4428880bc671039a935
|
data/.yardopts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--markup markdown
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 1.0.1
|
|
2
|
+
|
|
3
|
+
- Add `mean_variance` method in Array class and Enumerable module
|
|
4
|
+
- Add optimized implementation of `mean_variance` method for a Hash
|
|
5
|
+
- Add the following methods, implemented by using `mean_variance`, in Array class and Enumerable module
|
|
6
|
+
- `mean`
|
|
7
|
+
- `variance`
|
|
8
|
+
- `stddev`
|
|
9
|
+
- `mean_stddev`
|
|
10
|
+
- Add `sum` method in Array class and Enumerable module when Ruby < 2.4, that is almost same as introduced in Ruby 2.4
|
|
11
|
+
- Add optimized implementation of `sum` method for a Range with integer ends and a Hash, that is almost same as introduced in Ruby 2.4
|
|
12
|
+
|
|
13
|
+
# 1.0.0
|
|
14
|
+
|
|
15
|
+
- This version was yanked due to documentation issue
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Kenta Murata
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Enumerable::Statistics
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://travis-ci.org/mrkn/enumerable-statistics)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Enumerable::Statistics provides some methods to calculate statistical summary in arrays and enumerables.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -22,7 +22,63 @@ Or install it yourself as:
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
You should load this library by the following line in your script at first.
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
require 'enumerable/statistics'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The following methods are supplied by this library:
|
|
32
|
+
|
|
33
|
+
- `Array#mean`, `Enumerable#mean`
|
|
34
|
+
- Calculates a mean of values in an array or an enumerable
|
|
35
|
+
- `Array#variance`, `Enumerable#variance`
|
|
36
|
+
- Calculates a variance of values in an array or an enumerable
|
|
37
|
+
- `Array#stdev`, `Enumerable#stdev`
|
|
38
|
+
- Calculates a standard deviation of values in an array or an enumerable
|
|
39
|
+
- `Array#mean_variance`, `Enumerable#mean_variance`
|
|
40
|
+
- Calculates a mean and a variance simultaneously
|
|
41
|
+
- `Array#mean_stdev`, `Enumerable#mean_stdev`
|
|
42
|
+
- Calculates a mean and a standard deviation simultaneously
|
|
43
|
+
|
|
44
|
+
Moreover, for Ruby < 2.4, `Array#sum` and `Enumerable#sum` are provided.
|
|
45
|
+
|
|
46
|
+
All methods scan a collection once to calculate statistics and preserve precision as possible.
|
|
47
|
+
|
|
48
|
+
## Performance
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
$ bundle exec rake bench
|
|
52
|
+
# sum
|
|
53
|
+
Warming up --------------------------------------
|
|
54
|
+
inject 1.545k i/100ms
|
|
55
|
+
while 2.342k i/100ms
|
|
56
|
+
sum 11.009k i/100ms
|
|
57
|
+
Calculating -------------------------------------
|
|
58
|
+
inject 15.016k (± 9.6%) i/s - 75.705k in 5.098723s
|
|
59
|
+
while 22.238k (±16.2%) i/s - 107.732k in 5.068156s
|
|
60
|
+
sum 112.992k (± 6.9%) i/s - 572.468k in 5.091868s
|
|
61
|
+
# mean
|
|
62
|
+
Warming up --------------------------------------
|
|
63
|
+
inject 1.578k i/100ms
|
|
64
|
+
while 2.057k i/100ms
|
|
65
|
+
mean 9.855k i/100ms
|
|
66
|
+
Calculating -------------------------------------
|
|
67
|
+
inject 15.347k (± 8.6%) i/s - 77.322k in 5.076009s
|
|
68
|
+
while 21.669k (±14.5%) i/s - 106.964k in 5.074312s
|
|
69
|
+
mean 108.861k (± 8.9%) i/s - 542.025k in 5.021786s
|
|
70
|
+
# variance
|
|
71
|
+
Warming up --------------------------------------
|
|
72
|
+
inject 586.000 i/100ms
|
|
73
|
+
while 826.000 i/100ms
|
|
74
|
+
variance 8.475k i/100ms
|
|
75
|
+
Calculating -------------------------------------
|
|
76
|
+
inject 6.187k (± 6.7%) i/s - 31.058k in 5.043418s
|
|
77
|
+
while 8.597k (± 7.4%) i/s - 42.952k in 5.024587s
|
|
78
|
+
variance 84.702k (± 8.5%) i/s - 423.750k in 5.039936s
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+

|
|
26
82
|
|
|
27
83
|
## Development
|
|
28
84
|
|
|
@@ -32,5 +88,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
|
32
88
|
|
|
33
89
|
## Contributing
|
|
34
90
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
91
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mrkn/enumerable-statistics.
|
|
36
92
|
|
data/Rakefile
CHANGED
|
@@ -7,3 +7,14 @@ task :default => :spec
|
|
|
7
7
|
Rake::ExtensionTask.new('enumerable/statistics/extension')
|
|
8
8
|
|
|
9
9
|
RSpec::Core::RakeTask.new(:spec)
|
|
10
|
+
|
|
11
|
+
task :bench do
|
|
12
|
+
puts "# sum\n"
|
|
13
|
+
system('ruby bench/sum.rb')
|
|
14
|
+
|
|
15
|
+
puts "# mean\n"
|
|
16
|
+
system('ruby bench/mean.rb')
|
|
17
|
+
|
|
18
|
+
puts "# variance\n"
|
|
19
|
+
system('ruby bench/variance.rb')
|
|
20
|
+
end
|
data/bench/mean.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'enumerable/statistics'
|
|
2
|
+
require 'benchmark/ips'
|
|
3
|
+
|
|
4
|
+
Benchmark.ips do |x|
|
|
5
|
+
x.config(times: 5, warmup: 2)
|
|
6
|
+
|
|
7
|
+
n = 1_000
|
|
8
|
+
ary = Array.new(n) { rand }
|
|
9
|
+
|
|
10
|
+
x.report('inject') do
|
|
11
|
+
mean = ary.inject(:+) / n.to_f
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
x.report('while') do
|
|
15
|
+
i = 0
|
|
16
|
+
mean = 0
|
|
17
|
+
while i < n
|
|
18
|
+
mean += ary[i]
|
|
19
|
+
i += 1
|
|
20
|
+
end
|
|
21
|
+
mean /= n.to_f
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
x.report('mean') do
|
|
25
|
+
mean = ary.mean
|
|
26
|
+
end
|
|
27
|
+
end
|
data/bench/sum.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'enumerable/statistics'
|
|
2
|
+
require 'benchmark/ips'
|
|
3
|
+
|
|
4
|
+
Benchmark.ips do |x|
|
|
5
|
+
x.config(times: 5, warmup: 2)
|
|
6
|
+
|
|
7
|
+
n = 1_000
|
|
8
|
+
ary = Array.new(n) { rand }
|
|
9
|
+
|
|
10
|
+
x.report('inject') do
|
|
11
|
+
sum = ary.inject(:+)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
x.report('while') do
|
|
15
|
+
i = 0
|
|
16
|
+
sum = 0
|
|
17
|
+
while i < n
|
|
18
|
+
sum += ary[i]
|
|
19
|
+
i += 1
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
x.report('sum') do
|
|
24
|
+
sum = ary.sum
|
|
25
|
+
end
|
|
26
|
+
end
|
data/bench/variance.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'enumerable/statistics'
|
|
2
|
+
require 'benchmark/ips'
|
|
3
|
+
|
|
4
|
+
Benchmark.ips do |x|
|
|
5
|
+
x.config(times: 5, warmup: 2)
|
|
6
|
+
|
|
7
|
+
n = 1_000
|
|
8
|
+
ary = Array.new(n) { rand }
|
|
9
|
+
mean = ary.inject(:+) / n.to_f
|
|
10
|
+
|
|
11
|
+
x.report('inject') do
|
|
12
|
+
var = ary.inject(0.0) { |sum, x|
|
|
13
|
+
sum += (x - mean) ** 2
|
|
14
|
+
} / (n - 1).to_f
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
x.report('while') do
|
|
18
|
+
i = 0
|
|
19
|
+
var = 0
|
|
20
|
+
while i < n
|
|
21
|
+
var += (ary[i] - mean) ** 2
|
|
22
|
+
i += 1
|
|
23
|
+
end
|
|
24
|
+
mean /= (n - 1).to_f
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
x.report('variance') do
|
|
28
|
+
var = ary.variance
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -5,15 +5,28 @@
|
|
|
5
5
|
#if RUBY_API_VERSION_CODE >= 20400
|
|
6
6
|
/* for 2.4.0 or higher */
|
|
7
7
|
# define HAVE_ARRAY_SUM
|
|
8
|
+
# define HAVE_ENUM_SUM
|
|
8
9
|
# undef HAVE_RB_FIX_PLUS
|
|
9
10
|
# undef HAVE_RB_RATIONAL_PLUS
|
|
10
11
|
#elif RUBY_API_VERSION_CODE >= 20200
|
|
11
12
|
/* for 2.3.0 and 2.2.0 */
|
|
12
13
|
# undef HAVE_ARRAY_SUM
|
|
14
|
+
# undef HAVE_ENUM_SUM
|
|
13
15
|
# undef HAVE_RB_FIX_PLUS
|
|
14
16
|
# undef HAVE_RB_RATIONAL_PLUS
|
|
15
17
|
#endif
|
|
16
18
|
|
|
19
|
+
#ifndef RB_INTEGER_TYPE_P
|
|
20
|
+
# define RB_INTEGER_TYPE_P(obj) enum_stat_integer_type_p(obj)
|
|
21
|
+
static inline int
|
|
22
|
+
enum_stat_integer_type_p(VALUE obj)
|
|
23
|
+
{
|
|
24
|
+
return (FIXNUM_P(obj) ||
|
|
25
|
+
(!SPECIAL_CONST_P(obj) &&
|
|
26
|
+
BUILTIN_TYPE(obj) == RUBY_T_BIGNUM));
|
|
27
|
+
}
|
|
28
|
+
#endif
|
|
29
|
+
|
|
17
30
|
#ifndef HAVE_TYPE_STRUCT_RRATIONAL
|
|
18
31
|
struct RRational {
|
|
19
32
|
struct RBasic basic;
|
|
@@ -67,8 +80,14 @@ struct RComplex {
|
|
|
67
80
|
# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
|
|
68
81
|
#endif
|
|
69
82
|
|
|
70
|
-
|
|
71
|
-
|
|
83
|
+
#define SET_MEAN(v) do { if (mean_ptr) *mean_ptr = (v); } while (0)
|
|
84
|
+
#define SET_VARIANCE(v) do { if (variance_ptr) *variance_ptr = (v); } while (0)
|
|
85
|
+
|
|
86
|
+
static VALUE half_in_rational;
|
|
87
|
+
|
|
88
|
+
static ID idPow, idPLUS, idMINUS, idSTAR, idDIV, idGE;
|
|
89
|
+
static ID id_eqeq_p, id_idiv, id_negate, id_to_f, id_cmp;
|
|
90
|
+
static ID id_each, id_real_p, id_sum, id_population;
|
|
72
91
|
|
|
73
92
|
inline static VALUE
|
|
74
93
|
f_add(VALUE x, VALUE y)
|
|
@@ -99,7 +118,6 @@ f_real_p(VALUE x)
|
|
|
99
118
|
return rb_funcall(x, id_real_p, 0);
|
|
100
119
|
}
|
|
101
120
|
|
|
102
|
-
#ifndef HAVE_RB_FIX_PLUS
|
|
103
121
|
static VALUE
|
|
104
122
|
complex_new(VALUE klass, VALUE real, VALUE imag)
|
|
105
123
|
{
|
|
@@ -156,6 +174,7 @@ complex_add(VALUE self, VALUE other)
|
|
|
156
174
|
return rb_num_coerce_bin(self, other, idPLUS);
|
|
157
175
|
}
|
|
158
176
|
|
|
177
|
+
#ifndef HAVE_RB_FIX_PLUS
|
|
159
178
|
static VALUE
|
|
160
179
|
rb_fix_plus(VALUE x, VALUE y)
|
|
161
180
|
{
|
|
@@ -185,6 +204,170 @@ rb_fix_plus(VALUE x, VALUE y)
|
|
|
185
204
|
}
|
|
186
205
|
#endif
|
|
187
206
|
|
|
207
|
+
#ifndef HAVE_RB_INT_PLUS
|
|
208
|
+
static VALUE
|
|
209
|
+
rb_int_plus(VALUE x, VALUE y)
|
|
210
|
+
{
|
|
211
|
+
if (FIXNUM_P(x)) {
|
|
212
|
+
return rb_fix_plus(x, y);
|
|
213
|
+
}
|
|
214
|
+
else if (RB_TYPE_P(x, T_BIGNUM)) {
|
|
215
|
+
return rb_big_plus(x, y);
|
|
216
|
+
}
|
|
217
|
+
return rb_num_coerce_bin(x, y, '+');
|
|
218
|
+
}
|
|
219
|
+
#endif
|
|
220
|
+
|
|
221
|
+
#ifndef HAVE_RB_FIX_MINUS
|
|
222
|
+
static VALUE
|
|
223
|
+
rb_fix_minus(VALUE x, VALUE y)
|
|
224
|
+
{
|
|
225
|
+
if (FIXNUM_P(y)) {
|
|
226
|
+
long a, b, c;
|
|
227
|
+
VALUE r;
|
|
228
|
+
|
|
229
|
+
a = FIX2LONG(x);
|
|
230
|
+
b = FIX2LONG(y);
|
|
231
|
+
c = a - b;
|
|
232
|
+
r = LONG2NUM(c);
|
|
233
|
+
|
|
234
|
+
return r;
|
|
235
|
+
}
|
|
236
|
+
else if (RB_TYPE_P(y, T_BIGNUM)) {
|
|
237
|
+
x = rb_int2big(FIX2LONG(x));
|
|
238
|
+
return rb_big_minus(x, y);
|
|
239
|
+
}
|
|
240
|
+
else if (RB_TYPE_P(y, T_FLOAT)) {
|
|
241
|
+
return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
return rb_num_coerce_bin(x, y, '-');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
#endif
|
|
248
|
+
|
|
249
|
+
#ifndef HAVE_RB_INT_MINUS
|
|
250
|
+
VALUE
|
|
251
|
+
rb_int_minus(VALUE x, VALUE y)
|
|
252
|
+
{
|
|
253
|
+
if (FIXNUM_P(x)) {
|
|
254
|
+
return rb_fix_minus(x, y);
|
|
255
|
+
}
|
|
256
|
+
else if (RB_TYPE_P(x, T_BIGNUM)) {
|
|
257
|
+
return rb_big_minus(x, y);
|
|
258
|
+
}
|
|
259
|
+
return rb_num_coerce_bin(x, y, '-');
|
|
260
|
+
}
|
|
261
|
+
#endif
|
|
262
|
+
|
|
263
|
+
#ifndef HAVE_RB_INTEGER_FLOAT_CMP
|
|
264
|
+
static VALUE
|
|
265
|
+
rb_integer_float_cmp(VALUE x, VALUE y)
|
|
266
|
+
{
|
|
267
|
+
double yd = RFLOAT_VALUE(y);
|
|
268
|
+
double yi, yf;
|
|
269
|
+
VALUE rel;
|
|
270
|
+
|
|
271
|
+
if (isnan(yd))
|
|
272
|
+
return Qnil;
|
|
273
|
+
if (isinf(yd)) {
|
|
274
|
+
if (yd > 0.0) return INT2FIX(-1);
|
|
275
|
+
else return INT2FIX(1);
|
|
276
|
+
}
|
|
277
|
+
yf = modf(yd, &yi);
|
|
278
|
+
if (FIXNUM_P(x)) {
|
|
279
|
+
#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
|
|
280
|
+
double xd = (double)FIX2LONG(x);
|
|
281
|
+
if (xd < yd)
|
|
282
|
+
return INT2FIX(-1);
|
|
283
|
+
if (xd > yd)
|
|
284
|
+
return INT2FIX(1);
|
|
285
|
+
return INT2FIX(0);
|
|
286
|
+
#else
|
|
287
|
+
long xn, yn;
|
|
288
|
+
if (yi < FIXNUM_MIN)
|
|
289
|
+
return INT2FIX(1);
|
|
290
|
+
if (FIXNUM_MAX+1 <= yi)
|
|
291
|
+
return INT2FIX(-1);
|
|
292
|
+
xn = FIX2LONG(x);
|
|
293
|
+
yn = (long)yi;
|
|
294
|
+
if (xn < yn)
|
|
295
|
+
return INT2FIX(-1);
|
|
296
|
+
if (xn > yn)
|
|
297
|
+
return INT2FIX(1);
|
|
298
|
+
if (yf < 0.0)
|
|
299
|
+
return INT2FIX(1);
|
|
300
|
+
if (0.0 < yf)
|
|
301
|
+
return INT2FIX(-1);
|
|
302
|
+
return INT2FIX(0);
|
|
303
|
+
#endif
|
|
304
|
+
}
|
|
305
|
+
y = rb_dbl2big(yi);
|
|
306
|
+
rel = rb_big_cmp(x, y);
|
|
307
|
+
if (yf == 0.0 || rel != INT2FIX(0))
|
|
308
|
+
return rel;
|
|
309
|
+
if (yf < 0.0)
|
|
310
|
+
return INT2FIX(1);
|
|
311
|
+
return INT2FIX(-1);
|
|
312
|
+
}
|
|
313
|
+
#endif
|
|
314
|
+
|
|
315
|
+
static VALUE
|
|
316
|
+
fix_ge(VALUE x, VALUE y)
|
|
317
|
+
{
|
|
318
|
+
if (FIXNUM_P(y)) {
|
|
319
|
+
if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
|
|
320
|
+
return Qfalse;
|
|
321
|
+
}
|
|
322
|
+
else if (RB_TYPE_P(y, T_BIGNUM)) {
|
|
323
|
+
return rb_big_cmp(y, x) != INT2FIX(+1) ? Qtrue : Qfalse;
|
|
324
|
+
}
|
|
325
|
+
else if (RB_TYPE_P(y, T_FLOAT)) {
|
|
326
|
+
VALUE rel = rb_integer_float_cmp(x, y);
|
|
327
|
+
return rel == INT2FIX(1) || rel == INT2FIX(0) ? Qtrue : Qfalse;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
return rb_num_coerce_relop(x, y, idGE);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
#ifndef HAVE_RB_BIG_GE
|
|
335
|
+
static VALUE
|
|
336
|
+
rb_big_ge(VALUE x, VALUE y)
|
|
337
|
+
{
|
|
338
|
+
VALUE rel;
|
|
339
|
+
int n;
|
|
340
|
+
|
|
341
|
+
if (RB_INTEGER_TYPE_P(y)) {
|
|
342
|
+
rel = rb_big_cmp(x, y);
|
|
343
|
+
}
|
|
344
|
+
else if (RB_FLOAT_TYPE_P(y)) {
|
|
345
|
+
rel = rb_integer_float_cmp(x, y);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
return rb_num_coerce_relop(x, y, idGE);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (NIL_P(rel)) return Qfalse;
|
|
352
|
+
n = FIX2INT(rel);
|
|
353
|
+
return n >= 0 ? Qtrue : Qfalse;
|
|
354
|
+
}
|
|
355
|
+
#endif
|
|
356
|
+
|
|
357
|
+
#ifndef HAVE_RB_INT_GE
|
|
358
|
+
static VALUE
|
|
359
|
+
rb_int_ge(VALUE x, VALUE y)
|
|
360
|
+
{
|
|
361
|
+
if (FIXNUM_P(x)) {
|
|
362
|
+
return fix_ge(x, y);
|
|
363
|
+
}
|
|
364
|
+
else if (RB_TYPE_P(x, T_BIGNUM)) {
|
|
365
|
+
return rb_big_ge(x, y);
|
|
366
|
+
}
|
|
367
|
+
return Qnil;
|
|
368
|
+
}
|
|
369
|
+
#endif
|
|
370
|
+
|
|
188
371
|
#ifndef HAVE_RB_RATIONAL_PLUS
|
|
189
372
|
# define ZERO INT2FIX(0)
|
|
190
373
|
# define ONE INT2FIX(1)
|
|
@@ -459,7 +642,18 @@ rb_rational_plus(VALUE self, VALUE other)
|
|
|
459
642
|
}
|
|
460
643
|
#endif
|
|
461
644
|
|
|
462
|
-
|
|
645
|
+
/* call-seq:
|
|
646
|
+
* ary.sum
|
|
647
|
+
*
|
|
648
|
+
* Calculate the sum of the values in `ary`.
|
|
649
|
+
* This method utilizes
|
|
650
|
+
* [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
|
651
|
+
* to compensate the result precision when the `ary` includes Float values.
|
|
652
|
+
*
|
|
653
|
+
* Note that This library does not redefine `sum` method introduced in Ruby 2.4.
|
|
654
|
+
*
|
|
655
|
+
* @return [Number] A summation value
|
|
656
|
+
*/
|
|
463
657
|
static VALUE
|
|
464
658
|
ary_sum(int argc, VALUE* argv, VALUE ary)
|
|
465
659
|
{
|
|
@@ -558,7 +752,196 @@ not_exact:
|
|
|
558
752
|
|
|
559
753
|
return v;
|
|
560
754
|
}
|
|
755
|
+
|
|
756
|
+
static void
|
|
757
|
+
calculate_and_set_mean(VALUE *mean_ptr, VALUE sum, long const n)
|
|
758
|
+
{
|
|
759
|
+
if (RB_TYPE_P(sum, T_COMPLEX)) {
|
|
760
|
+
VALUE real_mean, imag_mean;
|
|
761
|
+
VALUE const real = RCOMPLEX(sum)->real;
|
|
762
|
+
VALUE const imag = RCOMPLEX(sum)->imag;
|
|
763
|
+
|
|
764
|
+
if (RB_FLOAT_TYPE_P(real))
|
|
765
|
+
real_mean = DBL2NUM(RFLOAT_VALUE(real) / n);
|
|
766
|
+
else
|
|
767
|
+
real_mean = rb_funcall(real, idDIV, 1, DBL2NUM(n));
|
|
768
|
+
|
|
769
|
+
if (RB_FLOAT_TYPE_P(imag))
|
|
770
|
+
imag_mean = DBL2NUM(RFLOAT_VALUE(imag) / n);
|
|
771
|
+
else
|
|
772
|
+
imag_mean = rb_funcall(imag, idDIV, 1, DBL2NUM(n));
|
|
773
|
+
|
|
774
|
+
SET_MEAN(complex_new(CLASS_OF(sum), real_mean, imag_mean));
|
|
775
|
+
}
|
|
776
|
+
else if (RB_FLOAT_TYPE_P(sum)) {
|
|
777
|
+
SET_MEAN(DBL2NUM(RFLOAT_VALUE(sum) / n));
|
|
778
|
+
}
|
|
779
|
+
else
|
|
780
|
+
SET_MEAN(rb_funcall(sum, idDIV, 1, DBL2NUM(n)));
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
static void
|
|
784
|
+
ary_mean_variance(VALUE ary, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
785
|
+
{
|
|
786
|
+
long i;
|
|
787
|
+
size_t n = 0;
|
|
788
|
+
double m = 0.0, m2 = 0.0, f = 0.0, c = 0.0;
|
|
789
|
+
|
|
790
|
+
SET_MEAN(DBL2NUM(0));
|
|
791
|
+
SET_VARIANCE(DBL2NUM(NAN));
|
|
792
|
+
|
|
793
|
+
if (RARRAY_LEN(ary) == 0)
|
|
794
|
+
return;
|
|
795
|
+
else if (RARRAY_LEN(ary) == 1) {
|
|
796
|
+
VALUE e = RARRAY_AREF(ary, 0);
|
|
797
|
+
if (rb_block_given_p())
|
|
798
|
+
e = rb_yield(e);
|
|
799
|
+
if (RB_TYPE_P(e, T_COMPLEX))
|
|
800
|
+
SET_MEAN(e);
|
|
801
|
+
else {
|
|
802
|
+
e = rb_Float(e);
|
|
803
|
+
SET_MEAN(e);
|
|
804
|
+
}
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (variance_ptr == NULL) {
|
|
809
|
+
VALUE init = DBL2NUM(0.0);
|
|
810
|
+
VALUE const sum = ary_sum(1, &init, ary);
|
|
811
|
+
long const n = RARRAY_LEN(ary);
|
|
812
|
+
calculate_and_set_mean(mean_ptr, sum, n);
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
|
817
|
+
double x, delta, y, t;
|
|
818
|
+
VALUE e;
|
|
819
|
+
|
|
820
|
+
n += 1;
|
|
821
|
+
|
|
822
|
+
e = RARRAY_AREF(ary, i);
|
|
823
|
+
if (rb_block_given_p())
|
|
824
|
+
e = rb_yield(e);
|
|
825
|
+
|
|
826
|
+
if (RB_FLOAT_TYPE_P(e))
|
|
827
|
+
x = RFLOAT_VALUE(e);
|
|
828
|
+
else if (FIXNUM_P(e))
|
|
829
|
+
x = FIX2LONG(e);
|
|
830
|
+
else if (RB_TYPE_P(e, T_BIGNUM))
|
|
831
|
+
x = rb_big2dbl(e);
|
|
832
|
+
else
|
|
833
|
+
x = rb_num2dbl(e);
|
|
834
|
+
|
|
835
|
+
y = x - c;
|
|
836
|
+
t = f + y;
|
|
837
|
+
c = (t - f) - y;
|
|
838
|
+
f = t;
|
|
839
|
+
|
|
840
|
+
delta = x - m;
|
|
841
|
+
m += delta / n;
|
|
842
|
+
m2 += delta * (x - m);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
SET_MEAN(DBL2NUM(f / n));
|
|
846
|
+
if (n >= 2) {
|
|
847
|
+
assert(n > ddof);
|
|
848
|
+
SET_VARIANCE(DBL2NUM(m2 / (n - ddof)));
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
static int
|
|
853
|
+
opt_population_p(VALUE opts)
|
|
854
|
+
{
|
|
855
|
+
ID kwargs = id_population;
|
|
856
|
+
VALUE population = Qfalse;
|
|
857
|
+
|
|
858
|
+
if (!NIL_P(opts)) {
|
|
859
|
+
#ifdef HAVE_RB_GET_KWARGS
|
|
860
|
+
rb_get_kwargs(opts, &kwargs, 0, 1, &population);
|
|
861
|
+
#else
|
|
862
|
+
VALUE val = rb_hash_aref(opts, ID2SYM(id_population));
|
|
863
|
+
population = NIL_P(val) ? population : val;
|
|
561
864
|
#endif
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
return RTEST(population);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/* call-seq:
|
|
871
|
+
* eary.mean_variance(population: false)
|
|
872
|
+
*
|
|
873
|
+
* Calculate a mean and a variance of the values in `ary`.
|
|
874
|
+
* The first element of the result array is the mean, and the second is the variance.
|
|
875
|
+
*
|
|
876
|
+
* When the `population:` keyword parameter is `true`,
|
|
877
|
+
* the variance is calculated as a population variance (divided by $n$).
|
|
878
|
+
* The default `population:` keyword parameter is `false`;
|
|
879
|
+
* this means the variance is a sample variance (divided by $n-1$).
|
|
880
|
+
*
|
|
881
|
+
* This method scan values in `ary` only once,
|
|
882
|
+
* and does not cache the values on memory.
|
|
883
|
+
*
|
|
884
|
+
* @return (mean, variance) Two element array consists of mean and variance values
|
|
885
|
+
*/
|
|
886
|
+
static VALUE
|
|
887
|
+
ary_mean_variance_m(int argc, VALUE* argv, VALUE ary)
|
|
888
|
+
{
|
|
889
|
+
VALUE opts, mean, variance;
|
|
890
|
+
size_t ddof = 1;
|
|
891
|
+
|
|
892
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
893
|
+
if (opt_population_p(opts))
|
|
894
|
+
ddof = 0;
|
|
895
|
+
|
|
896
|
+
ary_mean_variance(ary, &mean, &variance, ddof);
|
|
897
|
+
return rb_assoc_new(mean, variance);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* call-seq:
|
|
901
|
+
* ary.mean
|
|
902
|
+
*
|
|
903
|
+
* Calculate a mean of the values in `ary`.
|
|
904
|
+
* This method utilizes
|
|
905
|
+
* [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
|
906
|
+
* to compensate the result precision when the `enum` includes Float values.
|
|
907
|
+
*
|
|
908
|
+
* @return [Number] A mean value
|
|
909
|
+
*/
|
|
910
|
+
static VALUE
|
|
911
|
+
ary_mean(VALUE ary)
|
|
912
|
+
{
|
|
913
|
+
VALUE mean;
|
|
914
|
+
ary_mean_variance(ary, &mean, NULL, 1);
|
|
915
|
+
return mean;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/* call-seq:
|
|
919
|
+
* ary.variance(population: false)
|
|
920
|
+
*
|
|
921
|
+
* Calculate a variance of the values in `ary`.
|
|
922
|
+
* This method scan values in `ary` only once,
|
|
923
|
+
* and does not cache the values on memory.
|
|
924
|
+
*
|
|
925
|
+
* When the `population:` keyword parameter is `true`,
|
|
926
|
+
* the variance is calculated as a population variance (divided by $n$).
|
|
927
|
+
* The default `population:` keyword parameter is `false`;
|
|
928
|
+
* this means the variance is a sample variance (divided by $n-1$).
|
|
929
|
+
*
|
|
930
|
+
* @return [Number] A variance value
|
|
931
|
+
*/
|
|
932
|
+
static VALUE
|
|
933
|
+
ary_variance(int argc, VALUE* argv, VALUE ary)
|
|
934
|
+
{
|
|
935
|
+
VALUE opts, variance;
|
|
936
|
+
size_t ddof = 1;
|
|
937
|
+
|
|
938
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
939
|
+
if (opt_population_p(opts))
|
|
940
|
+
ddof = 0;
|
|
941
|
+
|
|
942
|
+
ary_mean_variance(ary, NULL, &variance, ddof);
|
|
943
|
+
return variance;
|
|
944
|
+
}
|
|
562
945
|
|
|
563
946
|
#define ENUM_WANT_SVALUE() do { \
|
|
564
947
|
e = rb_enum_values_pack(argc, argv); \
|
|
@@ -566,27 +949,28 @@ not_exact:
|
|
|
566
949
|
|
|
567
950
|
struct enum_sum_memo {
|
|
568
951
|
VALUE v, r;
|
|
569
|
-
long n;
|
|
952
|
+
long n, count;
|
|
570
953
|
double f, c;
|
|
571
954
|
int block_given;
|
|
572
955
|
int float_value;
|
|
573
956
|
};
|
|
574
957
|
|
|
575
|
-
static
|
|
576
|
-
|
|
958
|
+
static void
|
|
959
|
+
sum_iter(VALUE e, struct enum_sum_memo *memo)
|
|
577
960
|
{
|
|
578
|
-
|
|
961
|
+
int const unused = (assert(memo != NULL), 0);
|
|
962
|
+
|
|
579
963
|
long n = memo->n;
|
|
580
964
|
VALUE v = memo->v;
|
|
581
965
|
VALUE r = memo->r;
|
|
582
966
|
double f = memo->f;
|
|
583
967
|
double c = memo->c;
|
|
584
968
|
|
|
585
|
-
ENUM_WANT_SVALUE();
|
|
586
|
-
|
|
587
969
|
if (memo->block_given)
|
|
588
970
|
e = rb_yield(e);
|
|
589
971
|
|
|
972
|
+
memo->count += 1;
|
|
973
|
+
|
|
590
974
|
if (memo->float_value)
|
|
591
975
|
goto float_value;
|
|
592
976
|
|
|
@@ -659,20 +1043,72 @@ enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(e, args))
|
|
|
659
1043
|
memo->r = r;
|
|
660
1044
|
memo->f = f;
|
|
661
1045
|
memo->c = c;
|
|
1046
|
+
(void)unused;
|
|
1047
|
+
}
|
|
662
1048
|
|
|
1049
|
+
static VALUE
|
|
1050
|
+
enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(e, args))
|
|
1051
|
+
{
|
|
1052
|
+
ENUM_WANT_SVALUE();
|
|
1053
|
+
sum_iter(e, (struct enum_sum_memo *) args);
|
|
663
1054
|
return Qnil;
|
|
664
1055
|
}
|
|
665
1056
|
|
|
666
|
-
static
|
|
667
|
-
|
|
1057
|
+
static int
|
|
1058
|
+
hash_sum_i(VALUE key, VALUE value, VALUE arg)
|
|
668
1059
|
{
|
|
669
|
-
struct enum_sum_memo
|
|
1060
|
+
sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg);
|
|
1061
|
+
return ST_CONTINUE;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
static void
|
|
1065
|
+
hash_sum(VALUE hash, struct enum_sum_memo *memo)
|
|
1066
|
+
{
|
|
1067
|
+
assert(RB_TYPE_P(hash, T_HASH));
|
|
1068
|
+
assert(memo != NULL);
|
|
670
1069
|
|
|
671
|
-
|
|
672
|
-
|
|
1070
|
+
rb_hash_foreach(hash, hash_sum_i, (VALUE)memo);
|
|
1071
|
+
}
|
|
673
1072
|
|
|
674
|
-
|
|
1073
|
+
static void
|
|
1074
|
+
int_range_sum_count(VALUE beg, VALUE end, int excl,
|
|
1075
|
+
VALUE init, VALUE *sum_ptr, long *count_ptr)
|
|
1076
|
+
{
|
|
1077
|
+
if (excl) {
|
|
1078
|
+
if (FIXNUM_P(end))
|
|
1079
|
+
end = LONG2FIX(FIX2LONG(end) - 1);
|
|
1080
|
+
else
|
|
1081
|
+
end = rb_big_minus(end, LONG2FIX(1));
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
if (rb_int_ge(end, beg)) {
|
|
1085
|
+
VALUE a;
|
|
1086
|
+
a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
|
|
1087
|
+
a = f_mul(a, rb_int_plus(end, beg));
|
|
1088
|
+
a = f_idiv(a, LONG2FIX(2));
|
|
1089
|
+
if (sum_ptr)
|
|
1090
|
+
*sum_ptr = rb_int_plus(init, a);
|
|
1091
|
+
if (count_ptr)
|
|
1092
|
+
*count_ptr = a;
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
675
1095
|
|
|
1096
|
+
if (sum_ptr)
|
|
1097
|
+
*sum_ptr = init;
|
|
1098
|
+
if (count_ptr)
|
|
1099
|
+
*count_ptr = 0;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
static void
|
|
1103
|
+
enum_sum_count(VALUE obj, VALUE init, VALUE *sum_ptr, long *count_ptr)
|
|
1104
|
+
{
|
|
1105
|
+
struct enum_sum_memo memo;
|
|
1106
|
+
VALUE beg, end;
|
|
1107
|
+
int excl;
|
|
1108
|
+
|
|
1109
|
+
memo.count = 0;
|
|
1110
|
+
memo.v = init;
|
|
1111
|
+
memo.block_given = rb_block_given_p();
|
|
676
1112
|
memo.n = 0;
|
|
677
1113
|
memo.r = Qundef;
|
|
678
1114
|
|
|
@@ -681,80 +1117,407 @@ enum_stat_sum(int argc, VALUE* argv, VALUE obj)
|
|
|
681
1117
|
memo.c = 0.0;
|
|
682
1118
|
}
|
|
683
1119
|
|
|
684
|
-
|
|
1120
|
+
if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
|
|
1121
|
+
if (!rb_block_given_p() && !memo.float_value &&
|
|
1122
|
+
RB_INTEGER_TYPE_P(beg) && RB_INTEGER_TYPE_P(end)) {
|
|
1123
|
+
int_range_sum_count(beg, end, excl, memo.v, sum_ptr, count_ptr);
|
|
1124
|
+
return;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
if (RB_TYPE_P(obj, T_HASH) &&
|
|
1129
|
+
rb_method_basic_definition_p(CLASS_OF(obj), id_each))
|
|
1130
|
+
hash_sum(obj, &memo);
|
|
1131
|
+
else
|
|
1132
|
+
rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
|
|
685
1133
|
|
|
686
1134
|
if (memo.float_value) {
|
|
687
|
-
|
|
1135
|
+
if (sum_ptr)
|
|
1136
|
+
*sum_ptr = DBL2NUM(memo.f);
|
|
688
1137
|
}
|
|
689
1138
|
else {
|
|
690
1139
|
if (memo.n != 0)
|
|
691
1140
|
memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
|
|
692
1141
|
if (memo.r != Qundef)
|
|
693
1142
|
memo.v = rb_rational_plus(memo.r, memo.v);
|
|
694
|
-
|
|
1143
|
+
if (sum_ptr)
|
|
1144
|
+
*sum_ptr = memo.v;
|
|
695
1145
|
}
|
|
1146
|
+
|
|
1147
|
+
if (count_ptr)
|
|
1148
|
+
*count_ptr = memo.count;
|
|
696
1149
|
}
|
|
697
1150
|
|
|
1151
|
+
/* call-seq:
|
|
1152
|
+
* enum.sum
|
|
1153
|
+
*
|
|
1154
|
+
* Calculate the sum of the values in `enum`.
|
|
1155
|
+
* This method utilizes
|
|
1156
|
+
* [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
|
1157
|
+
* to compensate the result precision when the `enum` includes Float values.
|
|
1158
|
+
*
|
|
1159
|
+
* Note that This library does not redefine `sum` method introduced in Ruby 2.4.
|
|
1160
|
+
*
|
|
1161
|
+
* @return [Number] A summation value
|
|
1162
|
+
*/
|
|
698
1163
|
static VALUE
|
|
699
|
-
|
|
1164
|
+
enum_sum(int argc, VALUE* argv, VALUE obj)
|
|
700
1165
|
{
|
|
701
|
-
|
|
1166
|
+
VALUE sum, init;
|
|
1167
|
+
|
|
1168
|
+
if (rb_scan_args(argc, argv, "01", &init) == 0)
|
|
1169
|
+
init = LONG2FIX(0);
|
|
1170
|
+
|
|
1171
|
+
enum_sum_count(obj, init, &sum, NULL);
|
|
1172
|
+
|
|
1173
|
+
return sum;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
struct enum_mean_variance_memo {
|
|
1177
|
+
int block_given;
|
|
1178
|
+
long n;
|
|
1179
|
+
double m, m2, f, c;
|
|
1180
|
+
};
|
|
1181
|
+
|
|
1182
|
+
static void
|
|
1183
|
+
mean_variance_iter(VALUE e, struct enum_mean_variance_memo *memo)
|
|
1184
|
+
{
|
|
1185
|
+
int const unused = (assert(memo != NULL), 0);
|
|
1186
|
+
|
|
1187
|
+
double x, delta, y, t;
|
|
1188
|
+
|
|
1189
|
+
long n = memo->n;
|
|
1190
|
+
double m = memo->m;
|
|
1191
|
+
double m2 = memo->m2;
|
|
1192
|
+
double f = memo->f;
|
|
1193
|
+
double c = memo->c;
|
|
1194
|
+
|
|
1195
|
+
if (memo->block_given)
|
|
1196
|
+
e = rb_yield(e);
|
|
1197
|
+
|
|
1198
|
+
n += 1;
|
|
1199
|
+
|
|
1200
|
+
if (RB_FLOAT_TYPE_P(e))
|
|
1201
|
+
x = RFLOAT_VALUE(e);
|
|
1202
|
+
else if (FIXNUM_P(e))
|
|
1203
|
+
x = FIX2LONG(e);
|
|
1204
|
+
else if (RB_TYPE_P(e, T_BIGNUM))
|
|
1205
|
+
x = rb_big2dbl(e);
|
|
1206
|
+
else {
|
|
1207
|
+
x = rb_num2dbl(e);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
y = x - c;
|
|
1211
|
+
t = f + y;
|
|
1212
|
+
c = (t - f) - y;
|
|
1213
|
+
f = t;
|
|
1214
|
+
|
|
1215
|
+
delta = x - m;
|
|
1216
|
+
m += delta / n;
|
|
1217
|
+
m2 += delta * (x - m);
|
|
1218
|
+
|
|
1219
|
+
memo->n = n;
|
|
1220
|
+
memo->m = m;
|
|
1221
|
+
memo->m2 = m2;
|
|
1222
|
+
memo->f = f;
|
|
1223
|
+
memo->c = c;
|
|
1224
|
+
(void)unused;
|
|
702
1225
|
}
|
|
703
1226
|
|
|
704
1227
|
static VALUE
|
|
705
|
-
|
|
1228
|
+
enum_mean_variance_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(e, args))
|
|
1229
|
+
{
|
|
1230
|
+
struct enum_mean_variance_memo *memo = (struct enum_mean_variance_memo *)args;
|
|
1231
|
+
ENUM_WANT_SVALUE();
|
|
1232
|
+
mean_variance_iter(e, (struct enum_sum_memo *) args);
|
|
1233
|
+
return Qnil;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
static int
|
|
1237
|
+
hash_mean_variance_i(VALUE key, VALUE value, VALUE arg)
|
|
706
1238
|
{
|
|
707
|
-
|
|
708
|
-
return
|
|
1239
|
+
mean_variance_iter(rb_assoc_new(key, value), (struct enum_mean_variance_memo *) arg);
|
|
1240
|
+
return ST_CONTINUE;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
static void
|
|
1244
|
+
hash_mean_variance(VALUE hash, struct enum_mean_variance_memo *memo)
|
|
1245
|
+
{
|
|
1246
|
+
assert(RB_TYPE_P(hash, T_HASH));
|
|
1247
|
+
assert(memo != NULL);
|
|
1248
|
+
|
|
1249
|
+
rb_hash_foreach(hash, hash_mean_variance_i, (VALUE)memo);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
static void
|
|
1253
|
+
enum_mean_variance(VALUE obj, VALUE *mean_ptr, VALUE *variance_ptr, size_t ddof)
|
|
1254
|
+
{
|
|
1255
|
+
struct enum_mean_variance_memo memo;
|
|
1256
|
+
|
|
1257
|
+
SET_MEAN(DBL2NUM(0));
|
|
1258
|
+
SET_VARIANCE(DBL2NUM(NAN));
|
|
1259
|
+
|
|
1260
|
+
if (variance_ptr == NULL) {
|
|
1261
|
+
long n;
|
|
1262
|
+
VALUE sum;
|
|
1263
|
+
VALUE init = DBL2NUM(0.0);
|
|
1264
|
+
enum_sum_count(obj, init, &sum, &n);
|
|
1265
|
+
if (n > 0)
|
|
1266
|
+
calculate_and_set_mean(mean_ptr, sum, n);
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
memo.block_given = rb_block_given_p();
|
|
1271
|
+
memo.n = 0;
|
|
1272
|
+
memo.m = 0.0;
|
|
1273
|
+
memo.m2 = 0.0;
|
|
1274
|
+
memo.f = 0.0;
|
|
1275
|
+
memo.c = 0.0;
|
|
1276
|
+
|
|
1277
|
+
if (RB_TYPE_P(obj, T_HASH) &&
|
|
1278
|
+
rb_method_basic_definition_p(CLASS_OF(obj), id_each))
|
|
1279
|
+
hash_mean_variance(obj, &memo);
|
|
1280
|
+
else
|
|
1281
|
+
rb_block_call(obj, id_each, 0, 0, enum_mean_variance_iter_i, (VALUE)&memo);
|
|
1282
|
+
|
|
1283
|
+
if (memo.n == 0)
|
|
1284
|
+
return;
|
|
1285
|
+
else if (memo.n == 1)
|
|
1286
|
+
SET_MEAN(DBL2NUM(memo.f));
|
|
1287
|
+
else {
|
|
1288
|
+
SET_MEAN(DBL2NUM(memo.f / memo.n));
|
|
1289
|
+
|
|
1290
|
+
assert(memo.n > ddof);
|
|
1291
|
+
SET_VARIANCE(DBL2NUM(memo.m2 / (double)(memo.n - ddof)));
|
|
1292
|
+
}
|
|
709
1293
|
}
|
|
710
1294
|
|
|
1295
|
+
/* call-seq:
|
|
1296
|
+
* enum.mean_variance(population: false)
|
|
1297
|
+
*
|
|
1298
|
+
* Calculate a mean and a variance of the values in `enum`.
|
|
1299
|
+
* The first element of the result array is the mean, and the second is the variance.
|
|
1300
|
+
*
|
|
1301
|
+
* When the `population:` keyword parameter is `true`,
|
|
1302
|
+
* the variance is calculated as a population variance (divided by $n$).
|
|
1303
|
+
* The default `population:` keyword parameter is `false`;
|
|
1304
|
+
* this means the variance is a sample variance (divided by $n-1$).
|
|
1305
|
+
*
|
|
1306
|
+
* This method scan values in `enum` only once,
|
|
1307
|
+
* and does not cache the values on memory.
|
|
1308
|
+
*
|
|
1309
|
+
* @return (mean, variance) Two element array consists of mean and variance values
|
|
1310
|
+
*/
|
|
711
1311
|
static VALUE
|
|
712
|
-
|
|
1312
|
+
enum_mean_variance_m(int argc, VALUE* argv, VALUE obj)
|
|
713
1313
|
{
|
|
714
|
-
VALUE
|
|
715
|
-
|
|
1314
|
+
VALUE opts, mean, variance;
|
|
1315
|
+
size_t ddof = 1;
|
|
1316
|
+
|
|
1317
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
1318
|
+
if (opt_population_p(opts))
|
|
1319
|
+
ddof = 0;
|
|
1320
|
+
|
|
1321
|
+
enum_mean_variance(obj, &mean, &variance, ddof);
|
|
1322
|
+
return rb_assoc_new(mean, variance);
|
|
716
1323
|
}
|
|
717
1324
|
|
|
1325
|
+
/* call-seq:
|
|
1326
|
+
* enum.mean
|
|
1327
|
+
*
|
|
1328
|
+
* Calculate a mean of the values in `enum`.
|
|
1329
|
+
* This method utilizes
|
|
1330
|
+
* [Kahan summation algorithm](https://en.wikipedia.org/wiki/Kahan_summation_algorithm)
|
|
1331
|
+
* to compensate the result precision when the `enum` includes Float values.
|
|
1332
|
+
*
|
|
1333
|
+
* @return [Number] A mean value
|
|
1334
|
+
*/
|
|
718
1335
|
static VALUE
|
|
719
|
-
|
|
1336
|
+
enum_mean(VALUE obj)
|
|
720
1337
|
{
|
|
721
|
-
VALUE
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
RARRAY_ASET(ary, 1, stddev);
|
|
725
|
-
return ary;
|
|
1338
|
+
VALUE mean;
|
|
1339
|
+
enum_mean_variance(obj, &mean, NULL, 1);
|
|
1340
|
+
return mean;
|
|
726
1341
|
}
|
|
727
1342
|
|
|
1343
|
+
/* call-seq:
|
|
1344
|
+
* enum.variance(population: false)
|
|
1345
|
+
*
|
|
1346
|
+
* Calculate a variance of the values in `enum`.
|
|
1347
|
+
* This method scan values in `enum` only once,
|
|
1348
|
+
* and does not cache the values on memory.
|
|
1349
|
+
*
|
|
1350
|
+
* When the `population:` keyword parameter is `true`,
|
|
1351
|
+
* the variance is calculated as a population variance (divided by $n$).
|
|
1352
|
+
* The default `population:` keyword parameter is `false`;
|
|
1353
|
+
* this means the variance is a sample variance (divided by $n-1$).
|
|
1354
|
+
*
|
|
1355
|
+
* @return [Number] A variance value
|
|
1356
|
+
*/
|
|
728
1357
|
static VALUE
|
|
729
|
-
|
|
1358
|
+
enum_variance(int argc, VALUE* argv, VALUE obj)
|
|
730
1359
|
{
|
|
731
|
-
VALUE
|
|
732
|
-
|
|
1360
|
+
VALUE opts, variance;
|
|
1361
|
+
size_t ddof = 1;
|
|
1362
|
+
|
|
1363
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
1364
|
+
if (opt_population_p(opts))
|
|
1365
|
+
ddof = 0;
|
|
1366
|
+
|
|
1367
|
+
enum_mean_variance(obj, NULL, &variance, ddof);
|
|
1368
|
+
return variance;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
static VALUE
|
|
1372
|
+
sqrt_value(VALUE x)
|
|
1373
|
+
{
|
|
1374
|
+
if (RB_INTEGER_TYPE_P(x) || RB_FLOAT_TYPE_P(x) || RB_TYPE_P(x, T_RATIONAL)) {
|
|
1375
|
+
double f = NUM2DBL(x);
|
|
1376
|
+
return DBL2NUM(sqrt(f));
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
return rb_funcall(x, idPow, 1, half_in_rational);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/* call-seq:
|
|
1383
|
+
* enum.mean_stdev(population: false)
|
|
1384
|
+
*
|
|
1385
|
+
* Calculate a mean and a standard deviation of the values in `enum`.
|
|
1386
|
+
* The first element of the result array is the mean,
|
|
1387
|
+
* and the second is the standard deviation.
|
|
1388
|
+
*
|
|
1389
|
+
* This method is equivalent to:
|
|
1390
|
+
*
|
|
1391
|
+
* ```ruby
|
|
1392
|
+
* def mean_stdev(population: false)
|
|
1393
|
+
* m, v = mean_variance(population: population)
|
|
1394
|
+
* [m, Math.sqrt(v)]
|
|
1395
|
+
* end
|
|
1396
|
+
* ```
|
|
1397
|
+
*
|
|
1398
|
+
* @return (mean, stdev)
|
|
1399
|
+
*/
|
|
1400
|
+
static VALUE
|
|
1401
|
+
enum_mean_stdev(int argc, VALUE* argv, VALUE obj)
|
|
1402
|
+
{
|
|
1403
|
+
VALUE opts, mean, variance;
|
|
1404
|
+
size_t ddof = 1;
|
|
1405
|
+
|
|
1406
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
1407
|
+
if (opt_population_p(opts))
|
|
1408
|
+
ddof = 0;
|
|
1409
|
+
|
|
1410
|
+
enum_mean_variance(obj, &mean, &variance, ddof);
|
|
1411
|
+
VALUE stdev = sqrt_value(variance);
|
|
1412
|
+
return rb_assoc_new(mean, stdev);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
/* call-seq:
|
|
1416
|
+
* enum.stdev(population: false)
|
|
1417
|
+
*
|
|
1418
|
+
* Calculate a standard deviation of the values in `enum`.
|
|
1419
|
+
*
|
|
1420
|
+
* This method is equivalent to:
|
|
1421
|
+
*
|
|
1422
|
+
* ```ruby
|
|
1423
|
+
* Math.sqrt(enum.variance(population: population))
|
|
1424
|
+
* ```
|
|
1425
|
+
*
|
|
1426
|
+
* @return [Number] A standard deviation value
|
|
1427
|
+
*/
|
|
1428
|
+
static VALUE
|
|
1429
|
+
enum_stdev(int argc, VALUE* argv, VALUE obj)
|
|
1430
|
+
{
|
|
1431
|
+
VALUE variance = enum_variance(argc, argv, obj);
|
|
1432
|
+
VALUE stdev = sqrt_value(variance);
|
|
1433
|
+
return stdev;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
/* call-seq:
|
|
1437
|
+
* ary.mean_stdev(population: false)
|
|
1438
|
+
*
|
|
1439
|
+
* Calculate a mean and a standard deviation of the values in `ary`.
|
|
1440
|
+
* The first element of the result array is the mean,
|
|
1441
|
+
* and the second is the standard deviation.
|
|
1442
|
+
*
|
|
1443
|
+
* This method is equivalent to:
|
|
1444
|
+
*
|
|
1445
|
+
* ```ruby
|
|
1446
|
+
* def mean_stdev(population: false)
|
|
1447
|
+
* m, v = mean_variance(population: population)
|
|
1448
|
+
* [m, Math.sqrt(v)]
|
|
1449
|
+
* end
|
|
1450
|
+
* ```
|
|
1451
|
+
*
|
|
1452
|
+
* @return (mean, stdev)
|
|
1453
|
+
*/
|
|
1454
|
+
static VALUE
|
|
1455
|
+
ary_mean_stdev(int argc, VALUE* argv, VALUE ary)
|
|
1456
|
+
{
|
|
1457
|
+
VALUE opts, mean, variance;
|
|
1458
|
+
size_t ddof = 1;
|
|
1459
|
+
|
|
1460
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
1461
|
+
if (opt_population_p(opts))
|
|
1462
|
+
ddof = 0;
|
|
1463
|
+
|
|
1464
|
+
ary_mean_variance(ary, &mean, &variance, ddof);
|
|
1465
|
+
VALUE stdev = sqrt_value(variance);
|
|
1466
|
+
return rb_assoc_new(mean, stdev);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
/* call-seq:
|
|
1470
|
+
* ary.stdev(population: false)
|
|
1471
|
+
*
|
|
1472
|
+
* Calculate a standard deviation of the values in `ary`.
|
|
1473
|
+
*
|
|
1474
|
+
* This method is equivalent to:
|
|
1475
|
+
*
|
|
1476
|
+
* ```ruby
|
|
1477
|
+
* Math.sqrt(ary.variance(population: population))
|
|
1478
|
+
* ```
|
|
1479
|
+
*
|
|
1480
|
+
* @return [Number] A standard deviation value
|
|
1481
|
+
*/
|
|
1482
|
+
static VALUE
|
|
1483
|
+
ary_stdev(int argc, VALUE* argv, VALUE ary)
|
|
1484
|
+
{
|
|
1485
|
+
VALUE variance = ary_variance(argc, argv, ary);
|
|
1486
|
+
VALUE stdev = sqrt_value(variance);
|
|
1487
|
+
return stdev;
|
|
733
1488
|
}
|
|
734
1489
|
|
|
735
1490
|
void
|
|
736
1491
|
Init_extension(void)
|
|
737
1492
|
{
|
|
738
|
-
|
|
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);
|
|
1493
|
+
#ifndef HAVE_ENUM_SUM
|
|
1494
|
+
rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
|
|
748
1495
|
#endif
|
|
749
1496
|
|
|
1497
|
+
rb_define_method(rb_mEnumerable, "mean_variance", enum_mean_variance_m, -1);
|
|
1498
|
+
rb_define_method(rb_mEnumerable, "mean", enum_mean, 0);
|
|
1499
|
+
rb_define_method(rb_mEnumerable, "variance", enum_variance, -1);
|
|
1500
|
+
rb_define_method(rb_mEnumerable, "mean_stdev", enum_mean_stdev, -1);
|
|
1501
|
+
rb_define_method(rb_mEnumerable, "stdev", enum_stdev, -1);
|
|
1502
|
+
|
|
750
1503
|
#ifndef HAVE_ARRAY_SUM
|
|
751
1504
|
rb_define_method(rb_cArray, "sum", ary_sum, -1);
|
|
752
1505
|
#endif
|
|
1506
|
+
rb_define_method(rb_cArray, "mean_variance", ary_mean_variance_m, -1);
|
|
1507
|
+
rb_define_method(rb_cArray, "mean", ary_mean, 0);
|
|
1508
|
+
rb_define_method(rb_cArray, "variance", ary_variance, -1);
|
|
1509
|
+
rb_define_method(rb_cArray, "mean_stdev", ary_mean_stdev, -1);
|
|
1510
|
+
rb_define_method(rb_cArray, "stdev", ary_stdev, -1);
|
|
1511
|
+
|
|
1512
|
+
half_in_rational = nurat_s_new_internal(rb_cRational, INT2FIX(1), INT2FIX(2));
|
|
1513
|
+
rb_gc_register_mark_object(half_in_rational);
|
|
753
1514
|
|
|
754
1515
|
idPLUS = '+';
|
|
755
1516
|
idMINUS = '-';
|
|
756
1517
|
idSTAR = '*';
|
|
1518
|
+
idDIV = '/';
|
|
757
1519
|
idPow = rb_intern("**");
|
|
1520
|
+
idGE = rb_intern(">=");
|
|
758
1521
|
id_eqeq_p = rb_intern("==");
|
|
759
1522
|
id_idiv = rb_intern("div");
|
|
760
1523
|
id_negate = rb_intern("-@");
|
|
@@ -762,4 +1525,6 @@ Init_extension(void)
|
|
|
762
1525
|
id_cmp = rb_intern("<=>");
|
|
763
1526
|
id_each = rb_intern("each");
|
|
764
1527
|
id_real_p = rb_intern("real?");
|
|
1528
|
+
id_sum = rb_intern("sum");
|
|
1529
|
+
id_population = rb_intern("population");
|
|
765
1530
|
}
|