Skip to content

Commit 724db0a

Browse files
committed
Addition of mp_radix_size_overestimate (behaviour like the function mpz_sizeinbase in GMP); changed mp_radix_size to use mp_ilogb
1 parent 0da3c65 commit 724db0a

14 files changed

+579
-93
lines changed

bn_mp_fwrite.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream)
2727
err = MP_ERR;
2828
goto LBL_ERR;
2929
}
30+
3031
err = MP_OKAY;
3132

3233
LBL_ERR:

bn_mp_radix_size.c

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
44
/* SPDX-License-Identifier: Unlicense */
55

6-
/* returns size of ASCII reprensentation */
6+
/* returns exact size of ASCII reprensentation */
77
mp_err mp_radix_size(const mp_int *a, int radix, int *size)
88
{
9-
mp_err err;
10-
int digs;
11-
mp_int t;
12-
mp_digit d;
9+
mp_err err;
10+
mp_int a_, b;
11+
int rem, bit_count, ln2;
1312

1413
*size = 0;
1514

@@ -23,42 +22,66 @@ mp_err mp_radix_size(const mp_int *a, int radix, int *size)
2322
return MP_OKAY;
2423
}
2524

26-
/* special case for binary */
27-
if (radix == 2) {
28-
*size = mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1;
25+
/* A small shortcut for powers of two. */
26+
switch (radix) {
27+
case 4:
28+
ln2 = 2;
29+
break;
30+
case 8:
31+
ln2 = 3;
32+
break;
33+
case 16:
34+
ln2 = 4;
35+
break;
36+
case 32:
37+
ln2 = 5;
38+
break;
39+
case 64:
40+
ln2 = 6;
41+
break;
42+
default:
43+
ln2 = 0;
44+
break;
45+
}
46+
if (ln2 != 0) {
47+
bit_count = mp_count_bits(a);
48+
*size = bit_count/ln2;
49+
rem = bit_count - ((*size) * ln2);
50+
/* Add 1 for the remainder if any and 1 for "\0". */
51+
*size += (rem == 0) ? 1 : 2;
52+
/* And one extra character for the minus sign */
53+
if (a->sign == MP_NEG) {
54+
(*size)++;
55+
}
2956
return MP_OKAY;
3057
}
3158

32-
/* digs is the digit count */
33-
digs = 0;
3459

35-
/* if it's negative add one for the sign */
36-
if (a->sign == MP_NEG) {
37-
++digs;
60+
if ((err = mp_init(&b)) != MP_OKAY) {
61+
goto LBL_ERR;
3862
}
3963

40-
/* init a copy of the input */
41-
if ((err = mp_init_copy(&t, a)) != MP_OKAY) {
42-
return err;
64+
a_ = *a;
65+
a_.sign = MP_ZPOS;
66+
if ((err = mp_ilogb(&a_, (uint32_t)radix, &b)) != MP_OKAY) {
67+
goto LBL_ERR;
4368
}
4469

45-
/* force temp to positive */
46-
t.sign = MP_ZPOS;
70+
*size = (int)mp_get_l(&b);
4771

48-
/* fetch out all of the digits */
49-
while (!MP_IS_ZERO(&t)) {
50-
if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {
51-
goto LBL_ERR;
52-
}
53-
++digs;
72+
/* mp_ilogb truncates to zero, hence we need one extra put on top. */
73+
(*size)++;
74+
75+
/* The sign needs to have a place to live, too*/
76+
if (a->sign == MP_NEG) {
77+
(*size)++;
5478
}
5579

56-
/* return digs + 1, the 1 is for the NULL byte that would be required. */
57-
*size = digs + 1;
58-
err = MP_OKAY;
80+
/* return digs + 1, the 1 is for the NUL byte that would be required. */
81+
(*size)++;
5982

6083
LBL_ERR:
61-
mp_clear(&t);
84+
mp_clear(&b);
6285
return err;
6386
}
6487

0 commit comments

Comments
 (0)