Optimize Range#bsearch for beginless/endless ranges within Fixnum
This commit is contained in:
parent
ab637cad2b
commit
7e350f5310
@ -1,9 +1,21 @@
|
||||
prelude: |
|
||||
r = (1..)
|
||||
re = (1..)
|
||||
rb = (..0)
|
||||
|
||||
benchmark:
|
||||
'10**1': r.bsearch { |x| x >= 10 }
|
||||
'10**2': r.bsearch { |x| x >= 100 }
|
||||
'10**3': r.bsearch { |x| x >= 1000 }
|
||||
'10**4': r.bsearch { |x| x >= 10000 }
|
||||
'10**5': r.bsearch { |x| x >= 100000 }
|
||||
'endless 10**0': re.bsearch { |x| x >= 1 }
|
||||
'endless 10**1': re.bsearch { |x| x >= 10 }
|
||||
'endless 10**2': re.bsearch { |x| x >= 100 }
|
||||
'endless 10**3': re.bsearch { |x| x >= 1000 }
|
||||
'endless 10**4': re.bsearch { |x| x >= 10000 }
|
||||
'endless 10**5': re.bsearch { |x| x >= 100000 }
|
||||
'endless 10**10': re.bsearch { |x| x >= 10000000000 }
|
||||
'endless 10**100': re.bsearch { |x| x >= 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }
|
||||
'beginless -10**0': rb.bsearch { |x| x >= -1 }
|
||||
'beginless -10**1': rb.bsearch { |x| x >= -10 }
|
||||
'beginless -10**2': rb.bsearch { |x| x >= -100 }
|
||||
'beginless -10**3': rb.bsearch { |x| x >= -1000 }
|
||||
'beginless -10**4': rb.bsearch { |x| x >= -10000 }
|
||||
'beginless -10**5': rb.bsearch { |x| x >= -100000 }
|
||||
'beginless -10**10': rb.bsearch { |x| x >= -10000000000 }
|
||||
'beginless -10**100': rb.bsearch { |x| x >= -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 }
|
||||
|
32
range.c
32
range.c
@ -703,10 +703,10 @@ range_bsearch(VALUE range)
|
||||
* (-1...0.0).bsearch to yield -0.0.
|
||||
*/
|
||||
|
||||
#define BSEARCH(conv) \
|
||||
#define BSEARCH(conv, excl) \
|
||||
do { \
|
||||
RETURN_ENUMERATOR(range, 0, 0); \
|
||||
if (EXCL(range)) high--; \
|
||||
if (excl) high--; \
|
||||
org_high = high; \
|
||||
while (low < high) { \
|
||||
mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
|
||||
@ -726,22 +726,26 @@ range_bsearch(VALUE range)
|
||||
return satisfied; \
|
||||
} while (0)
|
||||
|
||||
#define BSEARCH_FIXNUM(beg, end, excl) \
|
||||
do { \
|
||||
long low = FIX2LONG(beg); \
|
||||
long high = FIX2LONG(end); \
|
||||
long mid, org_high; \
|
||||
BSEARCH(INT2FIX, (excl)); \
|
||||
} while (0)
|
||||
|
||||
beg = RANGE_BEG(range);
|
||||
end = RANGE_END(range);
|
||||
|
||||
if (FIXNUM_P(beg) && FIXNUM_P(end)) {
|
||||
long low = FIX2LONG(beg);
|
||||
long high = FIX2LONG(end);
|
||||
long mid, org_high;
|
||||
BSEARCH(INT2FIX);
|
||||
BSEARCH_FIXNUM(beg, end, EXCL(range));
|
||||
}
|
||||
#if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
|
||||
else if (RB_FLOAT_TYPE_P(beg) || RB_FLOAT_TYPE_P(end)) {
|
||||
int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg)));
|
||||
int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end)));
|
||||
int64_t mid, org_high;
|
||||
BSEARCH(int64_as_double_to_num);
|
||||
BSEARCH(int64_as_double_to_num, EXCL(range));
|
||||
}
|
||||
#endif
|
||||
else if (is_integer_p(beg) && is_integer_p(end)) {
|
||||
@ -755,7 +759,12 @@ range_bsearch(VALUE range)
|
||||
VALUE mid = rb_funcall(beg, '+', 1, diff);
|
||||
BSEARCH_CHECK(mid);
|
||||
if (smaller) {
|
||||
return bsearch_integer_range(beg, mid, 0);
|
||||
if (FIXNUM_P(beg) && FIXNUM_P(mid)) {
|
||||
BSEARCH_FIXNUM(beg, mid, false);
|
||||
}
|
||||
else {
|
||||
return bsearch_integer_range(beg, mid, false);
|
||||
}
|
||||
}
|
||||
diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
|
||||
beg = mid;
|
||||
@ -768,7 +777,12 @@ range_bsearch(VALUE range)
|
||||
VALUE mid = rb_funcall(end, '+', 1, diff);
|
||||
BSEARCH_CHECK(mid);
|
||||
if (!smaller) {
|
||||
return bsearch_integer_range(mid, end, 0);
|
||||
if (FIXNUM_P(mid) && FIXNUM_P(end)) {
|
||||
BSEARCH_FIXNUM(mid, end, false);
|
||||
}
|
||||
else {
|
||||
return bsearch_integer_range(mid, end, false);
|
||||
}
|
||||
}
|
||||
diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
|
||||
end = mid;
|
||||
|
@ -1047,7 +1047,10 @@ class TestRange < Test::Unit::TestCase
|
||||
assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 100 })
|
||||
assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| true })
|
||||
assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| false })
|
||||
|
||||
assert_equal(bignum * 2 + 1, (0...).bsearch {|i| i > bignum * 2 })
|
||||
assert_equal(bignum * 2 + 1, (bignum...).bsearch {|i| i > bignum * 2 })
|
||||
assert_equal(-bignum * 2 + 1, (...0).bsearch {|i| i > -bignum * 2 })
|
||||
assert_equal(-bignum * 2 + 1, (...-bignum).bsearch {|i| i > -bignum * 2 })
|
||||
|
||||
assert_raise(TypeError) { ("a".."z").bsearch {} }
|
||||
|
Loading…
x
Reference in New Issue
Block a user