Skip to content

Commit 131177c

Browse files
committed
Implement faster base conversion
1 parent 5809141 commit 131177c

19 files changed

+915
-144
lines changed

demo/test.c

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,30 +1157,27 @@ static int test_mp_montgomery_reduce(void)
11571157

11581158
}
11591159

1160+
#include <time.h>
11601161
static int test_mp_read_radix(void)
11611162
{
11621163
char buf[4096];
1163-
size_t written;
1164+
size_t written, maxlen;
11641165

1165-
mp_int a;
1166-
DOR(mp_init_multi(&a, NULL));
1166+
int bignum, i, j, k;
1167+
char *buffer, *bcpy, *startb;
1168+
clock_t start, stop, t_slow, t_fast;
1169+
double slow = 0.0, fast = 0.0, sum_slow = 0.0, sum_fast = 0.0;
1170+
double s_bases_slow[65] = {0.0};
1171+
double s_bases_fast[65] = {0.0};
1172+
1173+
mp_int a, b, c;
1174+
DOR(mp_init_multi(&a, &b, &c, NULL));
11671175

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

11701178
DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10));
11711179
printf(" '123456' a == %s, length = %zu", buf, written);
11721180

1173-
/* See comment in mp_to_radix.c */
1174-
/*
1175-
if( (err = mp_to_radix(&a, buf, 3u, &written, 10) ) != MP_OKAY) goto LBL_ERR;
1176-
printf(" '56' a == %s, length = %zu\n", buf, written);
1177-
1178-
if( (err = mp_to_radix(&a, buf, 4u, &written, 10) ) != MP_OKAY) goto LBL_ERR;
1179-
printf(" '456' a == %s, length = %zu\n", buf, written);
1180-
if( (err = mp_to_radix(&a, buf, 30u, &written, 10) ) != MP_OKAY) goto LBL_ERR;
1181-
printf(" '123456' a == %s, length = %zu, error = %s\n",
1182-
buf, written, mp_error_to_string(err));
1183-
*/
11841181
DO(mp_read_radix(&a, "-123456", 10));
11851182
DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10));
11861183
printf("\r '-123456' a == %s, length = %zu", buf, written);
@@ -1198,10 +1195,71 @@ static int test_mp_read_radix(void)
11981195
printf("%s, %lu\n", buf, (unsigned long)a.dp[0] & 3uL);
11991196
}
12001197

1201-
mp_clear(&a);
1198+
/* Test the fast method with a slightly larger number (about a minute on an older machine) */
1199+
for (k = 100; k < 6000; k += 1000) {
1200+
bignum = k;
1201+
buffer = (char *)malloc((size_t)(bignum + 2));
1202+
if (buffer == NULL) {
1203+
goto LBL_ERR;
1204+
}
1205+
DO(mp_rand(&a, bignum / MP_DIGIT_BIT));
1206+
/*fprintf(stderr,"\nNumber of limbs in &b = %d, bit_count of &b = %d\n", bignum / MP_DIGIT_BIT, mp_count_bits(&a));*/
1207+
for (i = 2; i < 65; i++) {
1208+
start = clock();
1209+
for (j = 0; j < 100; j++) {
1210+
DO(mp_to_radix(&a, buffer, (size_t)(bignum + 1), &written, i));
1211+
mp_zero(&b);
1212+
DO(mp_read_radix(&b, buffer, i));
1213+
/* Check roundabout */
1214+
EXPECT(mp_cmp(&a, &b) == MP_EQ);
1215+
}
1216+
stop = clock();
1217+
t_fast = stop - start;
1218+
1219+
start = clock();
1220+
for (j = 0; j < 100; j++) {
1221+
maxlen = (size_t)(bignum + 1);
1222+
bcpy = buffer;
1223+
/* s_mp_slower_to_radix is very rudimentary and needs some help to work as a stand-alone */
1224+
startb = bcpy;
1225+
DO(s_mp_slower_to_radix(&a, &bcpy, &maxlen, &written, i, false));
1226+
bcpy = startb;
1227+
mp_zero(&c);
1228+
DO(s_mp_slower_read_radix(&c, bcpy, 0, strlen(bcpy), i));
1229+
/* Check roundabout */
1230+
EXPECT(mp_cmp(&a, &c) == MP_EQ);
1231+
/* Check against result of fast algorithms above */
1232+
EXPECT(mp_cmp(&b, &c) == MP_EQ);
1233+
}
1234+
stop = clock();
1235+
t_slow = stop - start;
1236+
1237+
slow = (double)t_slow/(double)CLOCKS_PER_SEC;
1238+
fast = (double)t_fast/(double)CLOCKS_PER_SEC;
1239+
1240+
fprintf(stderr,"Bits %d Base %d SLOW: %.10f, FAST: %.10f\n", mp_count_bits(&a), i, slow, fast);
1241+
1242+
sum_slow += slow;
1243+
sum_fast += fast;
1244+
s_bases_slow[i] += slow;
1245+
s_bases_fast[i] += fast;
1246+
}
1247+
free(buffer);
1248+
}
1249+
1250+
fprintf(stderr,"\nSUM: SLOW: %.10f, FAST: %.10f\n",sum_slow, sum_fast);
1251+
1252+
for (i = 2; i < 65; i++) {
1253+
fprintf(stderr,"Sums for Base %d SLOW: %.10f, FAST: %.10f\n",i, s_bases_slow[i], s_bases_fast[i]);
1254+
}
1255+
1256+
/* Very basic check if the fast algorithms are actually faster. */
1257+
EXPECT(sum_slow > sum_fast);
1258+
1259+
mp_clear_multi(&a, &b, &c, NULL);
12021260
return EXIT_SUCCESS;
12031261
LBL_ERR:
1204-
mp_clear(&a);
1262+
mp_clear_multi(&a, &b, &c, NULL);
12051263
return EXIT_FAILURE;
12061264
}
12071265

