@@ -755,34 +755,70 @@ def test_frexp_dtype_consistency(backend):
755
755
assert exponent .shape == shape
756
756
757
757
758
- def test_frexp_finfo_compatibility ():
759
- """Test that frexp works correctly with np.finfo to enable machep/negep calculation ."""
758
+ def test_frexp_basic_functionality ():
759
+ """Test that frexp works correctly for basic cases ."""
760
760
# This is the key test that was failing before implementing frexp
761
761
quad_dtype = QuadPrecDType ()
762
762
763
- # This should work without raising _UFuncNoLoopError
764
- try :
765
- finfo = np .finfo (quad_dtype )
766
-
767
- # Try to access basic properties that should work
768
- assert hasattr (finfo , 'dtype' ), "finfo should have dtype attribute"
763
+ # Test that frexp ufunc is registered and callable
764
+ quad_arr = np .array ([1.0 ], dtype = quad_dtype )
765
+ mantissa , exponent = np .frexp (quad_arr )
766
+
767
+ assert len (mantissa ) == 1 , "frexp should return mantissa array"
768
+ assert len (exponent ) == 1 , "frexp should return exponent array"
769
+ assert mantissa .dtype == quad_dtype , "Mantissa should have quad dtype"
770
+ assert exponent .dtype == np .int32 , "Exponent should have int32 dtype"
771
+
772
+ # Test with epsilon value directly from constants
773
+ from numpy_quaddtype import epsilon
774
+ eps_arr = np .array ([float (epsilon )], dtype = quad_dtype )
775
+ eps_mantissa , eps_exponent = np .frexp (eps_arr )
776
+
777
+ # For binary128 (quad precision), epsilon = 2^-112
778
+ # So frexp(epsilon) should give mantissa=0.5 and exponent=-111
779
+ eps_mantissa_float = float (eps_mantissa [0 ])
780
+ eps_exponent_int = int (eps_exponent [0 ])
781
+
782
+ assert abs (eps_mantissa_float - 0.5 ) < 1e-15 , f"Expected mantissa 0.5 for epsilon, got { eps_mantissa_float } "
783
+ assert eps_exponent_int == - 111 , f"Expected exponent -111 for epsilon, got { eps_exponent_int } "
784
+
785
+
786
+ def test_frexp_with_quad_constants ():
787
+ """Test frexp using the constants exposed by numpy_quaddtype instead of np.finfo."""
788
+ from numpy_quaddtype import epsilon , smallest_normal , max_value , pi , e
789
+
790
+ quad_dtype = QuadPrecDType ()
791
+
792
+ # Test various important constants
793
+ constants_to_test = [
794
+ ("epsilon" , epsilon ),
795
+ ("smallest_normal" , smallest_normal ),
796
+ ("pi" , pi ),
797
+ ("e" , e ),
798
+ ]
799
+
800
+ for name , constant in constants_to_test :
801
+ # Convert constant to quad array
802
+ const_arr = np .array ([float (constant )], dtype = quad_dtype )
803
+ mantissa , exponent = np .frexp (const_arr )
769
804
770
- # For custom dtypes, some properties may not be available
771
- # The key test is that frexp ufunc is registered and callable
772
- quad_arr = np .array ([1.0 ], dtype = quad_dtype )
773
- mantissa , exponent = np .frexp (quad_arr )
805
+ # Basic checks
806
+ assert mantissa .dtype == quad_dtype , f"Mantissa dtype should be quad for { name } "
807
+ assert exponent .dtype == np .int32 , f"Exponent dtype should be int32 for { name } "
774
808
775
- assert len (mantissa ) == 1 , "frexp should return mantissa array"
776
- assert len (exponent ) == 1 , "frexp should return exponent array"
809
+ # Reconstruction check (if value is in reasonable range)
810
+ mantissa_float = float (mantissa [0 ])
811
+ exponent_int = int (exponent [0 ])
777
812
778
- except AttributeError as e :
779
- # Some finfo properties may not be available for custom dtypes
780
- # The important thing is that frexp works
781
- quad_arr = np .array ([ 1.0 ], dtype = quad_dtype )
782
- mantissa , exponent = np . frexp ( quad_arr )
813
+ if abs ( exponent_int ) < 1000 : # Avoid overflow in Python arithmetic
814
+ reconstructed = mantissa_float * ( 2.0 ** exponent_int )
815
+ original_float = float ( constant )
816
+ np .testing . assert_allclose ( reconstructed , original_float , rtol = 1e-14 ,
817
+ err_msg = f"Reconstruction failed for { name } " )
783
818
784
- assert len (mantissa ) == 1 , "frexp should return mantissa array"
785
- assert len (exponent ) == 1 , "frexp should return exponent array"
819
+ # Check mantissa range for non-zero values
820
+ if mantissa_float != 0.0 :
821
+ assert 0.5 <= abs (mantissa_float ) < 1.0 , f"Mantissa { mantissa_float } not in [0.5, 1) for { name } "
786
822
787
823
788
824
@pytest .mark .parametrize ("backend" , ["sleef" , "longdouble" ])
0 commit comments