From 0de3e893baf1a5ea0df716c0b1c638ffab4e8517 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 17 Oct 2025 16:20:18 +0000 Subject: [PATCH 1/4] degrees and rad2deg impl --- quaddtype/numpy_quaddtype/src/ops.hpp | 19 +++++++++ .../numpy_quaddtype/src/umath/unary_ops.cpp | 6 +++ quaddtype/release_tracker.md | 4 +- quaddtype/tests/test_quaddtype.py | 41 +++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/ops.hpp b/quaddtype/numpy_quaddtype/src/ops.hpp index 826cab57..467679d2 100644 --- a/quaddtype/numpy_quaddtype/src/ops.hpp +++ b/quaddtype/numpy_quaddtype/src/ops.hpp @@ -243,6 +243,15 @@ quad_atanh(const Sleef_quad *op) return Sleef_atanhq1_u10(*op); } +static inline Sleef_quad +quad_degrees(const Sleef_quad *op) +{ + // degrees = radians * 180 / π + static const Sleef_quad one_eighty = Sleef_strtoq("180.0", NULL); + Sleef_quad ratio = Sleef_divq1_u05(one_eighty, SLEEF_M_PIq); + return Sleef_mulq1_u05(*op, ratio); +} + // Unary long double operations typedef long double (*unary_op_longdouble_def)(const long double *); @@ -446,6 +455,16 @@ ld_atanh(const long double *op) return atanhl(*op); } +static inline long double +ld_degrees(const long double *op) +{ + // degrees = radians * 180 / π + #ifndef M_PI + #define M_PI 3.14159265358979323846 + #endif + return (*op) * (180.0L / static_cast(M_PI)); +} + // Unary Quad properties typedef npy_bool (*unary_prop_quad_def)(const Sleef_quad *); diff --git a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp index a6c69442..7e943e92 100644 --- a/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/unary_ops.cpp @@ -250,5 +250,11 @@ init_quad_unary_ops(PyObject *numpy) if (create_quad_unary_ufunc(numpy, "arctanh") < 0) { return -1; } + if (create_quad_unary_ufunc(numpy, "degrees") < 0) { + return -1; + } + if (create_quad_unary_ufunc(numpy, "rad2deg") < 0) { + return -1; + } return 0; } \ No newline at end of file diff --git a/quaddtype/release_tracker.md b/quaddtype/release_tracker.md index e9b84f37..ba8e715e 100644 --- a/quaddtype/release_tracker.md +++ b/quaddtype/release_tracker.md @@ -54,10 +54,10 @@ | arcsinh | ✅ | ✅ | | arccosh | ✅ | ✅ | | arctanh | ✅ | ✅ | -| degrees | | | +| degrees | ✅ | ✅ | | radians | | | | deg2rad | | | -| rad2deg | | | +| rad2deg | ✅ | ✅ | | bitwise_and | | | | bitwise_or | | | | bitwise_xor | | | diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 1a0bc97d..5fdc234b 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -1905,3 +1905,44 @@ def test_hypot(x1, x2, expected): else: np.testing.assert_allclose(float(result), expected, rtol=1e-13) + +@pytest.mark.parametrize("op", [np.degrees, np.rad2deg]) +@pytest.mark.parametrize("radians,expected_degrees", [ + # Basic conversions + (0.0, 0.0), + (np.pi / 6, 30.0), + (np.pi / 4, 45.0), + (np.pi / 3, 60.0), + (np.pi / 2, 90.0), + (np.pi, 180.0), + (3 * np.pi / 2, 270.0), + (2 * np.pi, 360.0), + # Negative values + (-np.pi / 2, -90.0), + (-np.pi, -180.0), + # Special values + (np.inf, np.inf), + (-np.inf, -np.inf), + (np.nan, np.nan), + # Edge cases + (0.0, 0.0), + (-0.0, -0.0), +]) +def test_degrees_rad2deg(op, radians, expected_degrees): + """Test degrees and rad2deg ufuncs convert radians to degrees""" + q_rad = QuadPrecision(radians) + result = op(q_rad) + + assert isinstance(result, QuadPrecision) + + if np.isnan(expected_degrees): + assert np.isnan(float(result)) + elif np.isinf(expected_degrees): + assert np.isinf(float(result)) + if expected_degrees > 0: + assert float(result) > 0 + else: + assert float(result) < 0 + else: + np.testing.assert_allclose(float(result), expected_degrees, rtol=1e-13) + From abb784e837cc6b9c78236febe8ae168f8f59c963 Mon Sep 17 00:00:00 2001 From: Swayam Date: Sat, 18 Oct 2025 01:34:02 +0530 Subject: [PATCH 2/4] Update quaddtype/tests/test_quaddtype.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- quaddtype/tests/test_quaddtype.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 5fdc234b..e6f78336 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -1925,7 +1925,6 @@ def test_hypot(x1, x2, expected): (-np.inf, -np.inf), (np.nan, np.nan), # Edge cases - (0.0, 0.0), (-0.0, -0.0), ]) def test_degrees_rad2deg(op, radians, expected_degrees): From 7142d0687fecf15775892dd3be0e1ba74a8ddc23 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 18 Oct 2025 12:46:41 +0530 Subject: [PATCH 3/4] qutil --- quaddtype/numpy_quaddtype/src/ops.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quaddtype/numpy_quaddtype/src/ops.hpp b/quaddtype/numpy_quaddtype/src/ops.hpp index 467679d2..dd05731a 100644 --- a/quaddtype/numpy_quaddtype/src/ops.hpp +++ b/quaddtype/numpy_quaddtype/src/ops.hpp @@ -247,7 +247,7 @@ static inline Sleef_quad quad_degrees(const Sleef_quad *op) { // degrees = radians * 180 / π - static const Sleef_quad one_eighty = Sleef_strtoq("180.0", NULL); + static const Sleef_quad one_eighty = sleef_q(+0x1680000000000LL, 0x0000000000000000ULL, 7); // 180.0 in quad Sleef_quad ratio = Sleef_divq1_u05(one_eighty, SLEEF_M_PIq); return Sleef_mulq1_u05(*op, ratio); } From f7d84b774d2a876b9769b1dfa9e01c7c20377ffc Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 18 Oct 2025 13:34:55 +0530 Subject: [PATCH 4/4] bitwise ops not defined for float --- quaddtype/release_tracker.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/quaddtype/release_tracker.md b/quaddtype/release_tracker.md index ba8e715e..535a5d66 100644 --- a/quaddtype/release_tracker.md +++ b/quaddtype/release_tracker.md @@ -58,12 +58,6 @@ | radians | | | | deg2rad | | | | rad2deg | ✅ | ✅ | -| bitwise_and | | | -| bitwise_or | | | -| bitwise_xor | | | -| invert | | | -| left_shift | | | -| right_shift | | | | greater | ✅ | ✅ | | greater_equal | ✅ | ✅ | | less | ✅ | ✅ |