diff options
author | 卜部昌平 <[email protected]> | 2020-06-15 10:13:10 +0900 |
---|---|---|
committer | 卜部昌平 <[email protected]> | 2020-06-29 11:05:41 +0900 |
commit | d060ebf83c74b79fd8315e6428bad53a0b0d3fce () | |
tree | 6a10a0ce2ded8c5f852506f9095ed5403d06933c /enum.c | |
parent | 5e960545193eeb7f52acc7ec505d908db3785e30 (diff) |
sum_iter: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a branch is definitely a bad idea. Better refactor.
Notes: Merged: https://.com/ruby/ruby/pull/3247
-rw-r--r-- | enum.c | 222 |
1 files changed, 115 insertions, 107 deletions
@@ -3848,122 +3848,130 @@ struct enum_sum_memo { }; static void -sum_iter(VALUE i, struct enum_sum_memo *memo) { - const int unused = (assert(memo != NULL), 0); - - long n = memo->n; - VALUE v = memo->v; - VALUE r = memo->r; double f = memo->f; - double c = memo->c; - - if (memo->block_given) - i = rb_yield(i); - - if (memo->float_value) - goto float_value; - - if (FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || RB_TYPE_P(v, T_RATIONAL)) { - if (FIXNUM_P(i)) { - n += FIX2LONG(i); /* should not overflow long type */ - if (!FIXABLE(n)) { - v = rb_big_plus(LONG2NUM(n), v); - n = 0; - } - } - else if (RB_TYPE_P(i, T_BIGNUM)) - v = rb_big_plus(i, v); - else if (RB_TYPE_P(i, T_RATIONAL)) { - if (r == Qundef) - r = i; - else - r = rb_rational_plus(r, i); - } - else { - if (n != 0) { - v = rb_fix_plus(LONG2FIX(n), v); - n = 0; - } - if (r != Qundef) { - /* r can be an Integer when mathn is loaded */ - if (FIXNUM_P(r)) - v = rb_fix_plus(r, v); - else if (RB_TYPE_P(r, T_BIGNUM)) - v = rb_big_plus(r, v); - else - v = rb_rational_plus(r, v); - r = Qundef; - } - if (RB_FLOAT_TYPE_P(i)) { - f = NUM2DBL(v); - c = 0.0; - memo->float_value = 1; - goto float_value; - } - else - goto some_value; - } } - else if (RB_FLOAT_TYPE_P(v)) { - /* - * Kahan-Babuska balancing compensated summation algorithm - * See http://link.springer.com/article/10.1007/s00607-005-0139-x - */ - double x, t; - - float_value: - if (RB_FLOAT_TYPE_P(i)) - x = RFLOAT_VALUE(i); - else if (FIXNUM_P(i)) - x = FIX2LONG(i); - else if (RB_TYPE_P(i, T_BIGNUM)) - x = rb_big2dbl(i); - else if (RB_TYPE_P(i, T_RATIONAL)) - x = rb_num2dbl(i); - else { - v = DBL2NUM(f); - memo->float_value = 0; - goto some_value; - } - - if (isnan(f)) return; - if (isnan(x)) { - memo->v = i; - memo->f = x; - return; - } - if (isinf(x)) { - if (isinf(f) && signbit(x) != signbit(f)) { - memo->f = NAN; - memo->v = DBL2NUM(f); - } - else { - memo->f = x; - memo->v = i; - } - return; } - if (isinf(f)) return; - - t = f + x; - if (fabs(f) >= fabs(x)) - c += ((f - t) + x); - else - c += ((x - t) + f); - f = t; } else { - some_value: - v = rb_funcallv(v, idPLUS, 1, &i); } - - memo->v = v; - memo->n = n; - memo->r = r; memo->f = f; memo->c = c; - (void)unused; } static VALUE |