mruby-bigint (mrb_bint_2comp): simplify using mpz_2comp()

This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-07-25 16:01:16 +09:00
parent 3d69412ea5
commit 99c078bb6b
2 changed files with 13 additions and 32 deletions
+5 -29
View File
@@ -1776,40 +1776,16 @@ mrb_bint_hash(mrb_state *mrb, mrb_value x)
return mrb_int_value(mrb, hash);
}
/* to be used only from mruby-sprintf */
mrb_value
mrb_bint_2comp(mrb_state *mrb, mrb_value x, mrb_int base)
mrb_bint_2comp(mrb_state *mrb, mrb_value x)
{
struct RBigint *b = RBIGINT(x);
mrb_int i;
for (i=b->mp.sz-1; i>=0; i--) {
if (b->mp.p[i] > 0) break;
}
#ifdef __GNUC__
mrb_int dbits = __builtin_ctz(base);
#else
mrb_int dbits;
switch (base) {
case 16: dbits = 4; break;
case 8: dbits = 3; break;
case 2: dbits = 1; break;
}
#endif
mrb_int topbit = DIG_SIZE * (i+1) - lzb(b->mp.p[i]);
mrb_int nbits = (topbit / dbits + 1) * dbits;
mpz_t one;
mpz_t up;
struct RBigint *b2 = bint_new(mrb);
/* rounding up to nearest power of 2 */
mpz_init_set_int(mrb, &one, 1);
mpz_init(mrb, &up);
mpz_mul_2exp(mrb, &up, &one, nbits);
mpz_clear(mrb, &one);
mpz_add(mrb, &b2->mp, &up, &b->mp);
mpz_clear(mrb, &up);
mpz_set(mrb, &b2->mp, &b->mp);
mpz_2comp(mrb, &b2->mp);
b2->mp.sn = 1;
return mrb_obj_value(b2);
}
+8 -3
View File
@@ -17,7 +17,7 @@
#define BITSPERDIG MRB_INT_BIT
#define EXTENDSIGN(n, l) (((~0U << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0U << (n)))
mrb_value mrb_bint_2comp(mrb_state *mrb, mrb_value x, mrb_int base);
mrb_value mrb_bint_2comp(mrb_state *mrb, mrb_value x);
static char*
remove_sign_bits(char *str, int base)
@@ -599,7 +599,7 @@ retry:
mrb_int n = (mrb_bint_cmp(mrb, val, mrb_fixnum_value(0)));
mrb_bool need_dots = ((flags & FPLUS) == 0) && (base == 16 || base == 8 || base == 2) && n < 0;
if (need_dots) {
val = mrb_bint_2comp(mrb, val, base);
val = mrb_bint_2comp(mrb, val);
dots = 1;
v = -1;
}
@@ -665,6 +665,11 @@ retry:
fc = '1'; break;
}
if (dots) {
while (*s == fc) {
s++; len--;
}
}
if (*p == 'X') {
char *pp = s;
int c;
@@ -672,7 +677,7 @@ retry:
*pp = toupper(c);
pp++;
}
if (base == 16 && fc) {
if (base == 16) {
fc = 'F';
}
}