@@ -1072,3 +1072,152 @@ def test_fill_function(func, args, expected):
10721072    assert  len (arr ) ==  len (expected )
10731073    for  i , exp_val  in  enumerate (expected ):
10741074        np .testing .assert_allclose (float (arr [i ]), float (exp_val ), rtol = 1e-15 , atol = 1e-15 )
1075+ 
1076+ @pytest .mark .parametrize ("base,exponent" , [ 
1077+     # Basic integer powers  
1078+     (2.0 , 3.0 ), (3.0 , 2.0 ), (10.0 , 5.0 ), (5.0 , 10.0 ), 
1079+      
1080+     # Fractional powers  
1081+     (4.0 , 0.5 ), (9.0 , 0.5 ), (27.0 , 1.0 / 3.0 ), (16.0 , 0.25 ), 
1082+     (8.0 , 2.0 / 3.0 ), (100.0 , 0.5 ), 
1083+      
1084+     # Negative bases with integer exponents  
1085+     (- 2.0 , 3.0 ), (- 3.0 , 2.0 ), (- 2.0 , 4.0 ), (- 5.0 , 3.0 ), 
1086+      
1087+     # Negative bases with fractional exponents (should return NaN)  
1088+     (- 1.0 , 0.5 ), (- 4.0 , 0.5 ), (- 1.0 , 1.5 ), (- 4.0 , 1.5 ), 
1089+     (- 2.0 , 0.25 ), (- 8.0 , 1.0 / 3.0 ), (- 5.0 , 2.5 ), (- 10.0 , 0.75 ), 
1090+     (- 1.0 , - 0.5 ), (- 4.0 , - 1.5 ), (- 2.0 , - 2.5 ), 
1091+      
1092+     # Zero base cases  
1093+     (0.0 , 0.0 ), (0.0 , 1.0 ), (0.0 , 2.0 ), (0.0 , 10.0 ), 
1094+     (0.0 , 0.5 ), (0.0 , - 0.0 ), 
1095+      
1096+     # Negative zero base  
1097+     (- 0.0 , 0.0 ), (- 0.0 , 1.0 ), (- 0.0 , 2.0 ), (- 0.0 , 3.0 ), 
1098+      
1099+     # Base of 1  
1100+     (1.0 , 0.0 ), (1.0 , 1.0 ), (1.0 , 100.0 ), (1.0 , - 100.0 ), 
1101+     (1.0 , float ('inf' )), (1.0 , float ('-inf' )), (1.0 , float ('nan' )), 
1102+      
1103+     # Base of -1  
1104+     (- 1.0 , 0.0 ), (- 1.0 , 1.0 ), (- 1.0 , 2.0 ), (- 1.0 , 3.0 ), 
1105+     (- 1.0 , float ('inf' )), (- 1.0 , float ('-inf' )), 
1106+      
1107+     # Exponent of 0  
1108+     (2.0 , 0.0 ), (100.0 , 0.0 ), (- 5.0 , 0.0 ), (0.5 , 0.0 ), 
1109+     (float ('inf' ), 0.0 ), (float ('-inf' ), 0.0 ), (float ('nan' ), 0.0 ), 
1110+      
1111+     # Exponent of 1  
1112+     (2.0 , 1.0 ), (100.0 , 1.0 ), (- 5.0 , 1.0 ), (0.5 , 1.0 ), 
1113+     (float ('inf' ), 1.0 ), (float ('-inf' ), 1.0 ), 
1114+      
1115+     # Negative exponents  
1116+     (2.0 , - 1.0 ), (2.0 , - 2.0 ), (10.0 , - 3.0 ), (0.5 , - 1.0 ), 
1117+     (4.0 , - 0.5 ), (9.0 , - 0.5 ), 
1118+      
1119+     # Infinity base  
1120+     (float ('inf' ), 0.0 ), (float ('inf' ), 1.0 ), (float ('inf' ), 2.0 ), 
1121+     (float ('inf' ), - 1.0 ), (float ('inf' ), - 2.0 ), (float ('inf' ), 0.5 ), 
1122+     (float ('inf' ), float ('inf' )), (float ('inf' ), float ('-inf' )), 
1123+      
1124+     # Negative infinity base  
1125+     (float ('-inf' ), 0.0 ), (float ('-inf' ), 1.0 ), (float ('-inf' ), 2.0 ), 
1126+     (float ('-inf' ), 3.0 ), (float ('-inf' ), - 1.0 ), (float ('-inf' ), - 2.0 ), 
1127+     (float ('-inf' ), float ('inf' )), (float ('-inf' ), float ('-inf' )), 
1128+      
1129+     # Infinity exponent  
1130+     (2.0 , float ('inf' )), (0.5 , float ('inf' )), (1.5 , float ('inf' )), 
1131+     (2.0 , float ('-inf' )), (0.5 , float ('-inf' )), (1.5 , float ('-inf' )), 
1132+     (0.0 , float ('inf' )), (0.0 , float ('-inf' )), 
1133+      
1134+     # NaN cases  
1135+     (float ('nan' ), 0.0 ), (float ('nan' ), 1.0 ), (float ('nan' ), 2.0 ), 
1136+     (2.0 , float ('nan' )), (0.0 , float ('nan' )), 
1137+     (float ('nan' ), float ('nan' )), (float ('nan' ), float ('inf' )), 
1138+     (float ('inf' ), float ('nan' )), 
1139+      
1140+     # Small and large values  
1141+     (1e-10 , 2.0 ), (1e10 , 2.0 ), (1e-10 , 0.5 ), (1e10 , 0.5 ), 
1142+     (2.0 , 100.0 ), (2.0 , - 100.0 ), (0.5 , 100.0 ), (0.5 , - 100.0 ), 
1143+ ]) 
1144+ def  test_float_power (base , exponent ):
1145+     """ 
1146+     Comprehensive test for float_power ufunc. 
1147+      
1148+     float_power differs from power in that it always promotes to floating point. 
1149+     For floating-point dtypes like QuadPrecDType, it should behave identically to power. 
1150+     """ 
1151+     quad_base  =  QuadPrecision (str (base )) if  not  (np .isnan (base ) or  np .isinf (base )) else  QuadPrecision (base )
1152+     quad_exp  =  QuadPrecision (str (exponent )) if  not  (np .isnan (exponent ) or  np .isinf (exponent )) else  QuadPrecision (exponent )
1153+ 
1154+     float_base  =  np .float64 (base )
1155+     float_exp  =  np .float64 (exponent )
1156+ 
1157+     quad_result  =  np .float_power (quad_base , quad_exp )
1158+     float_result  =  np .float_power (float_base , float_exp )
1159+ 
1160+     # Handle NaN cases 
1161+     if  np .isnan (float_result ):
1162+         assert  np .isnan (float (quad_result )), \
1163+             f"Expected NaN for float_power({ base } { exponent } { float (quad_result )}  
1164+         return 
1165+ 
1166+     # Handle infinity cases 
1167+     if  np .isinf (float_result ):
1168+         assert  np .isinf (float (quad_result )), \
1169+             f"Expected inf for float_power({ base } { exponent } { float (quad_result )}  
1170+         assert  np .sign (float_result ) ==  np .sign (float (quad_result )), \
1171+             f"Infinity sign mismatch for float_power({ base } { exponent }  
1172+         return 
1173+ 
1174+     # For finite results 
1175+     np .testing .assert_allclose (
1176+         float (quad_result ), float_result , 
1177+         rtol = 1e-13 , atol = 1e-15 ,
1178+         err_msg = f"Value mismatch for float_power({ base } { exponent }  
1179+     )
1180+ 
1181+     # Check sign for zero results 
1182+     if  float_result  ==  0.0 :
1183+         assert  np .signbit (float_result ) ==  np .signbit (quad_result ), \
1184+             f"Zero sign mismatch for float_power({ base } { exponent }  
1185+ 
1186+ 
1187+ @pytest .mark .parametrize ("base,exponent" , [ 
1188+     # Test that float_power works with integer inputs (promotes to float)  
1189+     (2 , 3 ), 
1190+     (4 , 2 ), 
1191+     (10 , 5 ), 
1192+     (- 2 , 3 ), 
1193+ ]) 
1194+ def  test_float_power_integer_promotion (base , exponent ):
1195+     """ 
1196+     Test that float_power works with integer inputs and promotes them to QuadPrecDType. 
1197+     This is the key difference from power - float_power always returns float types. 
1198+     """ 
1199+     # Create arrays with integer inputs 
1200+     base_arr  =  np .array ([base ], dtype = QuadPrecDType ())
1201+     exp_arr  =  np .array ([exponent ], dtype = QuadPrecDType ())
1202+ 
1203+     result  =  np .float_power (base_arr , exp_arr )
1204+ 
1205+     # Result should be QuadPrecDType 
1206+     assert  result .dtype .name  ==  "QuadPrecDType128" 
1207+ 
1208+     # Check the value 
1209+     expected  =  float (base ) **  float (exponent )
1210+     np .testing .assert_allclose (float (result [0 ]), expected , rtol = 1e-13 )
1211+ 
1212+ 
1213+ def  test_float_power_array ():
1214+     """Test float_power with arrays""" 
1215+     bases  =  np .array ([2.0 , 4.0 , 9.0 , 16.0 ], dtype = QuadPrecDType ())
1216+     exponents  =  np .array ([3.0 , 0.5 , 2.0 , 0.25 ], dtype = QuadPrecDType ())
1217+ 
1218+     result  =  np .float_power (bases , exponents )
1219+     expected  =  np .array ([8.0 , 2.0 , 81.0 , 2.0 ], dtype = np .float64 )
1220+ 
1221+     assert  result .dtype .name  ==  "QuadPrecDType128" 
1222+     for  i  in  range (len (result )):
1223+         np .testing .assert_allclose (float (result [i ]), expected [i ], rtol = 1e-13 )
0 commit comments