@@ -1157,30 +1157,27 @@ static int test_mp_montgomery_reduce(void)
11571157
11581158}
11591159
1160+ #include <time.h>
11601161static 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 ;
12031261LBL_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
0 commit comments