@@ -1395,8 +1395,7 @@ static int test_mp_reduce_2k_l(void)
1395
1395
return EXIT_SUCCESS ;
1396
1396
# endif /* LTM_DEMO_TEST_REDUCE_2K_L */
1397
1397
}
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 */
1400
1399
static mp_err s_rs (const mp_int * a , int radix , int * size )
1401
1400
{
1402
1401
mp_err res ;
@@ -1425,13 +1424,21 @@ static mp_err s_rs(const mp_int *a, int radix, int *size)
1425
1424
* size = digs + 1 ;
1426
1425
return MP_OKAY ;
1427
1426
}
1427
+
1428
+
1428
1429
static int test_mp_log_n (void )
1429
1430
{
1430
1431
mp_int a ;
1431
1432
mp_digit d ;
1432
- int base , lb , size ;
1433
+ int base , lb , size , i ;
1433
1434
const int max_base = MP_MIN (INT_MAX , MP_DIGIT_MAX );
1434
1435
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
+
1435
1442
DOR (mp_init (& a ));
1436
1443
1437
1444
/*
@@ -1484,25 +1491,32 @@ static int test_mp_log_n(void)
1484
1491
DO (mp_rand (& a , 10 ));
1485
1492
for (base = 2 ; base < 65 ; base ++ ) {
1486
1493
DO (mp_log_n (& a , base , & lb ));
1487
- DO (s_rs (& a ,( int ) base , & size ));
1494
+ DO (s_rs (& a ,base , & size ));
1488
1495
/* radix_size includes the memory needed for '\0', too*/
1489
1496
size -= 2 ;
1490
1497
EXPECT (lb == size );
1491
1498
}
1492
1499
1493
1500
/*
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)
1496
1505
*/
1497
- DO (mp_rand (& a , 1 ));
1498
1506
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
+ }
1503
1517
}
1504
1518
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 */
1506
1520
mp_set (& a , max_base );
1507
1521
DO (mp_expt_n (& a , 10uL , & a ));
1508
1522
DO (mp_add_d (& a , max_base / 2 , & a ));
@@ -1516,6 +1530,76 @@ static int test_mp_log_n(void)
1516
1530
return EXIT_FAILURE ;
1517
1531
}
1518
1532
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
+
1519
1603
static int test_mp_incr (void )
1520
1604
{
1521
1605
mp_int a , b ;
@@ -2373,6 +2457,7 @@ static int unit_tests(int argc, char **argv)
2373
2457
T1 (mp_get_u64 , MP_GET_I64 ),
2374
2458
T1 (mp_get_ul , MP_GET_L ),
2375
2459
T1 (mp_log_n , MP_LOG_N ),
2460
+ T1 (mp_log , MP_LOG ),
2376
2461
T1 (mp_incr , MP_ADD_D ),
2377
2462
T1 (mp_invmod , MP_INVMOD ),
2378
2463
T1 (mp_is_square , MP_IS_SQUARE ),
0 commit comments