Extract ruby_convert_to_digits inline function

For arbitrary base within 2..36, including 10.
This commit is contained in:
Nobuyoshi Nakada 2026-11-02 14:09:40 +09:00
parent a990df74db
commit 4faedd7373
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
Notes: git 2026-11-02 08:39:44 +00:00
3 changed files with 29 additions and 39 deletions

View File

@ -4822,7 +4822,6 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
{
size_t j;
BDIGIT_DBL num;
char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
int beginning = !b2s->ptr;
size_t len = 0;
@ -4830,45 +4829,24 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
num = bary2bdigitdbl(xds, xn);
if (beginning) {
char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p = buf;
if (num == 0)
return;
p = buf;
j = sizeof(buf);
if (b2s->base == 10) {
/* Emit two decimal digits per iteration from ruby_decimal_digit_pairs.
* See the comment on the table in bignum.c near ruby_digitmap. */
j -= ruby_convert_to_decimals(&p[j], num);
}
else {
do {
unsigned int idx = (unsigned int)(num % b2s->base);
num /= b2s->base;
p[--j] = ruby_digitmap[idx];
} while (num);
}
j -= ruby_convert_to_digits(&p[j], num, b2s->base);
len = sizeof(buf) - j;
big2str_alloc(b2s, len + taillen);
MEMCPY(b2s->ptr, buf + j, char, len);
}
else {
p = b2s->ptr;
char *p = b2s->ptr;
j = b2s->hbase2_numdigits;
if (b2s->base == 10) {
/* Non-beginning chunks must emit EXACTLY hbase2_numdigits,
* zero-padded on the left. Consume num in 2-digit groups,
* handle the odd trailing digit, then memset remaining
* positions with '0'. */
j -= ruby_convert_to_decimals(&p[j], num);
if (j > 0) {
memset(p, '0', j);
}
}
else {
do {
unsigned int idx = (unsigned int)(num % b2s->base);
num /= b2s->base;
p[--j] = ruby_digitmap[idx];
} while (j);
j -= ruby_convert_to_digits(&p[j], num, b2s->base);
/* Non-beginning chunks must emit EXACTLY hbase2_numdigits,
* zero-padded on the left. Consume num, then memset
* remaining positions with '0'. */
if (j > 0) {
memset(p, '0', j);
}
len = b2s->hbase2_numdigits;
}

View File

@ -143,6 +143,25 @@ ruby_convert_to_decimals(char *dest, BDIGIT_DBL num)
return (size_t)(dest - b);
}
/* Stores the string for num using base as the radix, backward from
* dest. base must be 2..36. Returns the stored size. */
static inline size_t
ruby_convert_to_digits(char *dest, BDIGIT_DBL num, unsigned int base)
{
RBIMPL_ASSERT_OR_ASSUME(base >= 2);
RBIMPL_ASSERT_OR_ASSUME(base <= 36);
if (base == 10) {
return ruby_convert_to_decimals(dest, num);
}
char *b = dest;
do {
unsigned int idx = (unsigned int)(num % base);
num /= base;
*--b = ruby_digitmap[idx];
} while (num);
return (size_t)(dest - b);
}
double rb_big_fdiv_double(VALUE x, VALUE y);
VALUE rb_big_uminus(VALUE x);
VALUE rb_big_hash(VALUE);

View File

@ -4092,14 +4092,7 @@ rb_fix2str(VALUE x, int base)
else {
u = val;
}
if (base == 10) {
b -= ruby_convert_to_decimals(b, u);
}
else {
do {
*--b = ruby_digitmap[(unsigned int)(u % base)];
} while (u /= base);
}
b -= ruby_convert_to_digits(b, u, base);
if (neg) {
*--b = '-';
}