@@ -2600,13 +2658,16 @@ static int unit_tests(int argc, char **argv)
26002658
T3(s_mp_div_recursive, ONLY_PUBLIC_API, S_MP_DIV_RECURSIVE, S_MP_DIV_SCHOOL),
26012659
T3(s_mp_div_small, ONLY_PUBLIC_API, S_MP_DIV_SMALL, S_MP_DIV_SCHOOL),
26022660
T2(s_mp_sqr, ONLY_PUBLIC_API, S_MP_SQR),
2661+
26032662
/* s_mp_mul_comba not (yet) testable because s_mp_mul branches to s_mp_mul_comba automatically */
2663+
26042664
T2(s_mp_sqr_comba, ONLY_PUBLIC_API, S_MP_SQR_COMBA),
26052665
T2(s_mp_mul_balance, ONLY_PUBLIC_API, S_MP_MUL_BALANCE),
26062666
T2(s_mp_mul_karatsuba, ONLY_PUBLIC_API, S_MP_MUL_KARATSUBA),
26072667
T2(s_mp_sqr_karatsuba, ONLY_PUBLIC_API, S_MP_SQR_KARATSUBA),
26082668
T2(s_mp_mul_toom, ONLY_PUBLIC_API, S_MP_MUL_TOOM),
26092669
T2(s_mp_sqr_toom, ONLY_PUBLIC_API, S_MP_SQR_TOOM)
2670+
26102671
#undef T3
26112672
#undef T2
26122673
#undef T1

libtommath_VS2008.vcproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,14 @@
836836
RelativePath="s_mp_exptmod_fast.c"
837837
>
838838
</File>
839+
<File
840+
RelativePath="s_mp_faster_read_radix.c"
841+
>
842+
</File>
843+
<File
844+
RelativePath="s_mp_faster_to_radix.c"
845+
>
846+
</File>
839847
<File
840848
RelativePath="s_mp_fp_log.c"
841849
>
@@ -912,6 +920,14 @@
912920
RelativePath="s_mp_rand_platform.c"
913921
>
914922
</File>
923+
<File
924+
RelativePath="s_mp_slower_read_radix.c"
925+
>
926+
</File>
927+
<File
928+
RelativePath="s_mp_slower_to_radix.c"
929+
>
930+
</File>
915931
<File
916932
RelativePath="s_mp_sqr.c"
917933
>

makefile

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
4444
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 \
4545
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 \
4646
mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \
47-
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 \
48-
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 \
49-
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 \
50-
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 \
51-
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 \
52-
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \
53-
s_mp_zero_buf.o s_mp_zero_digs.o
47+
s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o \
48+
s_mp_faster_read_radix.o s_mp_faster_to_radix.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o \
49+
s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
50+
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 \
51+
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
52+
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o \
53+
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_warray.o \
54+
s_mp_warray_get.o s_mp_warray_put.o s_mp_zero_buf.o s_mp_zero_digs.o
5455

5556
#END_INS
5657

makefile.mingw

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
4646
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 \
4747
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 \
4848
mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \
49-
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 \
50-
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 \
51-
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 \
52-
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 \
53-
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 \
54-
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \
55-
s_mp_zero_buf.o s_mp_zero_digs.o
49+
s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o \
50+
s_mp_faster_read_radix.o s_mp_faster_to_radix.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o \
51+
s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
52+
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 \
53+
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
54+
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o \
55+
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_warray.o \
56+
s_mp_warray_get.o s_mp_warray_put.o s_mp_zero_buf.o s_mp_zero_digs.o
5657

5758
HEADERS_PUB=tommath.h
5859
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

