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

ruby-changes:74459

From: Kenta <ko1@a...>
Date: Sun, 13 Nov 2022 11:02:19 +0900 (JST)
Subject: [ruby-changes:74459] 74c6e6e565 (master): [ruby/bigdecimal] Rewrite check_rounding_mode function

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

From 74c6e6e565aad4cbf2e5b7a13c21e78361808404 Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@m...>
Date: Sun, 13 Nov 2022 10:50:33 +0900
Subject: [ruby/bigdecimal] Rewrite check_rounding_mode function

Use table-lookup algorithm instead of consecutive if-statements.

https://github.com/ruby/bigdecimal/commit/23eaff3ae5
---
 ext/bigdecimal/bigdecimal.c | 79 ++++++++++++++++++++++++---------------------
 ext/bigdecimal/bigdecimal.h | 37 +++++++++++++++------
 2 files changed, 70 insertions(+), 46 deletions(-)

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 20158c27c5..40a825dfc7 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -61,6 +61,13 @@ static ID id_to_r; https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L61
 static ID id_eq;
 static ID id_half;
 
+#define RBD_NUM_ROUNDING_MODES 11
+
+static struct {
+    ID id;
+    uint8_t mode;
+} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
+
 /* MACRO's to guard objects from GC by keeping them in stack */
 #ifdef RBIMPL_ATTR_MAYBE_UNUSED
 #define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
