tests fail on i386 (32-bit x86)
Hi,
When I run enumerable-statistics tests on a i386 userspace (i.e. 32-bit x86), I get several test failures. Comparing floating point numbers for equality is not really reliable, and You Should Not Do It(TM).
1) Hash#sum for {:a=>(100000000/1), :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
2) Hash#sum for {:a=>1.0e-09, :b=>(100000000/1), :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09, :l=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
3) Hash#sum for {:a=>100000000, :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
4) Enumerable#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 8333333.333333335
Failure/Error: it { is_expected.to eq(x) }
expected: 8333333.333333335
got: 8333333.333333333
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
5) Enumerable#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 909090909090909.4]
Failure/Error: it { is_expected.to eq([m, var]) }
expected: [9090909.090909092, 909090909090909.4]
got: [9090909.090909092, 909090909090909.0]
(compared using ==)
# ./spec/enum_spec.rb:237:in `block (4 levels) in <top (required)>'
6) Enumerable#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 30151134.457776368]
Failure/Error: it { is_expected.to eq([m, sd]) }
expected: [9090909.090909092, 30151134.457776368]
got: [9090909.090909092, 30151134.45777636]
(compared using ==)
# ./spec/enum_spec.rb:422:in `block (4 levels) in <top (required)>'
7) Enumerable#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 909090909090909.4
Failure/Error: it { is_expected.to eq(x) }
expected: 909090909090909.4
got: 909090909090909.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
8) Enumerable#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 30151134.457776368
Failure/Error: it { is_expected.to eq(x) }
expected: 30151134.457776368
got: 30151134.45777636
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
9) Array#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 909090909090909.4
Failure/Error: it { is_expected.to eq(x) }
expected: 909090909090909.4
got: 909090909090909.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
10) Array#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 30151134.457776368]
Failure/Error: it { is_expected.to eq([m, sd]) }
expected: [9090909.090909092, 30151134.457776368]
got: [9090909.090909092, 30151134.45777636]
(compared using ==)
# ./spec/array_spec.rb:335:in `block (4 levels) in <top (required)>'
11) Array#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 30151134.457776368
Failure/Error: it { is_expected.to eq(x) }
expected: 30151134.457776368
got: 30151134.45777636
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
12) Array#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 909090909090909.4]
Failure/Error: it { is_expected.to eq([m, var]) }
expected: [9090909.090909092, 909090909090909.4]
got: [9090909.090909092, 909090909090909.0]
(compared using ==)
# ./spec/array_spec.rb:240:in `block (4 levels) in <top (required)>'
13) Array#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 8333333.333333335
Failure/Error: it { is_expected.to eq(x) }
expected: 8333333.333333335
got: 8333333.333333333
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
I tried to come up with a patch for this but wasn't able to grok all the rspec macros in there. This here fixes 7 of those 13 failures:
diff --git a/spec/support/macros.rb b/spec/support/macros.rb
index 6d3dd6e..3ae99dd 100644
--- a/spec/support/macros.rb
+++ b/spec/support/macros.rb
@@ -45,7 +45,7 @@ module Enumerable
def it_equals_with_type(x, type)
it { is_expected.to be_an(type) }
- it { is_expected.to eq(x) }
+ it { is_expected.to be_within(0.0000001).of(x) }
end
def it_is_int_equal(n)
The remaining ones are:
Failed examples:
rspec ./spec/enum_spec.rb:237 # Enumerable#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 909090909090909.4]
rspec ./spec/enum_spec.rb[1:2:7:2] # Enumerable#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to be within 1.0e-07 of 909090909090909.4
rspec ./spec/enum_spec.rb:422 # Enumerable#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 30151134.457776368]
rspec ./spec/array_spec.rb:240 # Array#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 909090909090909.4]
rspec ./spec/array_spec.rb[1:2:7:2] # Array#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to be within 1.0e-07 of 909090909090909.4
rspec ./spec/array_spec.rb:335 # Array#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 30151134.457776368]
@terceiro Thank you for reporting this issue. It is not a bug but these equality comparisons are intentional. The test currently assumes that floating-point arithmetic follows IEEE754.
Could you please check whether enumerable-statistics you built uses i387's extended precision arithmetic?
Well, just running rake from the enumerable-statistics sources on an i386 Debian system reproduces this. The build uses whatever are the default options:
$ git remote -v
origin https://github.com/mrkn/enumerable-statistics.git (fetch)
origin https://github.com/mrkn/enumerable-statistics.git (push)
$ git clean -dxf
$ rake
mkdir -p lib/enumerable/statistics
mkdir -p tmp/i386-linux-gnu/enumerable/statistics/extension/2.7.5/enumerable/statistics
cd tmp/i386-linux-gnu/enumerable/statistics/extension/2.7.5
/usr/bin/ruby2.7 -I. ../../../../../../ext/enumerable/statistics/extension/extconf.rb
checking for struct RRational... no
checking for rb_rational_new()... yes
checking for rb_rational_num()... yes
checking for rb_rational_den()... yes
checking for rb_rational_plus()... no
checking for struct RComplex... no
checking for rb_complex_raw()... yes
checking for rb_complex_real()... yes
checking for rb_complex_imag()... yes
checking for rb_complex_plus()... yes
checking for rb_complex_div()... yes
checking for rb_dbl_complex_new()... yes
creating Makefile
cd -
cd tmp/i386-linux-gnu/enumerable/statistics/extension/2.7.5
/usr/bin/gmake
compiling ../../../../../../ext/enumerable/statistics/extension/array_ext.c
compiling ../../../../../../ext/enumerable/statistics/extension/statistics.c
linking shared-object enumerable/statistics/extension.so
cp extension.so enumerable/statistics/extension.so
cd -
mkdir -p tmp/i386-linux-gnu/stage/lib/enumerable/statistics
install -c tmp/i386-linux-gnu/enumerable/statistics/extension/2.7.5/enumerable/statistics/extension.so lib/enumerable/statistics/extension.so
cp tmp/i386-linux-gnu/enumerable/statistics/extension/2.7.5/enumerable/statistics/extension.so tmp/i386-linux-gnu/stage/lib/enumerable/statistics/extension.so
/usr/bin/ruby2.7 -I/usr/share/rubygems-integration/all/gems/rspec-support-3.10.3/lib:/usr/share/rubygems-integration/all/gems/rspec-core-3.10.1/lib /usr/share/rubygems-integration/all/gems/rspec-core-3.10.1/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
/root/enumerable-statistics/lib/enumerable/statistics/extension.so: warning: method redefined; discarding old sum
/root/enumerable-statistics/lib/enumerable/statistics/extension.so: warning: method redefined; discarding old sum
Run options: include {:focus=>true}
All examples were filtered out; ignoring {:focus=>true}
Randomized with seed 54641
1) Array#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 909090909090909.4]
Failure/Error: it { is_expected.to eq([m, var]) }
expected: [9090909.090909092, 909090909090909.4]
got: [9090909.090909092, 909090909090909.0]
(compared using ==)
# ./spec/array_spec.rb:240:in `block (4 levels) in <top (required)>'
2) Array#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 30151134.457776368
Failure/Error: it { is_expected.to eq(x) }
expected: 30151134.457776368
got: 30151134.45777636
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
3) Array#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 30151134.457776368]
Failure/Error: it { is_expected.to eq([m, sd]) }
expected: [9090909.090909092, 30151134.457776368]
got: [9090909.090909092, 30151134.45777636]
(compared using ==)
# ./spec/array_spec.rb:335:in `block (4 levels) in <top (required)>'
4) Array#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 909090909090909.4
Failure/Error: it { is_expected.to eq(x) }
expected: 909090909090909.4
got: 909090909090909.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
5) Array#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 8333333.333333335
Failure/Error: it { is_expected.to eq(x) }
expected: 8333333.333333335
got: 8333333.333333333
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
6) Enumerable#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 30151134.457776368]
Failure/Error: it { is_expected.to eq([m, sd]) }
expected: [9090909.090909092, 30151134.457776368]
got: [9090909.090909092, 30151134.45777636]
(compared using ==)
# ./spec/enum_spec.rb:422:in `block (4 levels) in <top (required)>'
7) Enumerable#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 909090909090909.4
Failure/Error: it { is_expected.to eq(x) }
expected: 909090909090909.4
got: 909090909090909.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
8) Enumerable#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 909090909090909.4]
Failure/Error: it { is_expected.to eq([m, var]) }
expected: [9090909.090909092, 909090909090909.4]
got: [9090909.090909092, 909090909090909.0]
(compared using ==)
# ./spec/enum_spec.rb:237:in `block (4 levels) in <top (required)>'
9) Enumerable#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 30151134.457776368
Failure/Error: it { is_expected.to eq(x) }
expected: 30151134.457776368
got: 30151134.45777636
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
10) Enumerable#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 8333333.333333335
Failure/Error: it { is_expected.to eq(x) }
expected: 8333333.333333335
got: 8333333.333333333
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
11) Hash#sum for {:a=>(100000000/1), :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
12) Hash#sum for {:a=>1.0e-09, :b=>(100000000/1), :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09, :l=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
13) Hash#sum for {:a=>100000000, :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
390/390 |========================================================================================== 100 ==========================================================================================>| Time: 00:00:00
Top 10 slowest examples (0.05823 seconds, 16.2% of total time):
Array#histogram with 10,000 normal random values closed: :right is expected to eq false
0.01379 seconds ./spec/histogram/array_spec.rb:179
Array#histogram with 10,000 normal random values default is expected to eq false
0.01376 seconds ./spec/histogram/array_spec.rb:164
Array#histogram with 10,000 normal random values nbins: 5 is expected to eq false
0.01348 seconds ./spec/histogram/array_spec.rb:194
Array#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 909090909090909.4]
0.01055 seconds ./spec/array_spec.rb:240
Enumerable#sum for 1..0 with a conversion block does not call the conversion block
0.00194 seconds ./spec/range_spec.rb:19
Array#percentile for [1, nil, 3] is expected to match [(be nan), (be nan)]
0.00183 seconds ./spec/percentile/array_spec.rb:57
Array#percentile for [] is expected to raise ArgumentError
0.00108 seconds ./spec/percentile/array_spec.rb:10
Array#percentile for [1, NaN, 3] is expected to match [(be nan), (be nan)]
0.00101 seconds ./spec/percentile/array_spec.rb:50
Enumerable#sum for 3..5 is expected to be a kind of Integer
0.00041 seconds ./spec/support/macros.rb:47
Array#percentile for [1, 2, 3] is expected to eq [1.0, 1.5, 2.0, 2.5, 3.0]
0.00038 seconds ./spec/percentile/array_spec.rb:22
Top 10 slowest example groups:
Array#histogram
0.003 seconds average (0.04799 seconds / 16 examples) ./spec/histogram/array_spec.rb:4
Array
0.00139 seconds average (0.12517 seconds / 90 examples) ./spec/array_spec.rb:5
Array#percentile
0.00113 seconds average (0.00903 seconds / 8 examples) ./spec/percentile/array_spec.rb:3
Enumerable
0.00108 seconds average (0.09756 seconds / 90 examples) ./spec/enum_spec.rb:5
Array
0.00049 seconds average (0.01556 seconds / 32 examples) ./spec/value_counts_spec.rb:69
Hash
0.00047 seconds average (0.02012 seconds / 43 examples) ./spec/hash_spec.rb:5
Hash
0.00041 seconds average (0.01325 seconds / 32 examples) ./spec/value_counts_spec.rb:83
Enumerable
0.0004 seconds average (0.01254 seconds / 31 examples) ./spec/range_spec.rb:5
Enumerable
0.00035 seconds average (0.0113 seconds / 32 examples) ./spec/value_counts_spec.rb:101
Array#median
0.00031 seconds average (0.0049 seconds / 16 examples) ./spec/median/array_spec.rb:3
Finished in 0.36049 seconds (files took 0.83487 seconds to load)
390 examples, 13 failures
Failed examples:
rspec ./spec/array_spec.rb:240 # Array#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 909090909090909.4]
rspec ./spec/array_spec.rb[1:5:7:2] # Array#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 30151134.457776368
rspec ./spec/array_spec.rb:335 # Array#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq [9090909.090909092, 30151134.457776368]
rspec ./spec/array_spec.rb[1:2:7:2] # Array#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 909090909090909.4
rspec ./spec/array_spec.rb[1:1:8:2] # Array#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09] is expected to eq 8333333.333333335
rspec ./spec/enum_spec.rb:422 # Enumerable#mean_stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 30151134.457776368]
rspec ./spec/enum_spec.rb[1:2:7:2] # Enumerable#variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 909090909090909.4
rspec ./spec/enum_spec.rb:237 # Enumerable#mean_variance for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq [9090909.090909092, 909090909090909.4]
rspec ./spec/enum_spec.rb[1:4:7:2] # Enumerable#stdev for [100000000, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 30151134.457776368
rspec ./spec/enum_spec.rb[1:1:8:2] # Enumerable#mean for [1.0e-09, (100000000/1), 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09, 1.0e-09].each is expected to eq 8333333.333333335
rspec ./spec/hash_spec.rb[1:1:17:1:2] # Hash#sum for {:a=>(100000000/1), :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
rspec ./spec/hash_spec.rb[1:1:18:1:2] # Hash#sum for {:a=>1.0e-09, :b=>(100000000/1), :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09, :l=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
rspec ./spec/hash_spec.rb[1:1:16:1:2] # Hash#sum for {:a=>100000000, :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Randomized with seed 54641
/usr/bin/ruby2.7 -I/usr/share/rubygems-integration/all/gems/rspec-support-3.10.3/lib:/usr/share/rubygems-integration/all/gems/rspec-core-3.10.1/lib /usr/share/rubygems-integration/all/gems/rspec-core-3.10.1/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb failed
FWIW, the above was ran on a i386 lxc container under a amd64 system.
Could you please tell me the full compiler option? I guess it can be seen by the following command:
ruby -rrbconfig -e "puts RbConfig::CONFIG['CFLAGS']"
$ ruby -rrbconfig -e "puts RbConfig::CONFIG['CFLAGS']"
-g -O2 -ffile-prefix-map=/build/ruby2.7-I3v9IH/ruby2.7-2.7.5=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC
@terceiro Could you please check the result of rake test with Ruby that is built with -mfpmath=sse -msse2 options?
You can build Ruby with -mfpmath=sse -msse2 options by specifying optflags="-mfpmath=sse -msse2" to configure like below:
./configure optflags="-mfpmath=sse -msse2"
@mrkn in Debian i386 binaries cannot be built unconditionally with SSE because hardware without it is still supported, so there is no point in me doing this test because the i386 ruby binary will not change. I understand you might not care about this use case, in that case the Debian package can just keep carrying the patch it's currently carrying, which is this:
From: Antonio Terceiro <[email protected]>
Date: Wed, 3 Nov 2021 08:42:28 -0300
Subject: spec: avoid testing floats for equality
Forwarded: https://github.com/mrkn/enumerable-statistics/issues/31
---
spec/support/macros.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spec/support/macros.rb b/spec/support/macros.rb
index 6d3dd6e..3ae99dd 100644
--- a/spec/support/macros.rb
+++ b/spec/support/macros.rb
@@ -45,7 +45,7 @@ module Enumerable
def it_equals_with_type(x, type)
it { is_expected.to be_an(type) }
- it { is_expected.to eq(x) }
+ it { is_expected.to be_within(0.0000001).of(x) }
end
def it_is_int_equal(n)
@terceiro This patch is not appropriate for the tests you mentioned in this issue's description, especially for sum methods.
The reason why is that the tests examine whether the precision compensation calculation is performed.
1) Hash#sum for {:a=>(100000000/1), :b=>1.0e-09, :c=>1.0e-09, :d=>1.0e-09, :e=>1.0e-09, :f=>1.0e-09, :g=>1.0e-09, :h=>1.0e-09, :i=>1.0e-09, :j=>1.0e-09, :k=>1.0e-09} with conversion `(k, v) -> v` is expected to eq 100000000.00000001
Failure/Error: it { is_expected.to eq(x) }
expected: 100000000.00000001
got: 100000000.0
(compared using ==)
# ./spec/support/macros.rb:48:in `block in it_equals_with_type'
For example in the above case, the purpose of this test examines the sum method keeps the small number that is vanished by the round-off error. The test checks whether the effect of ten 1.0e-9 remains in the result of sum method. The number 1.0e-9 is automatically selected by the following code:
large_number = 100_000_000
small_number = 1e-9
until (large_number + small_number) == large_number
small_number /= 10
end
This code finds the number that the addition with large_number causes the round-off error. So the simple sum of large_number and ten small_numbers by inject(:+) equals to large_number.
The test must check sum method should produce the result that is different from the result by inject(:+).
what do you suggest to do in this case? skip the failing tests on i386 without SSE?
@terceiro In this case, skipping the failing tests is better than rewriting them with approximate comparing.
ok, thanks for the feedback. For now I'm changing the Debian package to skip the entire test suite on i386, as it's a bit difficult to filter out only the ones that would fail.