@@ -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 } { 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 } { 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