summaryrefslogtreecommitdiff
path: root/enum.c
diff options
context:
space:
mode:
author卜部昌平 <[email protected]>2020-06-15 10:13:10 +0900
committer卜部昌平 <[email protected]>2020-06-29 11:05:41 +0900
commitd060ebf83c74b79fd8315e6428bad53a0b0d3fce ()
tree6a10a0ce2ded8c5f852506f9095ed5403d06933c /enum.c
parent5e960545193eeb7f52acc7ec505d908db3785e30 (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.c222
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