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

ruby-changes:74469

From: Kenta <ko1@a...>
Date: Sun, 13 Nov 2022 15:01:42 +0900 (JST)
Subject: [ruby-changes:74469] 802dce4acd (master): [ruby/bigdecimal] Add and use specific value allocators

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

From 802dce4acd97234bef88fe4bbb98db5ab90c45d9 Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@m...>
Date: Sun, 13 Nov 2022 14:59:55 +0900
Subject: [ruby/bigdecimal] Add and use specific value allocators

* Add rbd_allocate_struct_zero for making 0.0
* Add rbd_allocate_struct_one for making 1.0
* Use them to replace VpAlloc calls
* Renmae VpPt5 to VpConstPt5

https://github.com/ruby/bigdecimal/commit/40c826f5e6
---
 ext/bigdecimal/bigdecimal.c | 69 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 50 insertions(+), 19 deletions(-)

diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index bad10ae832..a914d99589 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -144,7 +144,8 @@ PUREFUNC(static inline size_t rbd_struct_size(size_t const)); https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L144
 static inline size_t
 rbd_struct_size(size_t const internal_digits)
 {
-    return offsetof(Real, frac) + sizeof(DECDIG) * internal_digits;
+    size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
+    return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
 }
 
 static inline Real *
@@ -153,6 +154,7 @@ rbd_allocate_struct(size_t const internal_digits) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L154
     size_t const size = rbd_struct_size(internal_digits);
     Real *real = ruby_xcalloc(1, size);
     atomic_allocation_count_inc();
+    real->MaxPrec = internal_digits;
     return real;
 }
 
@@ -164,6 +166,7 @@ rbd_reallocate_struct(Real *real, size_t const internal_digits) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L166
     size_t const size = rbd_struct_size(internal_digits);
     VALUE obj = real ? real->obj : 0;
     Real *new_real = (Real *)ruby_xrealloc(real, size);
+    new_real->MaxPrec = internal_digits;
     if (obj) {
         new_real->obj = 0;
         BigDecimal_wrap_struct(obj, new_real);
@@ -181,6 +184,23 @@ rbd_free_struct(Real *real) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L184
     }
 }
 
+static Real *
+rbd_allocate_struct_zero(size_t const digits, int sign)
+{
+    size_t const len = roomof(digits, BASE_FIG);
+    Real *real = rbd_allocate_struct(len);
+    VpSetZero(real, sign);
+    return real;
+}
+
+static Real *
+rbd_allocate_struct_one(size_t const digits, int sign)
+{
+    Real *real = rbd_allocate_struct_zero(digits, sign);
+    VpSetOne(real);
+    return real;
+}
+
 /*
  * ================== Ruby Interface part ==========================
  */
@@ -4517,7 +4537,7 @@ static int gfCheckVal = 1;      /* Value checking flag in VpNmlz()  */ https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4537
 #endif /* BIGDECIMAL_DEBUG */
 
 static Real *VpConstOne;    /* constant 1.0 */
-static Real *VpPt5;        /* constant 0.5 */
+static Real *VpConstPt5;    /* constant 0.5 */
 #define maxnr 100UL    /* Maximum iterations for calculating sqrt. */
                 /* used in VpSqrt() */
 
@@ -4936,9 +4956,13 @@ VpInit(DECDIG BaseVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4956
     /* Setup +/- Inf  NaN -0 */
     VpGetDoubleNegZero();
 
-    /* Allocates Vp constants. */
-    VpConstOne = VpAlloc(1UL, "1", 1, 1);
-    VpPt5 = VpAlloc(1UL, ".5", 1, 1);
+    /* Const 1.0 */
+    VpConstOne = rbd_allocate_struct_one(1, 1);
+
+    /* Const 0.5 */
+    VpConstPt5 = rbd_allocate_struct_one(1, 1);
+    VpConstPt5->exponent = 0;
+    VpConstPt5->frac[0] = 5*BASE1;
 
 #ifdef BIGDECIMAL_DEBUG
     gnAlloc = 0;
@@ -5838,7 +5862,7 @@ VpMult(Real *c, Real *a, Real *b) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L5862
 
     if (MxIndC < MxIndAB) {    /* The Max. prec. of c < Prec(a)+Prec(b) */
 	w = c;
-	c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
+        c = rbd_allocate_struct_zero((size_t)((MxIndAB + 1) * BASE_FIG), 1);
 	MxIndC = MxIndAB;
     }
 
@@ -7003,8 +7027,9 @@ VpSqrt(Real *y, Real *x) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L7027
     if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
 
     /* allocate temporally variables  */
-    f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
-    r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
+    /* TODO: reconsider MaxPrec of f and r */
+    f = rbd_allocate_struct_one(y->MaxPrec * (BASE_FIG + 2), 1);
+    r = rbd_allocate_struct_one((n + n) * (BASE_FIG + 2), 1);
 
     nr = 0;
     y_prec = y->MaxPrec;
@@ -7029,16 +7054,21 @@ VpSqrt(Real *y, Real *x) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L7054
     f->MaxPrec = y->MaxPrec + 1;
     n = (SIGNED_VALUE)(y_prec * BASE_FIG);
     if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
+
+    /*
+     * Perform: y_{n+1} = (y_n - x/y_n) / 2
+     */
     do {
-	y->MaxPrec *= 2;
-	if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
-	f->MaxPrec = y->MaxPrec;
-	VpDivd(f, r, x, y);      /* f = x/y    */
-	VpAddSub(r, f, y, -1);   /* r = f - y  */
-	VpMult(f, VpPt5, r);     /* f = 0.5*r  */
-	if (VpIsZero(f))         goto converge;
-	VpAddSub(r, f, y, 1);    /* r = y + f  */
-	VpAsgn(y, r, 1);         /* y = r      */
+        y->MaxPrec *= 2;
+        if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
+        f->MaxPrec = y->MaxPrec;
+        VpDivd(f, r, x, y);        /* f = x/y    */
+        VpAddSub(r, f, y, -1);     /* r = f - y  */
+        VpMult(f, VpConstPt5, r);  /* f = 0.5*r  */
+        if (VpIsZero(f))
+            goto converge;
+        VpAddSub(r, f, y, 1);      /* r = y + f  */
+        VpAsgn(y, r, 1);           /* y = r      */
     } while (++nr < n);
 
 #ifdef BIGDECIMAL_DEBUG
@@ -7455,9 +7485,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L7485
     }
 
     /* Allocate working variables  */
+    /* TODO: reconsider MaxPrec of w1 and w2 */
+    w1 = rbd_allocate_struct_zero((y->MaxPrec + 2) * BASE_FIG, 1);
+    w2 = rbd_allocate_struct_zero((w1->MaxPrec * 2 + 1) * BASE_FIG, 1);
 
-    w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
-    w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
     /* calculation start */
 
     VpAsgn(y, x, 1);
-- 
cgit v1.2.3


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

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