From: "phasis68 (Heesob Park)" Date: 2012-11-15T16:40:25+09:00 Subject: [ruby-core:49364] [ruby-trunk - Bug #7352] Array#bsearch test failure on Range (32bits MinGW) Issue #7352 has been updated by phasis68 (Heesob Park). I guess this bug is related with the optimization of GCC 4.7.2. The version built with VC 2010 or GCC 4.5.2 works fine. The workaround is adding a volatile qualifier. Additionally, I found some problems in Range#bsearch method. 1. The following example in documentation is wrong. (0..4).bsearch {|i| 100 - i } #=> 1, 2 or 3 (0..4).bsearch {|i| 300 - i } #=> nil (0..4).bsearch {|i| 50 - i } #=> nil 2. (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } returns nil instead of 1.0 on Windows. 3. (0.0..10).bsearch {|x| 7.0-x} returns nil instead of 7.0 Here is a patch for all above problems: diff --git a/range.c b/range.c.new index 7d30383..0e0fd14 100644 --- a/range.c +++ b/range.c.new @@ -513,9 +513,9 @@ range_step(int argc, VALUE *argv, VALUE range) * satisfies the condition, it returns nil. * * ary = [0, 100, 100, 100, 200] - * (0..4).bsearch {|i| 100 - i } #=> 1, 2 or 3 - * (0..4).bsearch {|i| 300 - i } #=> nil - * (0..4).bsearch {|i| 50 - i } #=> nil + * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3 + * (0..4).bsearch {|i| 300 - ary[i] } #=> nil + * (0..4).bsearch {|i| 50 - ary[i] } #=> nil * * You must not mix the two modes at a time; the block must always * return either true/false, or always return a number. It is @@ -543,10 +543,10 @@ range_bsearch(VALUE range) smaller = 0; \ } \ else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \ - switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)) < 0) { \ + switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) { \ case 0: return val; \ - case 1: smaller = 1; \ - case -1: smaller = 0; \ + case -1: smaller = 1; break; \ + case 1: smaller = 0; \ } \ } \ else { \ @@ -586,6 +586,7 @@ range_bsearch(VALUE range) double high = RFLOAT_VALUE(rb_Float(end)); double mid, org_high; int count; + org_high = high; #ifdef FLT_RADIX #ifdef DBL_MANT_DIG #define BSEARCH_MAXCOUNT (((FLT_RADIX) - 1) * (DBL_MANT_DIG + DBL_MAX_EXP) + 100) @@ -646,7 +647,7 @@ range_bsearch(VALUE range) } if (isinf(low) && low < 0) { /* the range is (-INFINITY..high) */ - double nlow = -1.0, dec; + volatile double nlow = -1.0, dec; if (nlow > high) nlow = high; count = BSEARCH_MAXCOUNT; /* find lower bound by checking low, low*2, low*4, ... */ @@ -697,7 +698,6 @@ range_bsearch(VALUE range) binsearch: /* find the desired value within low..high */ /* where low is not -INFINITY and high is not INFINITY */ - org_high = high; count = BSEARCH_MAXCOUNT; while (low < high && count >= 0) { mid = low + ((high - low) / 2); ---------------------------------------- Bug #7352: Array#bsearch test failure on Range (32bits MinGW) https://bugs.ruby-lang.org/issues/7352#change-32921 Author: luislavena (Luis Lavena) Status: Assigned Priority: Normal Assignee: mame (Yusuke Endoh) Category: test Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-11-15 trunk 37656) [i386-mingw32] =begin Hello, After r37655, I noticed a failing test on RubyInstaller CI for x86: test_bsearch_for_float(TestRange) [C:/Users/Luis/Code/ruby/ruby/test/ruby/test_range.rb:392]: Expected -1.7976931348623157e+308 to be >= NaN. This do not fail on x64, both running with GCC 4.7.2 I don't have Linux test results to compare at this time, but wanted to raise awareness of this issue. Thank you =end -- http://bugs.ruby-lang.org/