@@ -755,34 +755,70 @@ def test_frexp_dtype_consistency(backend):
755755 assert exponent .shape == shape
756756
757757
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 ."""
760760 # This is the key test that was failing before implementing frexp
761761 quad_dtype = QuadPrecDType ()
762762
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 )
769804
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 } "
774808
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 ])
777812
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 } " )
783818
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 } "
786822
787823
788824@pytest .mark .parametrize ("backend" , ["sleef" , "longdouble" ])
0 commit comments