@@ -667,34 +674,23 @@ check_rounding_mode(VALUE const v) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L674
 {
     unsigned short sw;
     ID id;
-    switch (TYPE(v)) {
-      case T_SYMBOL:
-	id = SYM2ID(v);
-	if (id == id_up)
-	    return VP_ROUND_UP;
-	if (id == id_down || id == id_truncate)
-	    return VP_ROUND_DOWN;
-	if (id == id_half_up || id == id_default)
-	    return VP_ROUND_HALF_UP;
-	if (id == id_half_down)
-	    return VP_ROUND_HALF_DOWN;
-	if (id == id_half_even || id == id_banker)
-	    return VP_ROUND_HALF_EVEN;
-	if (id == id_ceiling || id == id_ceil)
-	    return VP_ROUND_CEIL;
-	if (id == id_floor)
-	    return VP_ROUND_FLOOR;
-	rb_raise(rb_eArgError, "invalid rounding mode");
-
-      default:
-	break;
+    if (RB_TYPE_P(v, T_SYMBOL)) {
+        int i;
+        id = SYM2ID(v);
+        for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
+            if (rbd_rounding_modes[i].id == id) {
+                return rbd_rounding_modes[i].mode;
+            }
+        }
+        rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
     }
-
-    sw = NUM2USHORT(v);
-    if (!VpIsRoundMode(sw)) {
-	rb_raise(rb_eArgError, "invalid rounding mode");
+    else {
+        sw = NUM2USHORT(v);
+        if (!VpIsRoundMode(sw)) {
+            rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
+        }
+        return sw;
     }
-    return sw;
 }
 
 /*  call-seq:
@@ -4419,17 +4415,26 @@ Init_bigdecimal(void) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4415
     rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
     rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
 
-    id_up = rb_intern_const("up");
-    id_down = rb_intern_const("down");
-    id_truncate = rb_intern_const("truncate");
-    id_half_up = rb_intern_const("half_up");
-    id_default = rb_intern_const("default");
-    id_half_down = rb_intern_const("half_down");
-    id_half_even = rb_intern_const("half_even");
-    id_banker = rb_intern_const("banker");
-    id_ceiling = rb_intern_const("ceiling");
-    id_ceil = rb_intern_const("ceil");
-    id_floor = rb_intern_const("floor");
+#define ROUNDING_MODE(i, name, value) \
+    id_##name = rb_intern_const(#name); \
+    rbd_rounding_modes[i].id   = id_##name; \
+    rbd_rounding_modes[i].mode = value;
+
+    ROUNDING_MODE(0, up,        RBD_ROUND_UP);
+    ROUNDING_MODE(1, down,      RBD_ROUND_DOWN);
+    ROUNDING_MODE(2, half_up,   RBD_ROUND_HALF_UP);
+    ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
+    ROUNDING_MODE(4, ceil,      RBD_ROUND_CEIL);
+    ROUNDING_MODE(5, floor,     RBD_ROUND_FLOOR);
+    ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
+
+    ROUNDING_MODE(7,  default,   RBD_ROUND_DEFAULT);
+    ROUNDING_MODE(8,  truncate,  RBD_ROUND_TRUNCATE);
+    ROUNDING_MODE(9,  banker,    RBD_ROUND_BANKER);
+    ROUNDING_MODE(10, ceiling,   RBD_ROUND_CEILING);
+
+#undef ROUNDING_MODE
+
     id_to_r = rb_intern_const("to_r");
     id_eq = rb_intern_const("==");
     id_half = rb_intern_const("half");
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index bd1c46743e..38dee51e68 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -102,7 +102,7 @@ extern VALUE rb_cBigDecimal; https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.h#L102
  */
 #define VP_EXPORT static
 
-/* Exception codes */
+/* Exception mode */
 #define VP_EXCEPTION_ALL        ((unsigned short)0x00FF)
 #define VP_EXCEPTION_INFINITY   ((unsigned short)0x0001)
 #define VP_EXCEPTION_NaN        ((unsigned short)0x0002)
@@ -115,18 +115,36 @@ extern VALUE rb_cBigDecimal; https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.h#L115
 
 #define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U
 
-/* Computation mode */
+/* This is used in BigDecimal#mode */
 #define VP_ROUND_MODE            ((unsigned short)0x0100)
-#define VP_ROUND_UP         1
-#define VP_ROUND_DOWN       2
-#define VP_ROUND_HALF_UP    3
-#define VP_ROUND_HALF_DOWN  4
-#define VP_ROUND_CEIL       5
-#define VP_ROUND_FLOOR      6
-#define VP_ROUND_HALF_EVEN  7
+
+/* Rounding mode */
+#define VP_ROUND_UP         RBD_ROUND_UP
+#define VP_ROUND_DOWN       RBD_ROUND_DOWN
+#define VP_ROUND_HALF_UP    RBD_ROUND_HALF_UP
+#define VP_ROUND_HALF_DOWN  RBD_ROUND_HALF_DOWN
+#define VP_ROUND_CEIL       RBD_ROUND_CEIL
+#define VP_ROUND_FLOOR      RBD_ROUND_FLOOR
+#define VP_ROUND_HALF_EVEN  RBD_ROUND_HALF_EVEN
+
+enum rbd_rounding_mode {
+    RBD_ROUND_UP          = 1,
+    RBD_ROUND_DOWN        = 2,
+    RBD_ROUND_HALF_UP     = 3,
+    RBD_ROUND_HALF_DOWN   = 4,
+    RBD_ROUND_CEIL        = 5,
+    RBD_ROUND_FLOOR       = 6,
+    RBD_ROUND_HALF_EVEN   = 7,
+
+    RBD_ROUND_DEFAULT  = RBD_ROUND_HALF_UP,
+    RBD_ROUND_TRUNCATE = RBD_ROUND_DOWN,
+    RBD_ROUND_BANKER   = RBD_ROUND_HALF_EVEN,
+    RBD_ROUND_CEILING  = RBD_ROUND_CEIL
+};
 
 #define BIGDECIMAL_ROUNDING_MODE_DEFAULT  VP_ROUND_HALF_UP
 
+/* Sign flag */
 #define VP_SIGN_NaN                0 /* NaN                      */
 #define VP_SIGN_POSITIVE_ZERO      1 /* Positive zero            */
 #define VP_SIGN_NEGATIVE_ZERO     -1 /* Negative zero            */
@@ -135,6 +153,7 @@ extern VALUE rb_cBigDecimal; https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.h#L153
 #define VP_SIGN_POSITIVE_INFINITE  3 /* Positive infinite number */
 #define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
 
+/* The size of fraction part array */
 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
 #define	FLEXIBLE_ARRAY_SIZE /* */
 #elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
-- 
cgit v1.2.3


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

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