@@ -1395,8 +1395,7 @@ static int test_mp_reduce_2k_l(void)
13951395 return EXIT_SUCCESS ;
13961396# endif /* LTM_DEMO_TEST_REDUCE_2K_L */
13971397}
1398- /* stripped down version of mp_radix_size. The faster version can be off by up t
1399- o +3 */
1398+ /* stripped down version of mp_radix_size. The faster version can be off by up to +3 */
14001399static mp_err s_rs (const mp_int * a , int radix , int * size )
14011400{
14021401 mp_err res ;
@@ -1425,13 +1424,21 @@ static mp_err s_rs(const mp_int *a, int radix, int *size)
14251424 * size = digs + 1 ;
14261425 return MP_OKAY ;
14271426}
1427+
1428+
14281429static int test_mp_log_n (void )
14291430{
14301431 mp_int a ;
14311432 mp_digit d ;
1432- int base , lb , size ;
1433+ int base , lb , size , i ;
14331434 const int max_base = MP_MIN (INT_MAX , MP_DIGIT_MAX );
14341435
1436+ if (MP_HAS (S_MP_WORD_TOO_SMALL )) {
1437+ fprintf (stderr , "Testing mp_log_n with restricted size of mp_word.\n" );
1438+ } else {
1439+ fprintf (stderr , "Testing mp_log_n with normal size of mp_word.\n" );
1440+ }
1441+
14351442 DOR (mp_init (& a ));
14361443
14371444 /*
@@ -1484,25 +1491,32 @@ static int test_mp_log_n(void)
14841491 DO (mp_rand (& a , 10 ));
14851492 for (base = 2 ; base < 65 ; base ++ ) {
14861493 DO (mp_log_n (& a , base , & lb ));
1487- DO (s_rs (& a ,( int ) base , & size ));
1494+ DO (s_rs (& a ,base , & size ));
14881495 /* radix_size includes the memory needed for '\0', too*/
14891496 size -= 2 ;
14901497 EXPECT (lb == size );
14911498 }
14921499
14931500 /*
1494- bases 2..64 with "a" a random small constant to
1495- test the part of mp_ilogb that uses native types.
1501+ bases 2..64 with "a" a small constant and a small exponent "n" to test
1502+ in the range a^n - 10 .. a^n + 10. That will check the correction loops
1503+ and the test for perfect power.
1504+ For simplicity a = base and n = 23 (64^23 == 2^138 > 2^128)
14961505 */
1497- DO (mp_rand (& a , 1 ));
14981506 for (base = 2 ; base < 65 ; base ++ ) {
1499- DO (mp_log_n (& a , base , & lb ));
1500- DO (s_rs (& a ,(int )base , & size ));
1501- size -= 2 ;
1502- EXPECT (lb == size );
1507+ mp_set (& a ,(mp_digit )base );
1508+ DO (mp_expt_n (& a , 23 , & a ));
1509+ DO (mp_sub_d (& a , 10u , & a ));
1510+ for (i = 0 ; i < 20 ; i ++ ) {
1511+ DO (mp_log_n (& a , base , & lb ));
1512+ DO (s_rs (& a , base , & size ));
1513+ size -= 2 ;
1514+ EXPECT (lb == size );
1515+ DO (mp_add_d (& a , 1u , & a ));
1516+ }
15031517 }
15041518
1505- /*Test upper edgecase with base UINT32_MAX and number (UINT32_MAX/2)*UINT32_MAX^10 */
1519+ /*Test base upper edgecase with base = UINT32_MAX and number = (UINT32_MAX/2)*UINT32_MAX^10 */
15061520 mp_set (& a , max_base );
15071521 DO (mp_expt_n (& a , 10uL , & a ));
15081522 DO (mp_add_d (& a , max_base / 2 , & a ));
@@ -1516,6 +1530,76 @@ static int test_mp_log_n(void)
15161530 return EXIT_FAILURE ;
15171531}
15181532
1533+ static int test_mp_log (void )
1534+ {
1535+ mp_int a , base , bn , t ;
1536+ int lb , lb2 , i , j ;
1537+
1538+ if (MP_HAS (S_MP_WORD_TOO_SMALL )) {
1539+ fprintf (stdout , "Testing mp_log with restricted size of mp_word.\n" );
1540+ } else {
1541+ fprintf (stdout , "Testing mp_log with normal size of mp_word.\n" );
1542+ }
1543+
1544+ DOR (mp_init_multi (& a , & base , & bn , & t , NULL ));
1545+
1546+ /*
1547+ The small values got tested above for mp_log_n already, leaving the big stuff
1548+ with bases larger than INT_MAX.
1549+ */
1550+
1551+ /* Edgecases a^b and -1+a^b (floor(log_2(256^129)) = 1032) */
1552+ for (i = 2 ; i < 256 ; i ++ ) {
1553+ mp_set_i32 (& a ,i );
1554+ for (j = 2 ; j < ((i /2 )+ 1 ); j ++ ) {
1555+ DO (mp_expt_n (& a , j , & bn ));
1556+ mp_set_i32 (& base ,j );
1557+ /* i^j a perfect power */
1558+ DO (mp_log (& bn , & a , & lb ));
1559+ DO (mp_expt_n (& a , lb , & t ));
1560+ if (mp_cmp (& t , & bn ) != MP_EQ ) {
1561+ fprintf (stderr ,"FAILURE mp_log for perf. power at i = %d, j = %d\n" , i , j );
1562+ goto LBL_ERR ;
1563+ }
1564+ /* -1 + i^j */
1565+ DO (mp_decr (& bn ));
1566+ DO (mp_log (& bn , & a , & lb2 ));
1567+ if (lb != (lb2 + 1 )) {
1568+ fprintf (stderr ,"FAILURE mp_log for -1 + i^j at i = %d, j = %d\n" , i , j );
1569+ goto LBL_ERR ;
1570+ }
1571+ }
1572+ }
1573+
1574+ /* Random a, base */
1575+ for (i = 1 ; i < 256 ; i ++ ) {
1576+ DO (mp_rand (& a , i ));
1577+ for (j = 1 ; j < ((i /2 )+ 1 ); j ++ ) {
1578+ DO (mp_rand (& base , j ));
1579+ DO (mp_log (& a , & base , & lb ));
1580+ DO (mp_expt_n (& base , lb , & bn ));
1581+ /* "bn" must be smaller than or equal to "a" at this point. */
1582+ if (mp_cmp (& bn , & a ) == MP_GT ) {
1583+ fprintf (stderr ,"FAILURE mp_log random in GT check" );
1584+ goto LBL_ERR ;
1585+ }
1586+ DO (mp_mul (& bn , & base , & bn ));
1587+ /* "bn" must be bigger than "a" at this point. */
1588+ if (mp_cmp (& bn , & a ) != MP_GT ) {
1589+ fprintf (stderr ,"FAILURE mp_log random in NOT GT check" );
1590+ goto LBL_ERR ;
1591+ }
1592+ }
1593+ }
1594+
1595+ mp_clear_multi (& a , & base , & bn , & t , NULL );
1596+ return EXIT_SUCCESS ;
1597+ LBL_ERR :
1598+ mp_clear_multi (& a , & base , & bn , & t , NULL );
1599+ return EXIT_FAILURE ;
1600+ }
1601+
1602+
15191603static int test_mp_incr (void )
15201604{
15211605 mp_int a , b ;
@@ -2373,6 +2457,7 @@ static int unit_tests(int argc, char **argv)
23732457 T1 (mp_get_u64 , MP_GET_I64 ),
23742458 T1 (mp_get_ul , MP_GET_L ),
23752459 T1 (mp_log_n , MP_LOG_N ),
2460+ T1 (mp_log , MP_LOG ),
23762461 T1 (mp_incr , MP_ADD_D ),
23772462 T1 (mp_invmod , MP_INVMOD ),
23782463 T1 (mp_is_square , MP_IS_SQUARE ),
0 commit comments