aboutsummaryrefslogtreecommitdiffstats
path: root/range.c
diff options
context:
space:
mode:
authorKouhei Yanagita <yanagi@shakenbu.org>2023-09-19 15:29:35 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-09-21 10:30:58 +0900
commit7e350f53107533856b0a87c26e5a1e5505ea5d59 (patch)
treee524ab366c7203fd90474123a8c385b826eb6a7b /range.c
parentab637cad2b582e8247bafd87a3b0f6323d564f64 (diff)
downloadruby-7e350f53107533856b0a87c26e5a1e5505ea5d59.tar.gz
Optimize Range#bsearch for beginless/endless ranges within Fixnum
Diffstat (limited to 'range.c')
-rw-r--r--range.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/range.c b/range.c
index 7c116d78c7..a8bdb98b53 100644
--- a/range.c
+++ b/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;