Skip to content

Commit 238ce35

Browse files
committed
fabs impl
1 parent 4c2863d commit 238ce35

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

quaddtype/numpy_quaddtype/src/ops.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ quad_absolute(const Sleef_quad *op)
3737
return Sleef_fabsq1(*op);
3838
}
3939

40+
static inline Sleef_quad
41+
quad_fabs(const Sleef_quad *op)
42+
{
43+
return Sleef_fabsq1(*op);
44+
}
45+
4046
static inline Sleef_quad
4147
quad_rint(const Sleef_quad *op)
4248
{
@@ -217,6 +223,12 @@ ld_absolute(const long double *op)
217223
return fabsl(*op);
218224
}
219225

226+
static inline long double
227+
ld_fabs(const long double *op)
228+
{
229+
return fabsl(*op);
230+
}
231+
220232
static inline long double
221233
ld_sign(const long double *op)
222234
{

quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ init_quad_unary_ops(PyObject *numpy)
156156
if (create_quad_unary_ufunc<quad_absolute, ld_absolute>(numpy, "absolute") < 0) {
157157
return -1;
158158
}
159+
if (create_quad_unary_ufunc<quad_fabs, ld_fabs>(numpy, "fabs") < 0) {
160+
return -1;
161+
}
159162
if (create_quad_unary_ufunc<quad_sign, ld_sign>(numpy, "sign") < 0) {
160163
return -1;
161164
}

quaddtype/release_tracker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
| fmod |||
2424
| divmod | | |
2525
| absolute |||
26-
| fabs | | |
26+
| fabs | | |
2727
| rint |||
2828
| sign |||
2929
| heaviside | | |

quaddtype/tests/test_quaddtype.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,4 +1349,49 @@ def test_float_power_array():
13491349

13501350
assert result.dtype.name == "QuadPrecDType128"
13511351
for i in range(len(result)):
1352-
np.testing.assert_allclose(float(result[i]), expected[i], rtol=1e-13)
1352+
np.testing.assert_allclose(float(result[i]), expected[i], rtol=1e-13)
1353+
1354+
1355+
@pytest.mark.parametrize("val", [
1356+
# Positive values
1357+
"3.0", "12.5", "100.0", "1e100", "0.0",
1358+
# Negative values
1359+
"-3.0", "-12.5", "-100.0", "-1e100", "-0.0",
1360+
# Special values
1361+
"inf", "-inf", "nan", "-nan",
1362+
# Small values
1363+
"1e-100", "-1e-100"
1364+
])
1365+
def test_fabs(val):
1366+
"""
1367+
Test np.fabs ufunc for QuadPrecision dtype.
1368+
fabs computes absolute values (positive magnitude) for floating-point numbers.
1369+
It should behave identically to np.absolute for real (non-complex) types.
1370+
"""
1371+
quad_val = QuadPrecision(val)
1372+
float_val = float(val)
1373+
1374+
quad_result = np.fabs(quad_val)
1375+
float_result = np.fabs(float_val)
1376+
1377+
# Test with both scalar and array
1378+
quad_arr = np.array([quad_val], dtype=QuadPrecDType())
1379+
quad_arr_result = np.fabs(quad_arr)
1380+
1381+
# Check scalar result
1382+
np.testing.assert_array_equal(np.array(quad_result).astype(float), float_result)
1383+
1384+
# Check array result
1385+
np.testing.assert_array_equal(quad_arr_result.astype(float)[0], float_result)
1386+
1387+
# For zero results, check sign (should always be positive after fabs)
1388+
if float_result == 0.0:
1389+
assert not np.signbit(quad_result), f"fabs({val}) should not have negative sign"
1390+
assert not np.signbit(quad_arr_result[0]), f"fabs({val}) should not have negative sign"
1391+
1392+
# Verify that fabs and absolute give the same result for QuadPrecision
1393+
quad_absolute_result = np.absolute(quad_val)
1394+
np.testing.assert_array_equal(
1395+
np.array(quad_result).astype(float),
1396+
np.array(quad_absolute_result).astype(float)
1397+
)

0 commit comments

Comments
 (0)