Skip to content

Faster radix conversion #499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 90 additions & 6 deletions demo/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,13 +1151,19 @@ static int test_mp_montgomery_reduce(void)

}

#include <time.h>
static int test_mp_read_radix(void)
{
char buf[4096];
size_t written;
size_t written, maxlen;
int bignum, i;

mp_int a;
DOR(mp_init_multi(&a, NULL));
char *buffer, *bcpy, *startb;

clock_t start, stop, t_slow, t_fast;

mp_int a, b;
DOR(mp_init_multi(&a, &b, NULL));

DO(mp_read_radix(&a, "123456", 10));

Expand All @@ -1183,6 +1189,84 @@ static int test_mp_read_radix(void)
DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10));
printf("\r '0' a == %s, length = %zu", buf, written);

/* Test the fast method with a slightly larger number */

/* 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));
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);
}
stop = clock();
t_fast = stop - start;

printf("Same number, slow radix conversions\n");
start = clock();
for (i = 2; i < 65; i++) {
/* 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);
}
stop = clock();
t_slow = stop - start;

/* It is "long int" in GLibC but can be bigger and/or even a floating point elsewhere */
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. */
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");
DO(mp_fwrite(&a, 16, stderr));
goto LBL_ERR;
}
}

free(buffer);

#if ((MP_DIGIT_BIT <= 16) && (defined MP_CHECK_RADIX_OVF))
/* Check a number of size (MP_MAX_DIGIT_COUNT * MP_DIGIT_BIT - 1) at fixed radix "10". */
/* Will not work if test is run on platforms with larger int's because
#define MP_MAX_DIGIT_COUNT ((INT_MAX - 2) / MP_DIGIT_BIT)
So we have to replace the value for INT_MAX with 2^15 - 1 = 32767 to test 16-bit int's. Not
very elegant but it works.
*/
bignum = ((32767 - 2) / MP_DIGIT_BIT);
bignum = ((bignum - 1) * MP_DIGIT_BIT) + (MP_DIGIT_BIT - 1);
/* Manual computation because the automatic methods might not have been included in the build */
buffer = (char *)malloc(((bignum + 2)/1000) * 333);
if (buffer == NULL) {
goto LBL_ERR;
}
DO(mp_2expt(&a, bignum));
DO(mp_decr(&a));
printf("Number of limbs in &b = %d, bit_count of &b = %d\n", bignum / MP_DIGIT_BIT, mp_count_bits(&a));
DO(mp_to_radix(&a, buffer, ((bignum + 2)/1000) * 333, &written, 10));
DO(mp_read_radix(&b, buffer, 10));
EXPECT(mp_cmp(&a, &b) == MP_EQ);
free(buffer);
#endif



while (0) {
char *s = fgets(buf, sizeof(buf), stdin);
if (s != buf) break;
Expand All @@ -1192,10 +1276,10 @@ static int test_mp_read_radix(void)
printf("%s, %lu\n", buf, (unsigned long)a.dp[0] & 3uL);
}

mp_clear(&a);
mp_clear_multi(&a, &b, NULL);
return EXIT_SUCCESS;
LBL_ERR:
mp_clear(&a);
mp_clear_multi(&a, &b, NULL);
return EXIT_FAILURE;
}

Expand Down Expand Up @@ -2479,7 +2563,7 @@ static int unit_tests(int argc, char **argv)
T1(mp_prime_next_prime, MP_PRIME_NEXT_PRIME),
T1(mp_prime_rand, MP_PRIME_RAND),
T1(mp_rand, MP_RAND),
T1(mp_read_radix, MP_READ_RADIX),
T3(mp_read_radix, ONLY_PUBLIC_API, MP_READ_RADIX, MP_TO_RADIX),
T1(mp_read_write_ubin, MP_TO_UBIN),
T1(mp_read_write_sbin, MP_TO_SBIN),
T1(mp_reduce_2k, MP_REDUCE_2K),
Expand Down
20 changes: 20 additions & 0 deletions libtommath_VS2008.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,18 @@
RelativePath="s_mp_exptmod_fast.c"
>
</File>
<File
RelativePath="s_mp_faster_read_radix.c"
>
</File>
<File
RelativePath="s_mp_faster_to_radix.c"
>
</File>
<File
RelativePath="s_mp_floor_ilog2.c"
>
</File>
<File
RelativePath="s_mp_fp_log.c"
>
Expand Down Expand Up @@ -908,6 +920,14 @@
RelativePath="s_mp_rand_platform.c"
>
</File>
<File
RelativePath="s_mp_slower_read_radix.c"
>
</File>
<File
RelativePath="s_mp_slower_to_radix.c"
>
</File>
<File
RelativePath="s_mp_sqr.c"
>
Expand Down
13 changes: 7 additions & 6 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \
mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \
mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \
s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \
s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_faster_read_radix.o \
s_mp_faster_to_radix.o s_mp_floor_ilog2.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o \
s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o

#END_INS

