@@ -528,6 +528,113 @@ def test_logaddexp_special_properties():
528528 np .testing .assert_allclose (float (result1 ), float (result2 ), rtol = 1e-14 )
529529
530530
531+ @pytest .mark .parametrize ("x" , [
532+ # Regular values
533+ "0.0" , "1.0" , "2.0" , "-1.0" , "-2.0" , "0.5" , "-0.5" ,
534+ # Large values (test numerical stability)
535+ "100.0" , "1000.0" , "-100.0" , "-1000.0" ,
536+ # Small values
537+ "1e-10" , "-1e-10" , "1e-20" , "-1e-20" ,
538+ # Special values
539+ "inf" , "-inf" , "nan" , "-nan" , "-0.0"
540+ ])
541+ @pytest .mark .parametrize ("y" , [
542+ # Regular values
543+ "0.0" , "1.0" , "2.0" , "-1.0" , "-2.0" , "0.5" , "-0.5" ,
544+ # Large values
545+ "100.0" , "1000.0" , "-100.0" , "-1000.0" ,
546+ # Small values
547+ "1e-10" , "-1e-10" , "1e-20" , "-1e-20" ,
548+ # Special values
549+ "inf" , "-inf" , "nan" , "-nan" , "-0.0"
550+ ])
551+ def test_logaddexp2 (x , y ):
552+ """Comprehensive test for logaddexp2 function: log2(2^x + 2^y)"""
553+ quad_x = QuadPrecision (x )
554+ quad_y = QuadPrecision (y )
555+ float_x = float (x )
556+ float_y = float (y )
557+
558+ quad_result = np .logaddexp2 (quad_x , quad_y )
559+ float_result = np .logaddexp2 (float_x , float_y )
560+
561+ # Handle NaN cases
562+ if np .isnan (float_result ):
563+ assert np .isnan (float (quad_result )), \
564+ f"Expected NaN for logaddexp2({ x } , { y } ), got { float (quad_result )} "
565+ return
566+
567+ # Handle infinity cases
568+ if np .isinf (float_result ):
569+ assert np .isinf (float (quad_result )), \
570+ f"Expected inf for logaddexp2({ x } , { y } ), got { float (quad_result )} "
571+ if not np .isnan (float_result ):
572+ assert np .sign (float_result ) == np .sign (float (quad_result )), \
573+ f"Infinity sign mismatch for logaddexp2({ x } , { y } )"
574+ return
575+
576+ # For finite results, check with appropriate tolerance
577+ # logaddexp2 is numerically sensitive, especially for large differences
578+ if abs (float_x - float_y ) > 50 :
579+ # When values differ greatly, result should be close to max(x, y)
580+ rtol = 1e-10
581+ atol = 1e-10
582+ else :
583+ rtol = 1e-13
584+ atol = 1e-15
585+
586+ np .testing .assert_allclose (
587+ float (quad_result ), float_result ,
588+ rtol = rtol , atol = atol ,
589+ err_msg = f"Value mismatch for logaddexp2({ x } , { y } )"
590+ )
591+
592+
593+ def test_logaddexp2_special_properties ():
594+ """Test special mathematical properties of logaddexp2"""
595+ # logaddexp2(x, x) = x + 1 (since log2(2^x + 2^x) = log2(2 * 2^x) = log2(2) + log2(2^x) = 1 + x)
596+ x = QuadPrecision ("2.0" )
597+ result = np .logaddexp2 (x , x )
598+ expected = float (x ) + 1.0
599+ np .testing .assert_allclose (float (result ), expected , rtol = 1e-14 )
600+
601+ # logaddexp2(x, -inf) = x
602+ x = QuadPrecision ("5.0" )
603+ result = np .logaddexp2 (x , QuadPrecision ("-inf" ))
604+ np .testing .assert_allclose (float (result ), float (x ), rtol = 1e-14 )
605+
606+ # logaddexp2(-inf, x) = x
607+ result = np .logaddexp2 (QuadPrecision ("-inf" ), x )
608+ np .testing .assert_allclose (float (result ), float (x ), rtol = 1e-14 )
609+
610+ # logaddexp2(-inf, -inf) = -inf
611+ result = np .logaddexp2 (QuadPrecision ("-inf" ), QuadPrecision ("-inf" ))
612+ assert np .isinf (float (result )) and float (result ) < 0
613+
614+ # logaddexp2(inf, anything) = inf
615+ result = np .logaddexp2 (QuadPrecision ("inf" ), QuadPrecision ("100.0" ))
616+ assert np .isinf (float (result )) and float (result ) > 0
617+
618+ # logaddexp2(anything, inf) = inf
619+ result = np .logaddexp2 (QuadPrecision ("100.0" ), QuadPrecision ("inf" ))
620+ assert np .isinf (float (result )) and float (result ) > 0
621+
622+ # Commutativity: logaddexp2(x, y) = logaddexp2(y, x)
623+ x = QuadPrecision ("3.0" )
624+ y = QuadPrecision ("5.0" )
625+ result1 = np .logaddexp2 (x , y )
626+ result2 = np .logaddexp2 (y , x )
627+ np .testing .assert_allclose (float (result1 ), float (result2 ), rtol = 1e-14 )
628+
629+ # Relationship with logaddexp: logaddexp2(x, y) = logaddexp(x*ln2, y*ln2) / ln2
630+ x = QuadPrecision ("2.0" )
631+ y = QuadPrecision ("3.0" )
632+ result_logaddexp2 = np .logaddexp2 (x , y )
633+ ln2 = np .log (2.0 )
634+ result_logaddexp = np .logaddexp (float (x ) * ln2 , float (y ) * ln2 ) / ln2
635+ np .testing .assert_allclose (float (result_logaddexp2 ), result_logaddexp , rtol = 1e-13 )
636+
637+
531638def test_inf ():
532639 assert QuadPrecision ("inf" ) > QuadPrecision ("1e1000" )
533640 assert np .signbit (QuadPrecision ("inf" )) == 0
0 commit comments