* range.c (range_bsearch): fix some bugs: a documentation bug, a wrong
condition, missed break in switch/case, and workaround for GCC optimization. See [ruby-core:49364] in detail. A great patch from Heesob Park. [Bug #7352] [Feature #4766] * array.c (rb_ary_bsearch): fix similar bug (missed break). * test/ruby/test_range.rb: add two test cases for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
768801b020
commit
412b023742
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
Thu Nov 15 22:39:32 2012 Yusuke Endoh <mame@tsg.ne.jp>
|
||||||
|
|
||||||
|
* range.c (range_bsearch): fix some bugs: a documentation bug, a wrong
|
||||||
|
condition, missed break in switch/case, and workaround for GCC
|
||||||
|
optimization. See [ruby-core:49364] in detail. A great patch from
|
||||||
|
Heesob Park. [Bug #7352] [Feature #4766]
|
||||||
|
|
||||||
|
* array.c (rb_ary_bsearch): fix similar bug (missed break).
|
||||||
|
|
||||||
|
* test/ruby/test_range.rb: add two test cases for above.
|
||||||
|
|
||||||
Thu Nov 15 22:41:57 2012 Koichi Sasada <ko1@atdot.net>
|
Thu Nov 15 22:41:57 2012 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* vm_exec.h (GENTRY): GENTRY should be pointer size.
|
* vm_exec.h (GENTRY): GENTRY should be pointer size.
|
||||||
|
2
array.c
2
array.c
@ -2451,7 +2451,7 @@ rb_ary_bsearch(VALUE ary)
|
|||||||
else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
|
else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
|
||||||
switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
|
switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
|
||||||
case 0: return val;
|
case 0: return val;
|
||||||
case 1: smaller = 1;
|
case 1: smaller = 1; break;
|
||||||
case -1: smaller = 0;
|
case -1: smaller = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
range.c
16
range.c
@ -513,9 +513,9 @@ range_step(int argc, VALUE *argv, VALUE range)
|
|||||||
* satisfies the condition, it returns nil.
|
* satisfies the condition, it returns nil.
|
||||||
*
|
*
|
||||||
* ary = [0, 100, 100, 100, 200]
|
* ary = [0, 100, 100, 100, 200]
|
||||||
* (0..4).bsearch {|i| 100 - i } #=> 1, 2 or 3
|
* (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
|
||||||
* (0..4).bsearch {|i| 300 - i } #=> nil
|
* (0..4).bsearch {|i| 300 - ary[i] } #=> nil
|
||||||
* (0..4).bsearch {|i| 50 - i } #=> nil
|
* (0..4).bsearch {|i| 50 - ary[i] } #=> nil
|
||||||
*
|
*
|
||||||
* You must not mix the two modes at a time; the block must always
|
* 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
|
* return either true/false, or always return a number. It is
|
||||||
@ -543,10 +543,10 @@ range_bsearch(VALUE range)
|
|||||||
smaller = 0; \
|
smaller = 0; \
|
||||||
} \
|
} \
|
||||||
else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
|
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 0: return val; \
|
||||||
case 1: smaller = 1; \
|
case -1: smaller = 1; break; \
|
||||||
case -1: smaller = 0; \
|
case 1: smaller = 0; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
@ -586,6 +586,7 @@ range_bsearch(VALUE range)
|
|||||||
double high = RFLOAT_VALUE(rb_Float(end));
|
double high = RFLOAT_VALUE(rb_Float(end));
|
||||||
double mid, org_high;
|
double mid, org_high;
|
||||||
int count;
|
int count;
|
||||||
|
org_high = high;
|
||||||
#ifdef FLT_RADIX
|
#ifdef FLT_RADIX
|
||||||
#ifdef DBL_MANT_DIG
|
#ifdef DBL_MANT_DIG
|
||||||
#define BSEARCH_MAXCOUNT (((FLT_RADIX) - 1) * (DBL_MANT_DIG + DBL_MAX_EXP) + 100)
|
#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) {
|
if (isinf(low) && low < 0) {
|
||||||
/* the range is (-INFINITY..high) */
|
/* the range is (-INFINITY..high) */
|
||||||
double nlow = -1.0, dec;
|
volatile double nlow = -1.0, dec;
|
||||||
if (nlow > high) nlow = high;
|
if (nlow > high) nlow = high;
|
||||||
count = BSEARCH_MAXCOUNT;
|
count = BSEARCH_MAXCOUNT;
|
||||||
/* find lower bound by checking low, low*2, low*4, ... */
|
/* find lower bound by checking low, low*2, low*4, ... */
|
||||||
@ -697,7 +698,6 @@ range_bsearch(VALUE range)
|
|||||||
binsearch:
|
binsearch:
|
||||||
/* find the desired value within low..high */
|
/* find the desired value within low..high */
|
||||||
/* where low is not -INFINITY and high is not INFINITY */
|
/* where low is not -INFINITY and high is not INFINITY */
|
||||||
org_high = high;
|
|
||||||
count = BSEARCH_MAXCOUNT;
|
count = BSEARCH_MAXCOUNT;
|
||||||
while (low < high && count >= 0) {
|
while (low < high && count >= 0) {
|
||||||
mid = low + ((high - low) / 2);
|
mid = low + ((high - low) / 2);
|
||||||
|
@ -417,6 +417,9 @@ class TestRange < Test::Unit::TestCase
|
|||||||
v = (-inf..0).bsearch {|x| x > -Float::MAX }
|
v = (-inf..0).bsearch {|x| x > -Float::MAX }
|
||||||
assert_operator(-Float::MAX, :<, v)
|
assert_operator(-Float::MAX, :<, v)
|
||||||
assert_equal(nil, v.infinite?)
|
assert_equal(nil, v.infinite?)
|
||||||
|
|
||||||
|
assert_in_delta(1.0, (0.0..inf).bsearch {|x| Math.log(x) >= 0 })
|
||||||
|
assert_in_delta(7.0, (0.0..10).bsearch {|x| 7.0 - x })
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_bsearch_for_bignum
|
def test_bsearch_for_bignum
|
||||||
|
Loading…
x
Reference in New Issue
Block a user