diff --git a/quaddtype/numpy_quaddtype/src/ops.hpp b/quaddtype/numpy_quaddtype/src/ops.hpp index 252fb2d..1a45bac 100644 --- a/quaddtype/numpy_quaddtype/src/ops.hpp +++ b/quaddtype/numpy_quaddtype/src/ops.hpp @@ -72,6 +72,12 @@ quad_square(const Sleef_quad *op) return Sleef_mulq1_u05(*op, *op); } +static inline Sleef_quad +quad_reciprocal(const Sleef_quad *op) +{ + return Sleef_divq1_u05(QUAD_ONE, *op); +} + static inline Sleef_quad quad_log(const Sleef_quad *op) { @@ -211,6 +217,12 @@ ld_square(const long double *op) return (*op) * (*op); } +static inline long double +ld_reciprocal(const long double *op) +{ + return 1.0L / (*op); +} + static inline long double ld_log(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 c0a0be8..09e45e9 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -177,6 +177,9 @@ init_quad_unary_ops(PyObject *numpy) if (create_quad_unary_ufunc(numpy, "square") < 0) { return -1; } + if (create_quad_unary_ufunc(numpy, "reciprocal") < 0) { + return -1; + } if (create_quad_unary_ufunc(numpy, "log") < 0) { return -1; } diff --git a/quaddtype/release_tracker.md b/quaddtype/release_tracker.md index 33914a4..b01a1c7 100644 --- a/quaddtype/release_tracker.md +++ b/quaddtype/release_tracker.md @@ -7,7 +7,7 @@ | add | ✅ | ✅ | | subtract | ✅ | ✅ | | multiply | ✅ | ✅ | -| matmul | ✅ | ✅ | +| matmul | ✅ | ✅ | | divide | ✅ | ✅ | | logaddexp | | | | logaddexp2 | | | @@ -24,7 +24,7 @@ | absolute | ✅ | ✅ | | fabs | | | | rint | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/±0.0/halfway cases)_ | -| sign | ✅ | ✅ | +| sign | ✅ | ✅ | | heaviside | | | | conj | | | | conjugate | | | @@ -35,10 +35,10 @@ | log10 | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/0/-values/1)_ | | expm1 | | | | log1p | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/-1/small values)_ | -| sqrt | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/0/-values)_ | -| square | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/0/large values)_ | +| sqrt | ✅ | ✅ | +| square | ✅ | ✅ | | cbrt | | | -| reciprocal | | | +| reciprocal | ✅ | ✅ | | gcd | | | | lcm | | | | sin | ✅ | ❌ _Need: basic tests + edge cases (NaN/inf/0/π multiples/2π range)_ | @@ -77,14 +77,14 @@ | logical_not | | | | maximum | ✅ | ✅ | | minimum | ✅ | ✅ | -| fmax | ✅ | ✅ | -| fmin | ✅ | ✅ | -| isfinite | ✅ | ✅ | -| isinf | ✅ | ✅ | -| isnan | ✅ | ✅ | +| fmax | ✅ | ✅ | +| fmin | ✅ | ✅ | +| isfinite | ✅ | ✅ | +| isinf | ✅ | ✅ | +| isnan | ✅ | ✅ | | isnat | | | -| signbit | ✅ | ✅ | -| copysign | ✅ | ✅ | +| signbit | ✅ | ✅ | +| copysign | ✅ | ✅ | | nextafter | | | | spacing | | | | modf | | | diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index ef7c6d0..7a755a3 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -103,8 +103,8 @@ def test_array_aminmax(op, a, b): np.testing.assert_array_equal(np.array(quad_res).astype(float), float_res) -@pytest.mark.parametrize("op", ["negative", "positive", "absolute", "sign", "signbit", "isfinite", "isinf", "isnan"]) -@pytest.mark.parametrize("val", ["3.0", "-3.0", "12.5", "100.0", "0.0", "-0.0", "inf", "-inf", "nan", "-nan"]) +@pytest.mark.parametrize("op", ["negative", "positive", "absolute", "sign", "signbit", "isfinite", "isinf", "isnan", "sqrt", "square", "reciprocal"]) +@pytest.mark.parametrize("val", ["3.0", "-3.0", "12.5", "100.0", "1e100", "0.0", "-0.0", "inf", "-inf", "nan", "-nan"]) def test_unary_ops(op, val): op_func = dict(negative=operator.neg, positive=operator.pos, absolute=operator.abs).get(op, None) nop_func = getattr(np, op) @@ -120,7 +120,9 @@ def test_unary_ops(op, val): float_result = of(float_val) np.testing.assert_array_equal(np.array(quad_result).astype(float), float_result) - assert np.signbit(float_result) == np.signbit(quad_result) + + if op in ["negative", "positive", "absolute", "sign"]: + assert np.signbit(float_result) == np.signbit(quad_result) def test_inf():