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

ruby-changes:74475

From: Kenta <ko1@a...>
Date: Sun, 13 Nov 2022 21:33:44 +0900 (JST)
Subject: [ruby-changes:74475] 8d82f4ba1c (master): [ruby/bigdecimal] Add specific value allocators

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

From 8d82f4ba1c715da6a50b8626792a49c343914efd Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@m...>
Date: Sun, 13 Nov 2022 21:05:46 +0900
Subject: [ruby/bigdecimal] Add specific value allocators

* Add NewZero* and NewOne* function families
* Use them instead of VpAlloc for allocating 0 and 1

https://github.com/ruby/bigdecimal/commit/9276a94ac7
---
 ext/bigdecimal/bigdecimal.c | 481 ++++++++++++++++++++++++++------------------
 1 file changed, 282 insertions(+), 199 deletions(-)

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index a914d99589..a5b80464d0 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -158,9 +158,33 @@ rbd_allocate_struct(size_t const internal_digits) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L158
     return real;
 }
 
-static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
+static size_t
+rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
+{
+    size_t const len = roomof(digits, BASE_FIG);
+    if (limit_precision) {
+        size_t const prec_limit = VpGetPrecLimit();
+        if (prec_limit > 0) {
+            /* NOTE: 2 more digits for rounding and division */
+            size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
+            if (len > max_len)
+                return max_len;
+        }
+    }
+
+    return len;
+}
 
 static inline Real *
+rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
+{
+    size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
+    return rbd_allocate_struct(internal_digits);
+}
+
+static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
+
+static Real *
 rbd_reallocate_struct(Real *real, size_t const internal_digits)
 {
     size_t const size = rbd_struct_size(internal_digits);
@@ -184,23 +208,54 @@ rbd_free_struct(Real *real) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L208
     }
 }
 
+#define NewZero rbd_allocate_struct_zero
 static Real *
-rbd_allocate_struct_zero(size_t const digits, int sign)
+rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
 {
-    size_t const len = roomof(digits, BASE_FIG);
-    Real *real = rbd_allocate_struct(len);
+    Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
     VpSetZero(real, sign);
     return real;
 }
 
+#define NewZeroLimited rbd_allocate_struct_zero_limited
+static inline Real *
+rbd_allocate_struct_zero_limited(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_zero(sign, digits, true);
+}
+
+#define NewZeroNolimit rbd_allocate_struct_zero_nolimit
+static inline Real *
+rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_zero(sign, digits, false);
+}
+
+#define NewOne rbd_allocate_struct_one
 static Real *
-rbd_allocate_struct_one(size_t const digits, int sign)
+rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
 {
-    Real *real = rbd_allocate_struct_zero(digits, sign);
+    Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
     VpSetOne(real);
+    if (sign < 0)
+        VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
     return real;
 }
 
+#define NewOneLimited rbd_allocate_struct_one_limited
+static inline Real *
+rbd_allocate_struct_one_limited(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_one(sign, digits, true);
+}
+
+#define NewOneNolimit rbd_allocate_struct_one_nolimit
+static inline Real *
+rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_one(sign, digits, false);
+}
+
 /*
  * ================== Ruby Interface part ==========================
  */
@@ -254,6 +309,56 @@ static const rb_data_type_t BigDecimal_data_type = { https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L309
 #endif
 };
 
+static Real *
+rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
+{
+    Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
+    if (real != NULL) {
+        VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+        BigDecimal_wrap_struct(obj, real);
+    }
+    return real;
+}
+
+#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
+static inline Real *
+rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
+static Real *
+rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
+{
+    Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
+    if (real != NULL) {
+        VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+        BigDecimal_wrap_struct(obj, real);
+    }
+    return real;
+}
+
+#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
+static inline Real *
+rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
+{
+    return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
 static inline int
 is_kind_of_BigDecimal(VALUE const v)
 {
@@ -1349,17 +1454,17 @@ BigDecimal_add(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1454
 
     mx = GetAddSubPrec(a, b);
     if (mx == (size_t)-1L) {
-        GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
-	VpAddSub(c, a, b, 1);
+        GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
+        VpAddSub(c, a, b, 1);
     }
     else {
-        GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
-	if(!mx) {
-	    VpSetInf(c, VpGetSign(a));
-	}
-	else {
-	    VpAddSub(c, a, b, 1);
-	}
+        GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
+        if (!mx) {
+            VpSetInf(c, VpGetSign(a));
+        }
+        else {
+            VpAddSub(c, a, b, 1);
+        }
     }
     return VpCheckGetValue(c);
 }
@@ -1404,17 +1509,17 @@ BigDecimal_sub(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1509
 
     mx = GetAddSubPrec(a,b);
     if (mx == (size_t)-1L) {
-        GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
-	VpAddSub(c, a, b, -1);
+        GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
+        VpAddSub(c, a, b, -1);
     }
     else {
-        GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
-	if (!mx) {
-	    VpSetInf(c,VpGetSign(a));
-	}
-	else {
-	    VpAddSub(c, a, b, -1);
-	}
+        GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
+        if (!mx) {
+            VpSetInf(c,VpGetSign(a));
+        }
+        else {
+            VpAddSub(c, a, b, -1);
+        }
     }
     return VpCheckGetValue(c);
 }
@@ -1654,7 +1759,7 @@ BigDecimal_neg(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1759
     ENTER(5);
     Real *c, *a;
     GUARD_OBJ(a, GetVpValue(self, 1));
-    GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
+    GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
     VpAsgn(c, a, -1);
     return VpCheckGetValue(c);
 }
@@ -1681,7 +1786,7 @@ BigDecimal_mult(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1786
     SAVE(b);
 
     mx = a->Prec + b->Prec;
-    GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
+    GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
     VpMult(c, a, b);
     return VpCheckGetValue(c);
 }
@@ -1728,8 +1833,8 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1833
     if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
         mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
 
-    GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
-    GUARD_OBJ((*res), VpCreateRbObject((mx + 1)*2 + 2*BASE_FIG, "#0", true));
+    GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
+    GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
     VpDivd(*c, *res, a, b);
 
     return Qnil;
@@ -1884,12 +1989,12 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1989
     if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
         mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
 
-    GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
-    GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
+    GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
+    GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
     VpDivd(c, res, a, b);
 
     mx = c->Prec * BASE_FIG;
-    GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
+    GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
     VpActiveRound(d, c, VP_ROUND_DOWN, 0);
 
     VpMult(res, d, b);
@@ -1900,7 +2005,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2005
         res = rbd_reallocate_struct(res, d->MaxPrec);
         res->MaxPrec = d->MaxPrec;
         VpAddSub(res, d, VpOne(), -1);
-        GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
+        GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
         VpAddSub(d, c, b, 1);
         *div = res;
         *mod = d;
@@ -1964,17 +2069,1 (... truncated)

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

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