summaryrefslogtreecommitdiff
path: root/ext/bigdecimal
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bigdecimal')
-rw-r--r--ext/bigdecimal/bigdecimal.c23
-rw-r--r--ext/bigdecimal/bigdecimal.h16
2 files changed, 27 insertions, 12 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index b9ba0ea62d..704f04510e 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -2727,23 +2727,22 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
vp->frac[0] = (DECDIG)uval;
}
else {
- const size_t len = (size_t)ceil(log10((double)uval) / BASE_FIG);
-
- vp = VpAllocReal(len);
- vp->MaxPrec = len;
- vp->Prec = len;
- vp->exponent = len;
- VpSetSign(vp, 1);
-
- size_t i, ntz = 0;
- for (i = 0; i < len; ++i) {
+ DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
+ size_t exp = 0, ntz = 0;
+ for (; uval > 0; ++exp) {
DECDIG r = uval % BASE;
- vp->frac[len - i - 1] = r;
if (r == 0) ++ntz;
+ buf[BIGDECIMAL_INT64_MAX_LENGTH - exp - 1] = r;
uval /= BASE;
}
- vp->Prec -= ntz;
+ const size_t len = exp - ntz;
+ vp = VpAllocReal(len);
+ vp->MaxPrec = len;
+ vp->Prec = len;
+ vp->exponent = exp;
+ VpSetSign(vp, 1);
+ MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - exp, DECDIG, len);
}
return BigDecimal_wrap_struct(obj, vp);
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index acc00b8127..bd1c46743e 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -54,9 +54,25 @@
#if SIZEOF_DECDIG == 4
# define BIGDECIMAL_BASE ((DECDIG)1000000000U)
# define BIGDECIMAL_COMPONENT_FIGURES 9
+/*
+ * The number of components required for a 64-bit integer.
+ *
+ * INT64_MAX: 9_223372036_854775807
+ * UINT64_MAX: 18_446744073_709551615
+ */
+# define BIGDECIMAL_INT64_MAX_LENGTH 3
+
#elif SIZEOF_DECDIG == 2
# define BIGDECIMAL_BASE ((DECDIG)10000U)
# define BIGDECIMAL_COMPONENT_FIGURES 4
+/*
+ * The number of components required for a 64-bit integer.
+ *
+ * INT64_MAX: 922_3372_0368_5477_5807
+ * UINT64_MAX: 1844_6744_0737_0955_1615
+ */
+# define BIGDECIMAL_INT64_MAX_LENGTH 5
+
#else
# error Unknown size of DECDIG
#endif