Expand Down
13 changes: 7 additions & 6 deletions makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \
mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \
mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \
s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \
s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_faster_read_radix.o \
s_mp_faster_to_radix.o s_mp_floor_ilog2.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o \
s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)
Expand Down
13 changes: 7 additions & 6 deletions makefile.msvc
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ mp_reduce_setup.obj mp_root_n.obj mp_rshd.obj mp_sbin_size.obj mp_set.obj mp_set
mp_set_l.obj mp_set_u32.obj mp_set_u64.obj mp_set_ul.obj mp_shrink.obj mp_signed_rsh.obj mp_sqrmod.obj mp_sqrt.obj \
mp_sqrtmod_prime.obj mp_sub.obj mp_sub_d.obj mp_submod.obj mp_to_radix.obj mp_to_sbin.obj mp_to_ubin.obj mp_ubin_size.obj \
mp_unpack.obj mp_xor.obj mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj s_mp_div_recursive.obj \
s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_fp_log.obj s_mp_fp_log_d.obj \
s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj \
s_mp_mul_balance.obj s_mp_mul_comba.obj s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj \
s_mp_mul_toom.obj s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj \
s_mp_radix_size_overestimate.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj s_mp_sqr_karatsuba.obj \
s_mp_sqr_toom.obj s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj
s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_faster_read_radix.obj \
s_mp_faster_to_radix.obj s_mp_floor_ilog2.obj s_mp_fp_log.obj s_mp_fp_log_d.obj s_mp_get_bit.obj s_mp_invmod.obj \
s_mp_invmod_odd.obj s_mp_log_2expt.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj s_mp_mul_balance.obj \
s_mp_mul_comba.obj s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj s_mp_mul_toom.obj \
s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj s_mp_radix_size_overestimate.obj \
s_mp_rand_platform.obj s_mp_slower_read_radix.obj s_mp_slower_to_radix.obj s_mp_sqr.obj s_mp_sqr_comba.obj \
s_mp_sqr_karatsuba.obj s_mp_sqr_toom.obj s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)
Expand Down
13 changes: 7 additions & 6 deletions makefile.shared
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \
mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \
mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \
s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \
s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_faster_read_radix.o \
s_mp_faster_to_radix.o s_mp_floor_ilog2.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o \
s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o

#END_INS

Expand Down
13 changes: 7 additions & 6 deletions makefile.unix
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \
mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \
mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \
s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \
s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_faster_read_radix.o \
s_mp_faster_to_radix.o s_mp_floor_ilog2.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o \
s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o


HEADERS_PUB=tommath.h
Expand Down
12 changes: 1 addition & 11 deletions mp_prime_is_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* portable integer log of two with small footprint */
static unsigned int s_floor_ilog2(int value)
{
unsigned int r = 0;
while ((value >>= 1) != 0) {
r++;
}
return r;
}

mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result)
{
mp_int b;
Expand Down Expand Up @@ -186,7 +176,7 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result)
* Hence the ugly type-fiddling in the following code.
*/
size_a = mp_count_bits(a);
mask = (1u << s_floor_ilog2(size_a)) - 1u;
mask = (1u << s_mp_floor_ilog2((unsigned int)size_a)) - 1u;
/*
Assuming the General Rieman hypothesis (never thought to write that in a
comment) the upper bound can be lowered to 2*(log a)^2.
Expand Down
65 changes: 30 additions & 35 deletions mp_read_radix.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,30 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

#ifdef MP_USE_MEMOPS
# include <string.h>

# define MP_STRLEN(s) strlen(s)
#else
static size_t s_mp_strlen(const char *s)
{
const char *p;
p = s;
while (*p != '\0') {
p++;
}
return (size_t)(p - s);
}
# define MP_STRLEN(s) s_mp_strlen(s)
#endif

/* read a string [ASCII] in a given radix */
mp_err mp_read_radix(mp_int *a, const char *str, int radix)
{

mp_err err;
mp_sign sign = MP_ZPOS;
size_t slen;

/* make sure the radix is ok */
if ((radix < 2) || (radix > 64)) {
Expand All @@ -22,48 +41,24 @@ mp_err mp_read_radix(mp_int *a, const char *str, int radix)
sign = MP_NEG;
}

/* set the integer to the default of zero */
mp_zero(a);
slen = MP_STRLEN(str);

/* process each digit of the string */
while (*str != '\0') {
/* if the radix <= 36 the conversion is case insensitive
* this allows numbers like 1AB and 1ab to represent the same value
* [e.g. in hex]
*/
uint8_t y;
char ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str;
unsigned pos = (unsigned)(ch - '+');
if (MP_RADIX_MAP_REVERSE_SIZE <= pos) {
break;
}
y = s_mp_radix_map_reverse[pos];
mp_zero(a);

/* if the char was found in the map
* and is less than the given radix add it
* to the number, otherwise exit the loop.
*/
if (y >= radix) {
break;
}
if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
return err;
}
if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
return err;
}
++str;
}

/* if an illegal character was found, fail. */
if ((*str != '\0') && (*str != '\r') && (*str != '\n')) {
return MP_VAL;
/* Try faster version first */
if (MP_HAS(S_MP_FASTER_READ_RADIX)) {
if ((err = s_mp_faster_read_radix(a, str, 0, slen, radix)) != MP_OKAY) goto LTM_ERR;
} else if (MP_HAS(S_MP_SLOWER_READ_RADIX)) {
if ((err = s_mp_slower_read_radix(a, str, 0, slen, radix)) != MP_OKAY) goto LTM_ERR;
}

/* set the sign only if a != 0 */
if (!mp_iszero(a)) {
a->sign = sign;
}
return MP_OKAY;

LTM_ERR:
return err;
}

#endif
Loading