diff --git a/demo/test.c b/demo/test.c index a9362036..0132baee 100644 --- a/demo/test.c +++ b/demo/test.c @@ -1158,7 +1158,7 @@ static int test_mp_read_radix(void) size_t written, maxlen; int bignum, i; - char *buffer, *bcpy; + char *buffer, *bcpy, *startb; clock_t start, stop, t_slow, t_fast; @@ -1191,18 +1191,19 @@ static int test_mp_read_radix(void) /* Test the fast method with a slightly larger number */ - /* Must be bigger than the cut-off value, of course */ - bignum = (2 * 20 * MP_RADIX_BARRETT_START_MULTIPLICATOR) * 10; + /* Needs to be big enough to make a sufficiently large timing difference */ + bignum = 30000; buffer = (char *)malloc((size_t)(bignum + 2)); if (buffer == NULL) { goto LBL_ERR; } DO(mp_rand(&a, bignum / MP_DIGIT_BIT)); - printf("\nNumber of limbs in &b = %d, bit_count of &b = %d\n", bignum / MP_DIGIT_BIT, mp_count_bits(&a)); + fprintf(stderr,"\nNumber of limbs in &b = %d, bit_count of &b = %d\n", bignum / MP_DIGIT_BIT, mp_count_bits(&a)); start = clock(); for (i = 2; i < 65; i++) { /* printf("FAST radix = %d\n",i); */ DO(mp_to_radix(&a, buffer, (size_t)(bignum + 1), &written, i)); + mp_zero(&b); DO(mp_read_radix(&b, buffer, i)); EXPECT(mp_cmp(&a, &b) == MP_EQ); } @@ -1215,7 +1216,11 @@ static int test_mp_read_radix(void) /* printf("SLOW radix = %d\n",i); */ maxlen = (size_t)(bignum + 1); bcpy = buffer; + /* s_mp_slower_to_radix is very rudimentary as a stand-alone */ + startb = bcpy; DO(s_mp_slower_to_radix(&a, &bcpy, &maxlen, &written, i, false)); + bcpy = startb; + mp_zero(&b); DO(s_mp_slower_read_radix(&b, bcpy, 0, strlen(bcpy), i)); EXPECT(mp_cmp(&a, &b) == MP_EQ); } @@ -1226,7 +1231,7 @@ static int test_mp_read_radix(void) fprintf(stderr,"SLOW: %.10f, FAST: %.10f\n", (double)t_slow/(double)CLOCKS_PER_SEC, (double)t_fast/(double)CLOCKS_PER_SEC); - /* Check if the branching works. + /* Check if the branching works. */ if (MP_HAS(S_MP_FASTER_READ_RADIX) && MP_HAS(S_MP_FASTER_TO_RADIX)) { if (t_fast > t_slow) { fprintf(stderr, "Timing suspicious in test_mp_read_radix. No fast multiplication? Cut-off too low?\n"); @@ -1234,7 +1239,6 @@ static int test_mp_read_radix(void) goto LBL_ERR; } } - */ free(buffer); diff --git a/mp_to_radix.c b/mp_to_radix.c index 114902f3..e7509efe 100644 --- a/mp_to_radix.c +++ b/mp_to_radix.c @@ -47,7 +47,9 @@ mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, i if ((err = s_mp_faster_to_radix(&a_bar, str, maxlen, &part_written, radix)) != MP_OKAY) goto LBL_ERR; } else { if (MP_HAS(S_MP_SLOWER_TO_RADIX)) { + char *start = str; if ((err = s_mp_slower_to_radix(&a_bar, &str, &maxlen, &part_written, radix, false)) != MP_OKAY) goto LBL_ERR; + str = start; /* part_written does not count EOS */ part_written++; } diff --git a/s_mp_faster_read_radix.c b/s_mp_faster_read_radix.c index 0843c0da..f35d8947 100644 --- a/s_mp_faster_read_radix.c +++ b/s_mp_faster_read_radix.c @@ -3,7 +3,7 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -/* TODO: It is tunable */ +/* TODO: It is tunable. Or is it? */ #define MP_READ_RADIX_CUTOFF_MULTIPLICATOR 3 /* for(n=2,64,t = ceil(log(2^100)/log(n)); printf(t", "); ) */ @@ -41,8 +41,8 @@ mp_err s_mp_faster_read_radix(mp_int *a, const char *str, size_t start, size_t e return err; } - if ((err = s_mp_slower_read_radix(&A, str, start, start + mid + 1, radix)) != MP_OKAY) goto LTM_ERR; - if ((err = s_mp_slower_read_radix(&B, str, start + mid +1, end, radix)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_faster_read_radix(&A, str, start, start + mid + 1, radix)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_faster_read_radix(&B, str, start + mid +1, end, radix)) != MP_OKAY) goto LTM_ERR; if (MP_IS_2EXPT(radix_)) { if ((err = mp_mul_2d(&A, (int)(((len - mid) - 1u) * s_mp_floor_ilog2(radix_)), &A)) != MP_OKAY) goto LTM_ERR; diff --git a/s_mp_slower_to_radix.c b/s_mp_slower_to_radix.c index 6dacb13a..0dffb2b7 100644 --- a/s_mp_slower_to_radix.c +++ b/s_mp_slower_to_radix.c @@ -20,29 +20,30 @@ mp_err s_mp_slower_to_radix(const mp_int *a, char **str, mp_int t; mp_digit d; mp_err err = MP_OKAY; - - /* The number of digits of "radix" to be filled if this chunk is not the most significant one. */ - int ybar = s_mp_radix_exponent_y[radix] * MP_RADIX_BARRETT_START_MULTIPLICATOR; + int ybar = 0; /* A temporary pointer to the output string to make reversal simpler */ char *s = *str; - /* TODO: input a is already a copy of the original and we could use it destructively? */ + /* The number of digits of "radix" to be filled if this chunk is not the most significant one. */ + if (pad) { + ybar = s_mp_radix_exponent_y[radix] * MP_RADIX_BARRETT_START_MULTIPLICATOR; + } + if ((err = mp_init_copy(&t, a)) != MP_OKAY) goto LTM_ERR; while (!mp_iszero(&t)) { - /* TODO: this method to decrease "maxlen" is not threadsafe! */ if ((--(*part_maxlen)) < 1u) { /* no more room */ err = MP_BUF; goto LTM_ERR; } - if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { - goto LTM_ERR; - } + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) goto LTM_ERR; *s++ = s_mp_radix_map[d]; ++digs; - ybar--; + if (pad) { + ybar--; + } } /* Fill in leading zeros if this chunk does not contain the most significant digits. */ @@ -53,7 +54,6 @@ mp_err s_mp_slower_to_radix(const mp_int *a, char **str, } } - /* TODO: I think that can be done more elegantly */ /* "rewind" */ s = *str; /* reverse */ @@ -63,7 +63,6 @@ mp_err s_mp_slower_to_radix(const mp_int *a, char **str, /* Add EOS at the end of every chunk to allow this function to be used stand-alone */ **str = '\0'; - /* TODO: this method to increase "written" is not threadsafe! */ if (part_written != NULL) { *part_written = *part_written + digs; }