GithubHelp home page GithubHelp logo

Comments (11)

mrkn avatar mrkn commented on August 10, 2024

@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?

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024

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

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024

FWIW, the above was ran on a i386 lxc container under a amd64 system.

from enumerable-statistics.

mrkn avatar mrkn commented on August 10, 2024

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']"

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024
$ 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

from enumerable-statistics.

mrkn avatar mrkn commented on August 10, 2024

@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"

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024

@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)

from enumerable-statistics.

mrkn avatar mrkn commented on August 10, 2024

@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(:+).

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024

what do you suggest to do in this case? skip the failing tests on i386 without SSE?

from enumerable-statistics.

mrkn avatar mrkn commented on August 10, 2024

@terceiro In this case, skipping the failing tests is better than rewriting them with approximate comparing.

from enumerable-statistics.

terceiro avatar terceiro commented on August 10, 2024

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.

from enumerable-statistics.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.