Skip to content

Commit 0f1e4a6

Browse files
authored
Merge pull request #185 from SwayamInSync/hypot
2 parents f67f5f1 + d4e4262 commit 0f1e4a6

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

quaddtype/numpy_quaddtype/src/ops.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,13 @@ quad_heaviside(const Sleef_quad *x1, const Sleef_quad *x2)
838838
}
839839
}
840840

841+
static inline Sleef_quad
842+
quad_hypot(const Sleef_quad *x1, const Sleef_quad *x2)
843+
{
844+
// hypot(x1, x2) = sqrt(x1^2 + x2^2)
845+
return Sleef_hypotq1_u05(*x1, *x2);
846+
}
847+
841848
// Binary long double operations
842849
typedef long double (*binary_op_longdouble_def)(const long double *, const long double *);
843850
// Binary long double operations with 2 outputs (for divmod, modf, frexp)
@@ -1108,6 +1115,14 @@ ld_heaviside(const long double *x1, const long double *x2)
11081115
}
11091116
}
11101117

1118+
static inline long double
1119+
ld_hypot(const long double *x1, const long double *x2)
1120+
{
1121+
// hypot(x1, x2) = sqrt(x1^2 + x2^2)
1122+
// Use the standard library hypotl function
1123+
return hypotl(*x1, *x2);
1124+
}
1125+
11111126
// comparison quad functions
11121127
typedef npy_bool (*cmp_quad_def)(const Sleef_quad *, const Sleef_quad *);
11131128

quaddtype/numpy_quaddtype/src/umath/binary_ops.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ init_quad_binary_ops(PyObject *numpy)
457457
if (create_quad_binary_ufunc<quad_heaviside, ld_heaviside>(numpy, "heaviside") < 0) {
458458
return -1;
459459
}
460+
if (create_quad_binary_ufunc<quad_hypot, ld_hypot>(numpy, "hypot") < 0) {
461+
return -1;
462+
}
460463
if (create_quad_binary_2out_ufunc<quad_divmod, ld_divmod>(numpy, "divmod") < 0) {
461464
return -1;
462465
}

quaddtype/release_tracker.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929
| heaviside |||
3030
| conj |||
3131
| conjugate |||
32-
| heaviside |||
33-
| conj | | |
34-
| conjugate | | |
3532
| exp |||
3633
| exp2 |||
3734
| log |||
@@ -50,7 +47,7 @@
5047
| arccos ||_Need: basic tests + edge cases (NaN/inf/±1/out-of-domain)_ |
5148
| arctan ||_Need: basic tests + edge cases (NaN/inf/0/asymptotes)_ |
5249
| arctan2 ||_Need: basic tests + edge cases (NaN/inf/0/quadrant coverage)_ |
53-
| hypot | | |
50+
| hypot | | |
5451
| sinh |||
5552
| cosh |||
5653
| tanh |||

quaddtype/tests/test_quaddtype.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,3 +1859,49 @@ def test_conj_conjugate_identity(func, value):
18591859
else:
18601860
assert result == x
18611861

1862+
1863+
@pytest.mark.parametrize("x1,x2,expected", [
1864+
# Basic Pythagorean triples
1865+
(3.0, 4.0, 5.0),
1866+
(5.0, 12.0, 13.0),
1867+
# Zero cases
1868+
(0.0, 0.0, 0.0),
1869+
(0.0, 5.0, 5.0),
1870+
(5.0, 0.0, 5.0),
1871+
# Negative values (hypot uses absolute values)
1872+
(-3.0, -4.0, 5.0),
1873+
(-3.0, 4.0, 5.0),
1874+
(3.0, -4.0, 5.0),
1875+
# Symmetry
1876+
(3.14159265358979323846, 2.71828182845904523536, None), # Will test symmetry
1877+
(2.71828182845904523536, 3.14159265358979323846, None), # Will test symmetry
1878+
# Infinity cases
1879+
(np.inf, 0.0, np.inf),
1880+
(0.0, np.inf, np.inf),
1881+
(np.inf, np.inf, np.inf),
1882+
(-np.inf, 0.0, np.inf),
1883+
(np.inf, -np.inf, np.inf),
1884+
# NaN cases
1885+
(np.nan, 3.0, np.nan),
1886+
(3.0, np.nan, np.nan),
1887+
(np.nan, np.nan, np.nan),
1888+
])
1889+
def test_hypot(x1, x2, expected):
1890+
"""Test hypot ufunc with various edge cases"""
1891+
q1 = QuadPrecision(x1)
1892+
q2 = QuadPrecision(x2)
1893+
result = np.hypot(q1, q2)
1894+
1895+
assert isinstance(result, QuadPrecision)
1896+
1897+
if expected is None:
1898+
# Symmetry test - just check the values are equal
1899+
result_reverse = np.hypot(q2, q1)
1900+
assert result == result_reverse
1901+
elif np.isnan(expected):
1902+
assert np.isnan(float(result))
1903+
elif np.isinf(expected):
1904+
assert np.isinf(float(result))
1905+
else:
1906+
np.testing.assert_allclose(float(result), expected, rtol=1e-13)
1907+

0 commit comments

Comments
 (0)