From c747c77f402e12deb559763cc7fa1cd15e36d5b6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 14 Jan 2026 10:08:05 +0900 Subject: [PATCH] mruby-bigint: always use 32-bit limbs by default Remove automatic downgrade to 16-bit limbs on 32-bit Windows. Modern compilers (including MSVC) have supported uint64_t for decades. MRB_NO_MPZ64BIT remains available for constrained platforms. Adjust BATCH_DIVISOR and BATCH_DIGITS for 16-bit limb compatibility: - 32-bit limbs: 10^9 (9 digits per batch) - 16-bit limbs: 10^4 (4 digits per batch) Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 25 +++++++++++++++++-------- mrbgems/mruby-bigint/core/bigint.h | 4 ---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 84b366e4d..a1217ecf7 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -2545,13 +2545,20 @@ dc_scratch_clear(mpz_ctx_t *ctx, dc_to_s_scratch_t *scratch) * The caller must ensure num_digits >= actual digits in x. * Leading zeros are added if x has fewer digits than num_digits. */ -/* Batch divisor: 10^9 for extracting 9 digits at once */ +/* Batch divisor for extracting multiple digits at once */ +#ifdef MRB_NO_MPZ64BIT +/* 16-bit limbs: 10^4 fits in 16 bits */ +#define BATCH_DIVISOR 10000UL +#define BATCH_DIGITS 4 +#else +/* 32-bit limbs: 10^9 fits in 32 bits */ #define BATCH_DIVISOR 1000000000UL #define BATCH_DIGITS 9 +#endif /* - * Divide limb array by 10^9 in place, returning remainder. - * Used for extracting 9 decimal digits at a time. + * Divide limb array by BATCH_DIVISOR in place, returning remainder. + * Used for extracting BATCH_DIGITS decimal digits at a time. * Compilers optimize constant division to multiplication+shift. */ static mp_limb @@ -2598,18 +2605,20 @@ mpz_get_str_dc_recur(mpz_ctx_t *ctx, char *s, mpz_t *x, size_t num_digits, mpz_set(ctx, tmp, x); while (pos > 0 && !zero_p(tmp)) { - /* Divide by 10^9 in place, get remainder as 9 digits */ + /* Divide by BATCH_DIVISOR in place, get remainder as BATCH_DIGITS digits */ mp_limb batch = mpn_div_batch(tmp->p, tmp->sz); trim(tmp); - /* Convert remainder (0-999999999) to 9 digits using table lookup */ - /* Extract last digit (9th) separately since 9 is odd */ + /* Convert remainder to BATCH_DIGITS digits using table lookup */ +#if (BATCH_DIGITS % 2) == 1 + /* Extract last digit separately since BATCH_DIGITS is odd */ if (pos > 0) { s[--pos] = '0' + (char)(batch % 10); batch /= 10; } - /* Extract remaining 8 digits as 4 pairs using lookup table */ - for (int d = 0; d < 4 && pos >= 2; d++) { +#endif + /* Extract remaining digits as pairs using lookup table */ + for (int d = 0; d < BATCH_DIGITS / 2 && pos >= 2; d++) { mp_limb pair = batch % 100; batch /= 100; s[--pos] = digit_pairs[pair * 2 + 1]; diff --git a/mrbgems/mruby-bigint/core/bigint.h b/mrbgems/mruby-bigint/core/bigint.h index 667b923ce..985653913 100644 --- a/mrbgems/mruby-bigint/core/bigint.h +++ b/mrbgems/mruby-bigint/core/bigint.h @@ -30,10 +30,6 @@ #include -#if defined(MRB_INT32) && defined(_WIN32) && !defined(MRB_NO_MPZ64BIT) -#define MRB_NO_MPZ64BIT -#endif - #ifdef MRB_NO_MPZ64BIT typedef uint16_t mp_limb; typedef uint32_t mp_dbl_limb;