From 5fd8b44502d8cb517c2889fc5416cb0045fa7bf1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Jan 2026 08:42:19 +0900 Subject: [PATCH] mruby-bigint: fix D&C to_s digit loss at split boundary When converting large numbers to strings using D&C algorithm, the base case extracts digits in batches of 9 (for 32-bit limbs). The extraction logic: 1 leading digit + 4 pairs (8 digits) = 9 digits. The pair extraction loop condition `pos >= 2` exits when pos < 2, but when the remaining batch still has value and pos == 1, that final digit was being lost and replaced with '0' by the padding loop. This caused roundtrip failures (x.to_s.to_i != x) for numbers just above the D&C threshold (1000 digits), where the split boundary produced a lo part requiring exactly the right number of digits to trigger this edge case. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 7116aaa36..31ad49992 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -2609,6 +2609,10 @@ mpz_to_s_dc_recur(mpz_ctx_t *ctx, char *s, mpz_t *x, size_t num_digits, s[--pos] = digit_pairs[pair * 2 + 1]; s[--pos] = digit_pairs[pair * 2]; } + /* Extract any remaining single digit when pos == 1 */ + if (pos > 0 && batch > 0) { + s[--pos] = '0' + (char)(batch % 10); + } /* Swap tmp and q pointers for next iteration */ mpz_t *swap = tmp;