mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
range.c: optimize range_each for Bignum
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
394418c9d5
commit
058949ac13
1 changed files with 51 additions and 8 deletions
59
range.c
59
range.c
|
@ -786,6 +786,7 @@ static VALUE
|
||||||
range_each(VALUE range)
|
range_each(VALUE range)
|
||||||
{
|
{
|
||||||
VALUE beg, end;
|
VALUE beg, end;
|
||||||
|
long i, lim;
|
||||||
|
|
||||||
RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
|
RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
|
||||||
|
|
||||||
|
@ -793,26 +794,67 @@ range_each(VALUE range)
|
||||||
end = RANGE_END(range);
|
end = RANGE_END(range);
|
||||||
|
|
||||||
if (FIXNUM_P(beg) && NIL_P(end)) {
|
if (FIXNUM_P(beg) && NIL_P(end)) {
|
||||||
long i = FIX2LONG(beg);
|
fixnum_endless:
|
||||||
|
i = FIX2LONG(beg);
|
||||||
while (FIXABLE(i)) {
|
while (FIXABLE(i)) {
|
||||||
rb_yield(LONG2FIX(i++));
|
rb_yield(LONG2FIX(i++));
|
||||||
}
|
}
|
||||||
beg = LONG2NUM(i);
|
beg = LONG2NUM(i);
|
||||||
|
bignum_endless:
|
||||||
inf_loop:
|
for (;; beg = rb_big_plus(beg, INT2FIX(1)))
|
||||||
for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
|
|
||||||
rb_yield(beg);
|
rb_yield(beg);
|
||||||
}
|
}
|
||||||
else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
|
else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
|
||||||
long lim = FIX2LONG(end);
|
fixnum_loop:
|
||||||
long i;
|
lim = FIX2LONG(end);
|
||||||
|
|
||||||
if (!EXCL(range))
|
if (!EXCL(range))
|
||||||
lim += 1;
|
lim += 1;
|
||||||
for (i = FIX2LONG(beg); i < lim; i++) {
|
for (i = FIX2LONG(beg); i < lim; i++) {
|
||||||
rb_yield(LONG2FIX(i));
|
rb_yield(LONG2FIX(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
|
||||||
|
if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
|
||||||
|
if (!FIXNUM_P(beg)) {
|
||||||
|
if (RBIGNUM_NEGATIVE_P(beg)) {
|
||||||
|
do {
|
||||||
|
rb_yield(beg);
|
||||||
|
} while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
|
||||||
|
if (NIL_P(end)) goto fixnum_endless;
|
||||||
|
if (FIXNUM_P(end)) goto fixnum_loop;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (NIL_P(end)) goto bignum_endless;
|
||||||
|
if (FIXNUM_P(end)) return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FIXNUM_P(beg)) {
|
||||||
|
i = FIX2LONG(beg);
|
||||||
|
do {
|
||||||
|
rb_yield(LONG2FIX(i));
|
||||||
|
} while (POSFIXABLE(++i));
|
||||||
|
beg = LONG2NUM(i);
|
||||||
|
}
|
||||||
|
ASSUME(!FIXNUM_P(beg));
|
||||||
|
ASSUME(!SPECIAL_CONST_P(end));
|
||||||
|
}
|
||||||
|
if (!FIXNUM_P(beg) && RBIGNUM_SIGN(beg) == RBIGNUM_SIGN(end)) {
|
||||||
|
if (EXCL(range)) {
|
||||||
|
while (rb_big_cmp(beg, end) == INT2FIX(-1)) {
|
||||||
|
rb_yield(beg);
|
||||||
|
beg = rb_big_plus(beg, INT2FIX(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VALUE c;
|
||||||
|
while ((c = rb_big_cmp(beg, end)) != INT2FIX(1)) {
|
||||||
|
rb_yield(beg);
|
||||||
|
if (c == INT2FIX(0)) break;
|
||||||
|
beg = rb_big_plus(beg, INT2FIX(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (SYMBOL_P(beg) && (NIL_P(end) || SYMBOL_P(end))) { /* symbols are special */
|
else if (SYMBOL_P(beg) && (NIL_P(end) || SYMBOL_P(end))) { /* symbols are special */
|
||||||
beg = rb_sym2str(beg);
|
beg = rb_sym2str(beg);
|
||||||
if (NIL_P(end)) {
|
if (NIL_P(end)) {
|
||||||
|
@ -841,7 +883,8 @@ range_each(VALUE range)
|
||||||
if (!NIL_P(end))
|
if (!NIL_P(end))
|
||||||
range_each_func(range, each_i, 0);
|
range_each_func(range, each_i, 0);
|
||||||
else
|
else
|
||||||
goto inf_loop;
|
for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
|
||||||
|
rb_yield(beg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return range;
|
return range;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue