[前][次][番号順一覧][スレッド一覧]

ruby-changes:62004

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Mon, 29 Jun 2020 11:07:10 +0900 (JST)
Subject: [ruby-changes:62004] d060ebf83c (master): sum_iter: do not goto into a branch

https://git.ruby-lang.org/ruby.git/commit/?id=d060ebf83c

From d060ebf83c74b79fd8315e6428bad53a0b0d3fce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Mon, 15 Jun 2020 10:13:10 +0900
Subject: 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.

diff --git a/enum.c b/enum.c
index 8c8adcf..f72a64f 100644
--- a/enum.c
+++ b/enum.c
@@ -3848,122 +3848,130 @@ struct enum_sum_memo { https://github.com/ruby/ruby/blob/trunk/enum.c#L3848
 };
 
 static void
-sum_iter(VALUE i, struct enum_sum_memo *memo)
+sum_iter_normalize_memo(struct enum_sum_memo *memo)
 {
-    const int unused = (assert(memo != NULL), 0);
-
-    long n = memo->n;
-    VALUE v = memo->v;
-    VALUE r = memo->r;
+    assert(FIXABLE(memo->n));
+    memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v);
+    memo->n = 0;
+    /* r can be an Integer when mathn is loaded */
+    switch (TYPE(memo->r)) {
+      case T_FIXNUM:   memo->v = rb_fix_plus(memo->r, memo->v);      break;
+      case T_BIGNUM:   memo->v = rb_big_plus(memo->r, memo->v);      break;
+      case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v); break;
+      case T_UNDEF:    break;
+      default:         UNREACHABLE; /* or ...? */
+    }
+    memo->r = Qundef;
+}
+static void
+sum_iter_fixnum(VALUE i, struct enum_sum_memo *memo)
+{
+    memo->n += FIX2LONG(i); /* should not overflow long type */
+    if (! FIXABLE(memo->n)) {
+        memo->v = rb_big_plus(LONG2NUM(memo->n), memo->v);
+        memo->n = 0;
+    }
+}
+static void
+sum_iter_bignum(VALUE i, struct enum_sum_memo *memo)
+{
+    memo->v = rb_big_plus(i, memo->v);
+}
+static void
+sum_iter_rational(VALUE i, struct enum_sum_memo *memo)
+{
+    if (memo->r == Qundef) {
+        memo->r = i;
+    }
+    else {
+        memo->r = rb_rational_plus(memo->r, i);
+    }
+}
+static void
+sum_iter_some_value(VALUE i, struct enum_sum_memo *memo)
+{
+    memo->v = rb_funcallv(memo->v, idPLUS, 1, &i);
+}
+static void
+sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo)
+{
+    /*
+     * Kahan-Babuska balancing compensated summation algorithm
+     * See http://link.springer.com/article/10.1007/s0????-???-????-x
+     */
+    double x;
+    switch (TYPE(i)) {
+      case T_FLOAT:    x = RFLOAT_VALUE(i); break;
+      case T_FIXNUM:   x = FIX2LONG(i);     break;
+      case T_BIGNUM:   x = rb_big2dbl(i);   break;
+      case T_RATIONAL: x = rb_num2dbl(i);   break;
+      default:
+        memo->v = DBL2NUM(memo->f);
+        memo->float_value = 0;
+        sum_iter_some_value(i, memo);
+        return;
+    }
     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;
-        }
+    if (isnan(f)) {
+        return;
     }
-    else if (RB_FLOAT_TYPE_P(v)) {
-        /*
-         * Kahan-Babuska balancing compensated summation algorithm
-         * See http://link.springer.com/article/10.1007/s0????-???-????-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;
+    else if (! isfinite(x)) {
+        if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
+            i = DBL2NUM(f);
+            x = nan("");
         }
-        if (isinf(f)) return;
-
-        t = f + x;
-        if (fabs(f) >= fabs(x))
-            c += ((f - t) + x);
-        else
-            c += ((x - t) + f);
-        f = t;
+        memo->v = i;
+        memo->f = x;
+        return;
+    }
+    else if (isinf(f)) {
+        return;
+    }
+    double c = memo->c;
+    double t = f + x;
+    if (fabs(f) >= fabs(x)) {
+        c += ((f - t) + x);
     }
     else {
-      some_value:
-        v = rb_funcallv(v, idPLUS, 1, &i);
+        c += ((x - t) + f);
     }
-
-    memo->v = v;
-    memo->n = n;
-    memo->r = r;
+    f = t;
     memo->f = f;
     memo->c = c;
-    (void)unused;
+}
+static void
+sum_iter(VALUE i, struct enum_sum_memo *memo)
+{
+    assert(memo != NULL);
+    if (memo->block_given) {
+        i = rb_yield(i);
+    }
+    if (memo->float_value) {
+        sum_iter_Kahan_Babuska(i, memo);
+    }
+    else switch (TYPE(memo->v)) {
+      default:      sum_iter_some_value(i, memo);    return;
+      case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
+      case T_FIXNUM:
+      case T_BIGNUM:
+      case T_RATIONAL:
+        switch (TYPE(i)) {
+          case T_FIXNUM:   sum_iter_fixnum(i, memo);   return;
+          case T_BIGNUM:   sum_iter_bignum(i, memo);   return;
+          case T_RATIONAL: sum_iter_rational(i, memo); return;
+          case T_FLOAT:
+            sum_iter_normalize_memo(memo);
+            memo->f = NUM2DBL(memo->v);
+            memo->c = 0.0;
+            memo->float_value = 1;
+            sum_iter_Kahan_Babuska(i, memo);
+            return;
+          default:
+            sum_iter_normalize_memo(memo);
+            sum_iter_some_value(i, memo);
+            return;
+        }
+    }
 }
 
 static VALUE
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]