Merge pull request #366 from czurnieden/radix_size_with_log Use of mp_ilogb in mp_radix_size
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
diff --git a/bn_mp_radix_size.c b/bn_mp_radix_size.c
index b96f487..5ed9ab1 100644
--- a/bn_mp_radix_size.c
+++ b/bn_mp_radix_size.c
@@ -6,12 +6,9 @@
/* returns size of ASCII representation */
mp_err mp_radix_size(const mp_int *a, int radix, int *size)
{
- mp_err err;
- int digs;
- mp_int t;
- mp_digit d;
-
- *size = 0;
+ mp_err err;
+ mp_int a_;
+ uint32_t b;
/* make sure the radix is in range */
if ((radix < 2) || (radix > 64)) {
@@ -23,43 +20,18 @@ mp_err mp_radix_size(const mp_int *a, int radix, int *size)
return MP_OKAY;
}
- /* special case for binary */
- if (radix == 2) {
- *size = (mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1);
- return MP_OKAY;
- }
-
- /* digs is the digit count */
- digs = 0;
-
- /* if it's negative add one for the sign */
- if (a->sign == MP_NEG) {
- ++digs;
- }
-
- /* init a copy of the input */
- if ((err = mp_init_copy(&t, a)) != MP_OKAY) {
- return err;
+ a_ = *a;
+ a_.sign = MP_ZPOS;
+ if ((err = mp_log_u32(&a_, (uint32_t)radix, &b)) != MP_OKAY) {
+ goto LBL_ERR;
}
- /* force temp to positive */
- t.sign = MP_ZPOS;
+ *size = (int)b;
- /* fetch out all of the digits */
- while (!MP_IS_ZERO(&t)) {
- if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {
- goto LBL_ERR;
- }
- ++digs;
- }
-
- /* return digs + 1, the 1 is for the NULL byte that would be required. */
- *size = digs + 1;
- err = MP_OKAY;
+ /* mp_ilogb truncates to zero, hence we need one extra put on top and one for `\0`. */
+ *size += 2 + (a->sign == MP_NEG);
LBL_ERR:
- mp_clear(&t);
return err;
}
-
#endif
diff --git a/demo/test.c b/demo/test.c
index c1fc878..4c3f1cc 100644
--- a/demo/test.c
+++ b/demo/test.c
@@ -2282,6 +2282,62 @@ LTM_ERR:
return EXIT_FAILURE;
}
+static int test_mp_radix_size(void)
+{
+ mp_err err;
+ mp_int a;
+ int radix, size;
+/* *INDENT-OFF* */
+ int results[65] = {
+ 0, 0, 1627, 1027, 814, 702, 630, 581, 543,
+ 514, 491, 471, 455, 441, 428, 418, 408, 399,
+ 391, 384, 378, 372, 366, 361, 356, 352, 347,
+ 343, 340, 336, 333, 330, 327, 324, 321, 318,
+ 316, 314, 311, 309, 307, 305, 303, 301, 299,
+ 298, 296, 294, 293, 291, 290, 288, 287, 285,
+ 284, 283, 281, 280, 279, 278, 277, 276, 275,
+ 273, 272
+ };
+/* *INDENT-ON* */
+
+ mp_init(&a);
+
+ /* number to result in a different size for every base: 67^(4 * 67) */
+ mp_set(&a, 67);
+ if ((err = mp_expt_u32(&a, 268u, &a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+
+ for (radix = 2; radix < 65; radix++) {
+ if ((err = mp_radix_size(&a, radix, &size)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (size != results[radix]) {
+ fprintf(stderr, "mp_radix_size: result for base %d was %d instead of %d\n",
+ radix, size, results[radix]);
+ goto LTM_ERR;
+ }
+ a.sign = MP_NEG;
+ if ((err = mp_radix_size(&a, radix, &size)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (size != (results[radix] + 1)) {
+ fprintf(stderr, "mp_radix_size: result for base %d was %d instead of %d\n",
+ radix, size, results[radix]);
+ goto LTM_ERR;
+ }
+ a.sign = MP_ZPOS;
+ }
+
+ mp_clear(&a);
+ return EXIT_SUCCESS;
+LTM_ERR:
+ mp_clear(&a);
+ return EXIT_FAILURE;
+}
+
+
+
static int test_mp_read_write_ubin(void)
{
mp_int a, b, c;
@@ -2446,6 +2502,7 @@ static int unit_tests(int argc, char **argv)
T1(mp_read_write_sbin, MP_TO_SBIN),
T1(mp_reduce_2k, MP_REDUCE_2K),
T1(mp_reduce_2k_l, MP_REDUCE_2K_L),
+ T1(mp_radix_size, MP_RADIX_SIZE),
#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
T1(mp_set_double, MP_SET_DOUBLE),
#endif
diff --git a/tommath_class.h b/tommath_class.h
index b3c5dbd..209d809 100644
--- a/tommath_class.h
+++ b/tommath_class.h
@@ -750,10 +750,7 @@
#endif
#if defined(BN_MP_RADIX_SIZE_C)
-# define BN_MP_CLEAR_C
-# define BN_MP_COUNT_BITS_C
-# define BN_MP_DIV_D_C
-# define BN_MP_INIT_COPY_C
+# define BN_MP_LOG_U32_C
#endif
#if defined(BN_MP_RADIX_SMAP_C)
diff --git a/tommath_superclass.h b/tommath_superclass.h
index d88bce9..bb606b5 100644
--- a/tommath_superclass.h
+++ b/tommath_superclass.h
@@ -28,6 +28,7 @@
# define BN_MP_NEG_C
# define BN_MP_PRIME_FROBENIUS_UNDERWOOD_C
# define BN_MP_RADIX_SIZE_C
+# define BN_MP_LOG_U32_C
# define BN_MP_RAND_C
# define BN_MP_REDUCE_C
# define BN_MP_REDUCE_2K_L_C