diff --git a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp index d60591e8..b8a82aee 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -156,6 +156,11 @@ init_quad_unary_ops(PyObject *numpy) if (create_quad_unary_ufunc(numpy, "absolute") < 0) { return -1; } + // fabs is simialr to absolute, just not handles complex values (we neither) + // registering the absolute here + if (create_quad_unary_ufunc(numpy, "fabs") < 0) { + return -1; + } if (create_quad_unary_ufunc(numpy, "sign") < 0) { return -1; } diff --git a/quaddtype/release_tracker.md b/quaddtype/release_tracker.md index 74c75315..4e3e9068 100644 --- a/quaddtype/release_tracker.md +++ b/quaddtype/release_tracker.md @@ -23,7 +23,7 @@ | fmod | ✅ | ✅ | | divmod | | | | absolute | ✅ | ✅ | -| fabs | | | +| fabs | ✅ | ✅ | | rint | ✅ | ✅ | | sign | ✅ | ✅ | | heaviside | | | diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 3c765b5b..ca500f49 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -1349,4 +1349,42 @@ def test_float_power_array(): assert result.dtype.name == "QuadPrecDType128" for i in range(len(result)): - np.testing.assert_allclose(float(result[i]), expected[i], rtol=1e-13) \ No newline at end of file + np.testing.assert_allclose(float(result[i]), expected[i], rtol=1e-13) + + +@pytest.mark.parametrize("val", [ + # Positive values + "3.0", "12.5", "100.0", "1e100", "0.0", + # Negative values + "-3.0", "-12.5", "-100.0", "-1e100", "-0.0", + # Special values + "inf", "-inf", "nan", "-nan", + # Small values + "1e-100", "-1e-100" +]) +def test_fabs(val): + """ + Test np.fabs ufunc for QuadPrecision dtype. + fabs computes absolute values (positive magnitude) for floating-point numbers. + It should behave identically to np.absolute for real (non-complex) types. + """ + quad_val = QuadPrecision(val) + float_val = float(val) + + quad_result = np.fabs(quad_val) + float_result = np.fabs(float_val) + + # Test with both scalar and array + quad_arr = np.array([quad_val], dtype=QuadPrecDType()) + quad_arr_result = np.fabs(quad_arr) + + # Check scalar result + np.testing.assert_array_equal(np.array(quad_result).astype(float), float_result) + + # Check array result + np.testing.assert_array_equal(quad_arr_result.astype(float)[0], float_result) + + # For zero results, check sign (should always be positive after fabs) + if float_result == 0.0: + assert not np.signbit(quad_result), f"fabs({val}) should not have negative sign" + assert not np.signbit(quad_arr_result[0]), f"fabs({val}) should not have negative sign"