aboutsummaryrefslogtreecommitdiffstats
path: root/ext/bigdecimal
diff options
context:
space:
mode:
authorcryptogopher <cryptogopher@noreply.me>2023-07-01 16:24:53 +0200
committergit <svn-admin@ruby-lang.org>2023-07-05 20:15:52 +0000
commit10f59dcbcd21807887ea0ebb1d0732f0fa32d416 (patch)
tree74d00240919bc2e4ef913f9541069eaf30557cda /ext/bigdecimal
parent1dde9d726099fc4e4b06b8c848c85eac195c521b (diff)
downloadruby-10f59dcbcd21807887ea0ebb1d0732f0fa32d416.tar.gz
[ruby/bigdecimal] Add .to_s('F') digit grouping for integer part
https://github.com/ruby/bigdecimal/commit/f63544d465
Diffstat (limited to 'ext/bigdecimal')
-rw-r--r--ext/bigdecimal/bigdecimal.c99
1 files changed, 47 insertions, 52 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 8cbe686e71..6239808a23 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -2689,7 +2689,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
* A space at the start of s returns positive values with a leading space.
*
* If s contains a number, a space is inserted after each group of that many
- * fractional digits.
+ * digits, starting from '.' and counting outwards.
*
* If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
*
@@ -6706,95 +6706,90 @@ VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
{
size_t i, n;
- DECDIG m, e, nn;
+ DECDIG m, e;
char *p = buf;
- size_t plen = buflen;
+ size_t plen = buflen, delim = fFmt;
ssize_t ex;
if (VpToSpecialString(a, buf, buflen, fPlus)) return;
-#define ADVANCE(n) do { \
- if (plen < n) goto overflow; \
- p += n; \
- plen -= n; \
+#define APPEND(c, group) do { \
+ if (plen < 1) goto overflow; \
+ if (group && delim == 0) { \
+ *p = ' '; \
+ p += 1; \
+ plen -= 1; \
+ } \
+ if (plen < 1) goto overflow; \
+ *p = c; \
+ p += 1; \
+ plen -= 1; \
+ if (group) delim = (delim + 1) % fFmt; \
} while (0)
if (BIGDECIMAL_NEGATIVE_P(a)) {
- *p = '-';
- ADVANCE(1);
+ APPEND('-', false);
}
else if (fPlus == 1) {
- *p = ' ';
- ADVANCE(1);
+ APPEND(' ', false);
}
else if (fPlus == 2) {
- *p = '+';
- ADVANCE(1);
+ APPEND('+', false);
}
n = a->Prec;
ex = a->exponent;
if (ex <= 0) {
- *p = '0'; ADVANCE(1);
- *p = '.'; ADVANCE(1);
- while (ex < 0) {
- for (i=0; i < BASE_FIG; ++i) {
- *p = '0'; ADVANCE(1);
- }
- ++ex;
+ APPEND('0', false);
+ APPEND('.', false);
+ }
+ while (ex < 0) {
+ for (i=0; i < BASE_FIG; ++i) {
+ APPEND('0', fFmt > 0);
}
- ex = -1;
+ ++ex;
}
for (i = 0; i < n; ++i) {
- --ex;
- if (i == 0 && ex >= 0) {
- size_t n = snprintf(p, plen, "%lu", (unsigned long)a->frac[i]);
- if (n > plen) goto overflow;
- ADVANCE(n);
- }
- else {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- *p = (char)(nn + '0');
- ADVANCE(1);
- e = e - nn * m;
+ m = BASE1;
+ e = a->frac[i];
+ if (i == 0 && ex > 0) {
+ for (delim = 0; e / m == 0; delim++) {
m /= 10;
}
+ if (fFmt > 0) {
+ delim = 2*fFmt - (ex * BASE_FIG - delim) % fFmt;
+ }
}
- if (ex == 0) {
- *p = '.';
- ADVANCE(1);
+ while (m && (e || (i < n - 1) || ex > 0)) {
+ APPEND((char)(e / m + '0'), fFmt > 0);
+ e %= m;
+ m /= 10;
+ }
+ if (--ex == 0) {
+ APPEND('.', false);
+ delim = fFmt;
}
}
- while (--ex>=0) {
- m = BASE;
- while (m /= 10) {
- *p = '0';
- ADVANCE(1);
+
+ while (ex > 0) {
+ for (i=0; i < BASE_FIG; ++i) {
+ APPEND('0', fFmt > 0);
}
- if (ex == 0) {
- *p = '.';
- ADVANCE(1);
+ if (--ex == 0) {
+ APPEND('.', false);
}
}
*p = '\0';
- while (p - 1 > buf && p[-1] == '0') {
- *(--p) = '\0';
- ++plen;
- }
if (p - 1 > buf && p[-1] == '.') {
snprintf(p, plen, "0");
}
- if (fFmt) VpFormatSt(buf, fFmt);
overflow:
return;
-#undef ADVANCE
+#undef APPEND
}
/*