@@ -2255,4 +2255,177 @@ def test_direction(self):
22552255 assert result > q_x , f"nextafter({ x } , { y } ) should be > { x } , got { result } "
22562256 elif expected_dir == "less" :
22572257 assert result < q_x , f"nextafter({ x } , { y } ) should be < { x } , got { result } "
2258+ class TestSpacing :
2259+ """Test cases for np.spacing function with QuadPrecision dtype"""
2260+
2261+ @pytest .mark .parametrize ("x" , [
2262+ np .nan , - np .nan ,
2263+ np .inf , - np .inf ,
2264+ ])
2265+ def test_special_values_return_nan (self , x ):
2266+ """Test spacing with NaN and infinity inputs returns NaN"""
2267+ q_x = QuadPrecision (x )
2268+ result = np .spacing (q_x )
2269+
2270+ assert isinstance (result , QuadPrecision )
2271+ assert np .isnan (result ), f"spacing({ x } ) should be NaN, got { result } "
2272+
2273+ @pytest .mark .parametrize ("x" , [
2274+ 1.0 , - 1.0 ,
2275+ 10.0 , - 10.0 ,
2276+ 100.0 , - 100.0 ,
2277+ ])
2278+ def test_sign_preservation (self , x ):
2279+ """Test that spacing preserves the sign of the input"""
2280+ q_x = QuadPrecision (x )
2281+ result = np .spacing (q_x )
2282+
2283+ q_zero = QuadPrecision (0 )
2284+ # spacing should have the same sign as x
2285+ if x > 0 :
2286+ assert result > q_zero , f"spacing({ x } ) should be positive, got { result } "
2287+ else :
2288+ assert result < q_zero , f"spacing({ x } ) should be negative, got { result } "
2289+
2290+ # Compare with numpy behavior
2291+ np_result = np .spacing (np .float64 (x ))
2292+ assert np .signbit (result ) == np .signbit (np_result ), \
2293+ f"Sign mismatch for spacing({ x } ): quad signbit={ np .signbit (result )} , numpy signbit={ np .signbit (np_result )} "
2294+
2295+ @pytest .mark .parametrize ("x" , [
2296+ 0.0 ,
2297+ - 0.0 ,
2298+ ])
2299+ def test_zero (self , x ):
2300+ """Test spacing of zero returns smallest_subnormal"""
2301+ q_x = QuadPrecision (x )
2302+ result = np .spacing (q_x )
2303+
2304+ finfo = np .finfo (QuadPrecDType ())
2305+ q_zero = QuadPrecision (0 )
2306+
2307+ # spacing(±0.0) should return smallest_subnormal (positive)
2308+ assert result == finfo .smallest_subnormal , \
2309+ f"spacing({ x } ) should be smallest_subnormal, got { result } "
2310+ assert result > q_zero , f"spacing({ x } ) should be positive, got { result } "
2311+
2312+ @pytest .mark .parametrize ("x" , [
2313+ 1.0 ,
2314+ - 1.0 ,
2315+ ])
2316+ def test_one_and_negative_one (self , x ):
2317+ """Test spacing(±1.0) equals ±machine epsilon"""
2318+ q_x = QuadPrecision (x )
2319+ result = np .spacing (q_x )
2320+
2321+ finfo = np .finfo (QuadPrecDType ())
2322+ q_zero = QuadPrecision (0 )
2323+
2324+ # For binary floating point, spacing(±1.0) = ±eps
2325+ expected = finfo .eps if x > 0 else - finfo .eps
2326+ assert result == expected , \
2327+ f"spacing({ x } ) should equal { expected } , got { result } "
2328+
2329+ if x > 0 :
2330+ assert result > q_zero , "spacing(1.0) should be positive"
2331+ else :
2332+ assert result < q_zero , "spacing(-1.0) should be negative"
2333+
2334+ @pytest .mark .parametrize ("x" , [
2335+ 1.0 , - 1.0 ,
2336+ 2.0 , - 2.0 ,
2337+ 10.0 , - 10.0 ,
2338+ 100.0 , - 100.0 ,
2339+ 1e10 , - 1e10 ,
2340+ 1e-10 , - 1e-10 ,
2341+ 0.5 , - 0.5 ,
2342+ 0.25 , - 0.25 ,
2343+ ])
2344+ def test_positive_magnitude (self , x ):
2345+ """Test that spacing always has positive magnitude"""
2346+ q_x = QuadPrecision (x )
2347+ result = np .spacing (q_x )
2348+
2349+ q_zero = QuadPrecision (0 )
2350+ # The absolute value should be positive
2351+ abs_result = np .abs (result )
2352+ assert abs_result > q_zero , f"|spacing({ x } )| should be positive, got { abs_result } "
2353+
2354+ def test_smallest_subnormal (self ):
2355+ """Test spacing at smallest subnormal value"""
2356+ finfo = np .finfo (QuadPrecDType ())
2357+ smallest = finfo .smallest_subnormal
2358+
2359+ result = np .spacing (smallest )
2360+
2361+ q_zero = QuadPrecision (0 )
2362+ # spacing(smallest_subnormal) should be smallest_subnormal itself
2363+ # (it's the minimum spacing in the subnormal range)
2364+ assert result == smallest , \
2365+ f"spacing(smallest_subnormal) should be smallest_subnormal, got { result } "
2366+ assert result > q_zero , "Result should be positive"
2367+
2368+ @pytest .mark .parametrize ("x" , [
2369+ 1.5 , - 1.5 ,
2370+ 3.7 , - 3.7 ,
2371+ 42.0 , - 42.0 ,
2372+ 1e8 , - 1e8 ,
2373+ ])
2374+ def test_finite_values (self , x ):
2375+ """Test spacing on various finite values"""
2376+ q_x = QuadPrecision (x )
2377+ result = np .spacing (q_x )
2378+
2379+ q_zero = QuadPrecision (0 )
2380+ # Result should be finite
2381+ assert np .isfinite (result ), \
2382+ f"spacing({ x } ) should be finite, got { result } "
2383+
2384+ # Result should be non-zero
2385+ assert result != q_zero , \
2386+ f"spacing({ x } ) should be non-zero, got { result } "
2387+
2388+ # Result should have same sign as input
2389+ assert np .signbit (result ) == np .signbit (q_x ), \
2390+ f"spacing({ x } ) should have same sign as { x } "
2391+
2392+ def test_array_spacing (self ):
2393+ """Test spacing on an array of QuadPrecision values"""
2394+ values = [1.0 , - 1.0 , 2.0 , - 2.0 , 0.0 , 10.0 , - 10.0 ]
2395+ q_array = np .array ([QuadPrecision (v ) for v in values ])
2396+
2397+ result = np .spacing (q_array )
2398+
2399+ q_zero = QuadPrecision (0 )
2400+ # Check each result
2401+ for i , val in enumerate (values ):
2402+ q_val = QuadPrecision (val )
2403+ if val != 0 :
2404+ assert np .signbit (result [i ]) == np .signbit (q_val ), \
2405+ f"Sign mismatch for spacing({ val } )"
2406+ else :
2407+ assert result [i ] > q_zero , \
2408+ f"spacing(0) should be positive, got { result [i ]} "
2409+
2410+ @pytest .mark .parametrize ("x" , [
2411+ 1e-100 , - 1e-100 ,
2412+ 1e-200 , - 1e-200 ,
2413+ ])
2414+ def test_subnormal_range (self , x ):
2415+ """Test spacing in subnormal range"""
2416+ q_x = QuadPrecision (x )
2417+ result = np .spacing (q_x )
2418+
2419+ finfo = np .finfo (QuadPrecDType ())
2420+
2421+ # In subnormal range, spacing should be smallest_subnormal
2422+ # or at least very small
2423+ assert np .abs (result ) >= finfo .smallest_subnormal , \
2424+ f"spacing({ x } ) should be >= smallest_subnormal"
2425+
2426+ q_zero = QuadPrecision (0 )
2427+ # Sign should match (but for very small subnormals, spacing might underflow to zero)
2428+ if result != q_zero :
2429+ assert np .signbit (result ) == np .signbit (q_x ), \
2430+ f"spacing({ x } ) should have same sign as { x } "
22582431
0 commit comments