summaryrefslogtreecommitdiff
path: root/enum.c
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-17 15:08:33 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-17 15:08:33 +0000
commitd5595a96272419a495e3766dc9c96b5884c00efd (patch)
tree4d6b6911dd87338b8ec012e07ef56853fc9cf30c /enum.c
parent41d002bbad90e2c290d3854a9543c907e86ce210 (diff)
Optimize enum_sum for a range from int to int
* enum.c (enum_sum): Optimize for a range from int to int. * test/ruby/test_enum.rb (test_range_sum): Move from test_range.rb, and add assertions for some conditions. * test/ruby/test_enum.rb (test_hash_sum): Move from test_hash.rb. * test/ruby/test_hash.rb, test/ruby/test_range.rb: Remove test_sum. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55034 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r--enum.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/enum.c b/enum.c
index 56d304c7a9..54e1364de7 100644
--- a/enum.c
+++ b/enum.c
@@ -3699,6 +3699,8 @@ static VALUE
enum_sum(int argc, VALUE* argv, VALUE obj)
{
struct enum_sum_memo memo;
+ VALUE beg, end;
+ int excl;
if (rb_scan_args(argc, argv, "01", &memo.v) == 0)
memo.v = LONG2FIX(0);
@@ -3713,6 +3715,29 @@ enum_sum(int argc, VALUE* argv, VALUE obj)
memo.c = 0.0;
}
+ if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
+ if (!memo.block_given && !memo.float_value &&
+ (FIXNUM_P(beg) || RB_TYPE_P(beg, T_BIGNUM)) &&
+ (FIXNUM_P(end) || RB_TYPE_P(end, T_BIGNUM))) {
+ if (excl) {
+ if (FIXNUM_P(end))
+ end = LONG2FIX(FIX2LONG(end) - 1);
+ else
+ end = rb_big_minus(end, LONG2FIX(1));
+ }
+ if (rb_int_ge(end, beg)) {
+ VALUE a;
+ a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
+ a = rb_int_mul(a, rb_int_plus(end, beg));
+ a = rb_int_idiv(a, LONG2FIX(2));
+ return rb_int_plus(memo.v, a);
+ }
+ else {
+ return memo.v;
+ }
+ }
+ }
+
rb_block_call(obj, id_each, 0, 0, enum_sum_iter_i, (VALUE)&memo);
if (memo.float_value) {