From 238ce3530efc1498fdb2172c71688a3d8af645fa Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Fri, 17 Oct 2025 13:31:50 +0530 Subject: [PATCH 1/3] fabs impl --- quaddtype/numpy_quaddtype/src/ops.hpp | 12 +++++ .../numpy_quaddtype/src/umath/unary_ops.cpp | 3 ++ quaddtype/release_tracker.md | 2 +- quaddtype/tests/test_quaddtype.py | 47 ++++++++++++++++++- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/ops.hpp b/quaddtype/numpy_quaddtype/src/ops.hpp index 08973f8a..10aeec56 100644 --- a/quaddtype/numpy_quaddtype/src/ops.hpp +++ b/quaddtype/numpy_quaddtype/src/ops.hpp @@ -37,6 +37,12 @@ quad_absolute(const Sleef_quad *op) return Sleef_fabsq1(*op); } +static inline Sleef_quad +quad_fabs(const Sleef_quad *op) +{ + return Sleef_fabsq1(*op); +} + static inline Sleef_quad quad_rint(const Sleef_quad *op) { @@ -217,6 +223,12 @@ ld_absolute(const long double *op) return fabsl(*op); } +static inline long double +ld_fabs(const long double *op) +{ + return fabsl(*op); +} + static inline long double ld_sign(const long double *op) { diff --git a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp index d60591e8..52520f71 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -156,6 +156,9 @@ init_quad_unary_ops(PyObject *numpy) if (create_quad_unary_ufunc(numpy, "absolute") < 0) { return -1; } + 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..408a0142 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -1349,4 +1349,49 @@ 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" + + # Verify that fabs and absolute give the same result for QuadPrecision + quad_absolute_result = np.absolute(quad_val) + np.testing.assert_array_equal( + np.array(quad_result).astype(float), + np.array(quad_absolute_result).astype(float) + ) From 1cf98b844a84d9752259d92a046c7de49dc36a97 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Fri, 17 Oct 2025 13:35:52 +0530 Subject: [PATCH 2/3] use absolute in fabs --- quaddtype/numpy_quaddtype/src/ops.hpp | 12 ------------ quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp | 2 +- quaddtype/tests/test_quaddtype.py | 7 ------- 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/ops.hpp b/quaddtype/numpy_quaddtype/src/ops.hpp index 10aeec56..08973f8a 100644 --- a/quaddtype/numpy_quaddtype/src/ops.hpp +++ b/quaddtype/numpy_quaddtype/src/ops.hpp @@ -37,12 +37,6 @@ quad_absolute(const Sleef_quad *op) return Sleef_fabsq1(*op); } -static inline Sleef_quad -quad_fabs(const Sleef_quad *op) -{ - return Sleef_fabsq1(*op); -} - static inline Sleef_quad quad_rint(const Sleef_quad *op) { @@ -223,12 +217,6 @@ ld_absolute(const long double *op) return fabsl(*op); } -static inline long double -ld_fabs(const long double *op) -{ - return fabsl(*op); -} - static inline long double ld_sign(const long double *op) { diff --git a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp index 52520f71..26b6a721 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -156,7 +156,7 @@ init_quad_unary_ops(PyObject *numpy) if (create_quad_unary_ufunc(numpy, "absolute") < 0) { return -1; } - if (create_quad_unary_ufunc(numpy, "fabs") < 0) { + if (create_quad_unary_ufunc(numpy, "fabs") < 0) { return -1; } if (create_quad_unary_ufunc(numpy, "sign") < 0) { diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 408a0142..ca500f49 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -1388,10 +1388,3 @@ def test_fabs(val): 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" - - # Verify that fabs and absolute give the same result for QuadPrecision - quad_absolute_result = np.absolute(quad_val) - np.testing.assert_array_equal( - np.array(quad_result).astype(float), - np.array(quad_absolute_result).astype(float) - ) From 7bde4c675c60c5c87d2ed3576cf37137ada17a69 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Fri, 17 Oct 2025 13:59:46 +0530 Subject: [PATCH 3/3] comment for fabs registration --- quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp index 26b6a721..b8a82aee 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -156,6 +156,8 @@ 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; }