44#define S_MP_RAND_JENKINS_C
55#include "s_mp_rand_jenkins.c"
66
7+ /* TODO: Make it an environment variable via main.yml?
8+ This is for testing only, so no reason to add checks to the build process. */
9+ #ifdef __has_include
10+ # if __has_include (< valgrind /valgrind .h > )
11+ # include <valgrind/valgrind.h>
12+ # else
13+ # define RUNNING_ON_VALGRIND 1
14+ # endif
15+ #else
16+ # define RUNNING_ON_VALGRIND 1
17+ #endif
18+
19+
720static long rand_long (void )
821{
922 long x ;
@@ -1157,30 +1170,27 @@ static int test_mp_montgomery_reduce(void)
11571170
11581171}
11591172
1173+ #include <time.h>
11601174static int test_mp_read_radix (void )
11611175{
11621176 char buf [4096 ];
1163- size_t written ;
1177+ size_t written , maxlen ;
11641178
1165- mp_int a ;
1166- DOR (mp_init_multi (& a , NULL ));
1179+ int bignum , i , j , k , limit_test ;
1180+ char * buffer , * bcpy , * startb ;
1181+ clock_t start , stop , t_slow , t_fast ;
1182+ double slow = 0.0 , fast = 0.0 , sum_slow = 0.0 , sum_fast = 0.0 ;
1183+ double s_bases_slow [65 ] = {0.0 };
1184+ double s_bases_fast [65 ] = {0.0 };
1185+
1186+ mp_int a , b , c ;
1187+ DOR (mp_init_multi (& a , & b , & c , NULL ));
11671188
11681189 DO (mp_read_radix (& a , "123456" , 10 ));
11691190
11701191 DO (mp_to_radix (& a , buf , sizeof (buf ), & written , 10 ));
11711192 printf (" '123456' a == %s, length = %zu" , buf , written );
11721193
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- */
11841194 DO (mp_read_radix (& a , "-123456" , 10 ));
11851195 DO (mp_to_radix (& a , buf , sizeof (buf ), & written , 10 ));
11861196 printf ("\r '-123456' a == %s, length = %zu" , buf , written );
@@ -1198,10 +1208,81 @@ static int test_mp_read_radix(void)
11981208 printf ("%s, %lu\n" , buf , (unsigned long )a .dp [0 ] & 3uL );
11991209 }
12001210
1201- mp_clear (& a );
1211+ /* Safe a bit of testing time */
1212+ if (RUNNING_ON_VALGRIND != 0 ) {
1213+ limit_test = 2000 ;
1214+ } else {
1215+ limit_test = 6000 ;
1216+ }
1217+
1218+ /* Test the fast method with a slightly larger number (about a minute on an older machine) */
1219+ for (k = 100 ; k < limit_test ; k += 1000 ) {
1220+ bignum = k ;
1221+ buffer = (char * )malloc ((size_t )(bignum + 2 ));
1222+ if (buffer == NULL ) {
1223+ goto LBL_ERR ;
1224+ }
1225+ DO (mp_rand (& a , bignum / MP_DIGIT_BIT ));
1226+ for (i = 2 ; i < 65 ; i ++ ) {
1227+ start = clock ();
1228+ for (j = 0 ; j < 100 ; j ++ ) {
1229+ DO (mp_to_radix (& a , buffer , (size_t )(bignum + 1 ), & written , i ));
1230+ mp_zero (& b );
1231+ DO (mp_read_radix (& b , buffer , i ));
1232+ /* Check roundabout */
1233+ EXPECT (mp_cmp (& a , & b ) == MP_EQ );
1234+ }
1235+ stop = clock ();
1236+ t_fast = stop - start ;
1237+
1238+ start = clock ();
1239+ for (j = 0 ; j < 100 ; j ++ ) {
1240+ maxlen = (size_t )(bignum + 1 );
1241+ bcpy = buffer ;
1242+ /* s_mp_slower_to_radix is very rudimentary and needs some help to work as a stand-alone */
1243+ startb = bcpy ;
1244+ DO (s_mp_slower_to_radix (& a , & bcpy , & maxlen , & written , i , false));
1245+ bcpy = startb ;
1246+ mp_zero (& c );
1247+ DO (s_mp_slower_read_radix (& c , bcpy , 0 , strlen (bcpy ), i ));
1248+ /* Check roundabout */
1249+ EXPECT (mp_cmp (& a , & c ) == MP_EQ );
1250+ /* Check against result of fast algorithms above */
1251+ EXPECT (mp_cmp (& b , & c ) == MP_EQ );
1252+ }
1253+ stop = clock ();
1254+ t_slow = stop - start ;
1255+
1256+ slow = (double )t_slow /(double )CLOCKS_PER_SEC ;
1257+ fast = (double )t_fast /(double )CLOCKS_PER_SEC ;
1258+
1259+ fprintf (stderr ,"Bits %d Base %d SLOW: %.10f, FAST: %.10f\n" , mp_count_bits (& a ), i , slow , fast );
1260+
1261+ sum_slow += slow ;
1262+ sum_fast += fast ;
1263+ s_bases_slow [i ] += slow ;
1264+ s_bases_fast [i ] += fast ;
1265+ }
1266+ free (buffer );
1267+ }
1268+
1269+ fprintf (stderr ,"\nSUM: SLOW: %.10f, FAST: %.10f\n" ,sum_slow , sum_fast );
1270+
1271+ for (i = 2 ; i < 65 ; i ++ ) {
1272+ fprintf (stderr ,"Sums for Base %d SLOW: %.10f, FAST: %.10f\n" ,i , s_bases_slow [i ], s_bases_fast [i ]);
1273+ }
1274+
1275+ /* Valgrind overhead does not allow for timings. */
1276+ if ((RUNNING_ON_VALGRIND == 0 ) && (MP_DIGIT_BIT >= 20 )) {
1277+ /* Very basic check if the fast algorithms are actually faster. */
1278+ EXPECT (sum_slow > sum_fast );
1279+ }
1280+
1281+
1282+ mp_clear_multi (& a , & b , & c , NULL );
12021283 return EXIT_SUCCESS ;
12031284LBL_ERR :
1204- mp_clear (& a );
1285+ mp_clear_multi (& a , & b , & c , NULL );
12051286 return EXIT_FAILURE ;
12061287}
12071288
@@ -2583,7 +2664,7 @@ static int unit_tests(int argc, char **argv)
25832664 T1 (mp_prime_next_prime , MP_PRIME_NEXT_PRIME ),
25842665 T1 (mp_prime_rand , MP_PRIME_RAND ),
25852666 T1 (mp_rand , MP_RAND ),
2586- T1 (mp_read_radix , MP_READ_RADIX ),
2667+ T2 (mp_read_radix , ONLY_PUBLIC_API , MP_READ_RADIX ),
25872668 T1 (mp_read_write_ubin , MP_TO_UBIN ),
25882669 T1 (mp_read_write_sbin , MP_TO_SBIN ),
25892670 T1 (mp_reduce_2k , MP_REDUCE_2K ),
@@ -2600,13 +2681,16 @@ static int unit_tests(int argc, char **argv)
26002681 T3 (s_mp_div_recursive , ONLY_PUBLIC_API , S_MP_DIV_RECURSIVE , S_MP_DIV_SCHOOL ),
26012682 T3 (s_mp_div_small , ONLY_PUBLIC_API , S_MP_DIV_SMALL , S_MP_DIV_SCHOOL ),
26022683 T2 (s_mp_sqr , ONLY_PUBLIC_API , S_MP_SQR ),
2684+
26032685 /* s_mp_mul_comba not (yet) testable because s_mp_mul branches to s_mp_mul_comba automatically */
2686+
26042687 T2 (s_mp_sqr_comba , ONLY_PUBLIC_API , S_MP_SQR_COMBA ),
26052688 T2 (s_mp_mul_balance , ONLY_PUBLIC_API , S_MP_MUL_BALANCE ),
26062689 T2 (s_mp_mul_karatsuba , ONLY_PUBLIC_API , S_MP_MUL_KARATSUBA ),
26072690 T2 (s_mp_sqr_karatsuba , ONLY_PUBLIC_API , S_MP_SQR_KARATSUBA ),
26082691 T2 (s_mp_mul_toom , ONLY_PUBLIC_API , S_MP_MUL_TOOM ),
26092692 T2 (s_mp_sqr_toom , ONLY_PUBLIC_API , S_MP_SQR_TOOM )
2693+
26102694#undef T3
26112695#undef T2
26122696#undef T1
0 commit comments