4
4
#define S_MP_RAND_JENKINS_C
5
5
#include "s_mp_rand_jenkins.c"
6
6
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
+
7
20
static long rand_long (void )
8
21
{
9
22
long x ;
@@ -1157,30 +1170,27 @@ static int test_mp_montgomery_reduce(void)
1157
1170
1158
1171
}
1159
1172
1173
+ #include <time.h>
1160
1174
static int test_mp_read_radix (void )
1161
1175
{
1162
1176
char buf [4096 ];
1163
- size_t written ;
1177
+ size_t written , maxlen ;
1164
1178
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 ));
1167
1188
1168
1189
DO (mp_read_radix (& a , "123456" , 10 ));
1169
1190
1170
1191
DO (mp_to_radix (& a , buf , sizeof (buf ), & written , 10 ));
1171
1192
printf (" '123456' a == %s, length = %zu" , buf , written );
1172
1193
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
- */
1184
1194
DO (mp_read_radix (& a , "-123456" , 10 ));
1185
1195
DO (mp_to_radix (& a , buf , sizeof (buf ), & written , 10 ));
1186
1196
printf ("\r '-123456' a == %s, length = %zu" , buf , written );
@@ -1198,10 +1208,81 @@ static int test_mp_read_radix(void)
1198
1208
printf ("%s, %lu\n" , buf , (unsigned long )a .dp [0 ] & 3uL );
1199
1209
}
1200
1210
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 );
1202
1283
return EXIT_SUCCESS ;
1203
1284
LBL_ERR :
1204
- mp_clear (& a );
1285
+ mp_clear_multi (& a , & b , & c , NULL );
1205
1286
return EXIT_FAILURE ;
1206
1287
}
1207
1288
@@ -2583,7 +2664,7 @@ static int unit_tests(int argc, char **argv)
2583
2664
T1 (mp_prime_next_prime , MP_PRIME_NEXT_PRIME ),
2584
2665
T1 (mp_prime_rand , MP_PRIME_RAND ),
2585
2666
T1 (mp_rand , MP_RAND ),
2586
- T1 (mp_read_radix , MP_READ_RADIX ),
2667
+ T2 (mp_read_radix , ONLY_PUBLIC_API , MP_READ_RADIX ),
2587
2668
T1 (mp_read_write_ubin , MP_TO_UBIN ),
2588
2669
T1 (mp_read_write_sbin , MP_TO_SBIN ),
2589
2670
T1 (mp_reduce_2k , MP_REDUCE_2K ),
@@ -2600,13 +2681,16 @@ static int unit_tests(int argc, char **argv)
2600
2681
T3 (s_mp_div_recursive , ONLY_PUBLIC_API , S_MP_DIV_RECURSIVE , S_MP_DIV_SCHOOL ),
2601
2682
T3 (s_mp_div_small , ONLY_PUBLIC_API , S_MP_DIV_SMALL , S_MP_DIV_SCHOOL ),
2602
2683
T2 (s_mp_sqr , ONLY_PUBLIC_API , S_MP_SQR ),
2684
+
2603
2685
/* s_mp_mul_comba not (yet) testable because s_mp_mul branches to s_mp_mul_comba automatically */
2686
+
2604
2687
T2 (s_mp_sqr_comba , ONLY_PUBLIC_API , S_MP_SQR_COMBA ),
2605
2688
T2 (s_mp_mul_balance , ONLY_PUBLIC_API , S_MP_MUL_BALANCE ),
2606
2689
T2 (s_mp_mul_karatsuba , ONLY_PUBLIC_API , S_MP_MUL_KARATSUBA ),
2607
2690
T2 (s_mp_sqr_karatsuba , ONLY_PUBLIC_API , S_MP_SQR_KARATSUBA ),
2608
2691
T2 (s_mp_mul_toom , ONLY_PUBLIC_API , S_MP_MUL_TOOM ),
2609
2692
T2 (s_mp_sqr_toom , ONLY_PUBLIC_API , S_MP_SQR_TOOM )
2693
+
2610
2694
#undef T3
2611
2695
#undef T2
2612
2696
#undef T1
0 commit comments