makefile.msvc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ mp_reduce_setup.obj mp_root_n.obj mp_rshd.obj mp_sbin_size.obj mp_set.obj mp_set
4242
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 \
4343
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 \
4444
mp_unpack.obj mp_warray_free.obj mp_xor.obj mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj \
45-
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 \
46-
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 \
47-
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 \
48-
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 \
49-
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 \
50-
s_mp_sqr_karatsuba.obj s_mp_sqr_toom.obj s_mp_sub.obj s_mp_warray.obj s_mp_warray_get.obj s_mp_warray_put.obj \
51-
s_mp_zero_buf.obj s_mp_zero_digs.obj
45+
s_mp_div_recursive.obj s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj \
46+
s_mp_faster_read_radix.obj s_mp_faster_to_radix.obj s_mp_fp_log.obj s_mp_fp_log_d.obj s_mp_get_bit.obj \
47+
s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj \
48+
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 \
49+
s_mp_mul_toom.obj s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj \
50+
s_mp_radix_size_overestimate.obj s_mp_rand_platform.obj s_mp_slower_read_radix.obj s_mp_slower_to_radix.obj \
51+
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_warray.obj \
52+
s_mp_warray_get.obj s_mp_warray_put.obj s_mp_zero_buf.obj s_mp_zero_digs.obj
5253

5354
HEADERS_PUB=tommath.h
5455
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

makefile.shared

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
4141
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 \
4242
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 \
4343
mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \
44-
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 \
45-
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 \
46-
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 \
47-
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 \
48-
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 \
49-
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \
50-
s_mp_zero_buf.o s_mp_zero_digs.o
44+
s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o \
45+
s_mp_faster_read_radix.o s_mp_faster_to_radix.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o \
46+
s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
47+
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 \
48+
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
49+
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o \
50+
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_warray.o \
51+
s_mp_warray_get.o s_mp_warray_put.o s_mp_zero_buf.o s_mp_zero_digs.o
5152

5253
#END_INS
5354

makefile.unix

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o
4747
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 \
4848
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 \
4949
mp_unpack.o mp_warray_free.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o \
50-
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 \
51-
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 \
52-
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 \
53-
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 \
54-
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 \
55-
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_warray.o s_mp_warray_get.o s_mp_warray_put.o \
56-
s_mp_zero_buf.o s_mp_zero_digs.o
50+
s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o \
51+
s_mp_faster_read_radix.o s_mp_faster_to_radix.o s_mp_fp_log.o s_mp_fp_log_d.o s_mp_get_bit.o \
52+
s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \
53+
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 \
54+
s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \
55+
s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_slower_read_radix.o s_mp_slower_to_radix.o \
56+
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_warray.o \
57+
s_mp_warray_get.o s_mp_warray_put.o s_mp_zero_buf.o s_mp_zero_digs.o
5758

5859

5960
HEADERS_PUB=tommath.h

mp_fread.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
/* SPDX-License-Identifier: Unlicense */
55

66
#ifndef MP_NO_FILE
7+
8+
/* TODO: It would be some effort involved to connect mp_fwrite (mp_fread) to s_faster_read_radix.
9+
10+
It is rather simple, on the other side, to just read the whole string into
11+
memory and send it to s_faster_read_radix but it would need heap that may or
12+
may not be available. So: check if there is something in the middle (e.g.: read
13+
in chunks (LSD to MSD) and send those strings to s_faster_read_radix).
14+
15+
NOTE: reading from a stream is quite fast already, especially bases of the form 2^n. */
16+
717
/* read a bigint from a file stream in ASCII */
818
mp_err mp_fread(mp_int *a, int radix, FILE *stream)
919
{
1020
mp_err err;
1121
mp_sign sign = MP_ZPOS;
1222
int ch;
23+
mp_digit binary_radix = 0u;
1324

1425
/* make sure the radix is ok */
1526
if ((radix < 2) || (radix > 64)) {
@@ -31,6 +42,10 @@ mp_err mp_fread(mp_int *a, int radix, FILE *stream)
3142
/* clear a */
3243
mp_zero(a);
3344

45+
if (MP_IS_2EXPT(radix)) {
46+
binary_radix = (mp_digit)s_mp_log2_radix[radix];
47+
}
48+
3449
do {
3550
uint8_t y;
3651
unsigned pos;
@@ -47,19 +62,21 @@ mp_err mp_fread(mp_int *a, int radix, FILE *stream)
4762
}
4863

4964
/* shift up and add */
50-
if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
51-
return err;
52-
}
53-
if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
54-
return err;
65+
if (binary_radix != 0u) {
66+
if ((err = mp_mul_2d(a, binary_radix, a)) != MP_OKAY) goto LBL_ERR;
67+
} else {
68+
if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) goto LBL_ERR;
5569
}
70+
if ((err = mp_add_d(a, y, a)) != MP_OKAY) goto LBL_ERR;
71+
5672
} while ((ch = fgetc(stream)) != EOF);
5773

5874
if (!mp_iszero(a)) {
5975
a->sign = sign;
6076
}
6177

62-
return MP_OKAY;
78+
LBL_ERR:
79+
return err;
6380
}
6481
#endif
6582

0 commit comments

Comments
 (0)