Skip to content

Commit 6f25601

Browse files
committed
Add hyperbolic tests
1 parent cd7f089 commit 6f25601

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

quaddtype/release_tracker.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@
5050
| arctan ||_Need: basic tests + edge cases (NaN/inf/0/asymptotes)_ |
5151
| arctan2 ||_Need: basic tests + edge cases (NaN/inf/0/quadrant coverage)_ |
5252
| hypot | | |
53-
| sinh | | |
54-
| cosh | | |
55-
| tanh | | |
56-
| arcsinh | | |
57-
| arccosh | | |
58-
| arctanh | | |
53+
| sinh | | |
54+
| cosh | | |
55+
| tanh | | |
56+
| arcsinh | | |
57+
| arccosh | | |
58+
| arctanh | | |
5959
| degrees | | |
6060
| radians | | |
6161
| deg2rad | | |

quaddtype/tests/test_quaddtype.py

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ def test_array_minmax(op, a, b):
100100
np.testing.assert_array_equal(quad_res.astype(float), float_res)
101101

102102
# Check sign for zero results
103-
if float_result == 0.0:
104-
assert np.signbit(float_result) == np.signbit(
105-
quad_result), f"Zero sign mismatch for {op}({a}, {b})"
103+
if float_res == 0.0:
104+
assert np.signbit(float_res) == np.signbit(
105+
quad_res), f"Zero sign mismatch for {op}({a}, {b})"
106106

107107

108108
@pytest.mark.parametrize("op", ["amin", "amax", "nanmin", "nanmax"])
@@ -119,9 +119,9 @@ def test_array_aminmax(op, a, b):
119119
np.testing.assert_array_equal(np.array(quad_res).astype(float), float_res)
120120

121121
# Check sign for zero results
122-
if float_result == 0.0:
123-
assert np.signbit(float_result) == np.signbit(
124-
quad_result), f"Zero sign mismatch for {op}({a}, {b})"
122+
if float_res == 0.0:
123+
assert np.signbit(float_res) == np.signbit(
124+
quad_res), f"Zero sign mismatch for {op}({a}, {b})"
125125

126126

127127
@pytest.mark.parametrize("op", ["negative", "positive", "absolute", "sign", "signbit", "isfinite", "isinf", "isnan", "sqrt", "square", "reciprocal"])
@@ -478,3 +478,58 @@ def test_mod(a, b, backend, op):
478478
numpy_negative = numpy_result < 0
479479

480480
assert result_negative == numpy_negative, f"Sign mismatch for {a} % {b}: quad={result_negative}, numpy={numpy_negative}"
481+
482+
483+
@pytest.mark.parametrize("op", ["sinh", "cosh", "tanh", "arcsinh", "arccosh", "arctanh"])
484+
@pytest.mark.parametrize("val", [
485+
# Basic cases
486+
"0.0", "-0.0", "1.0", "-1.0", "2.0", "-2.0",
487+
# Small values
488+
"1e-10", "-1e-10", "1e-15", "-1e-15",
489+
# Values near one
490+
"0.9", "-0.9", "0.9999", "-0.9999",
491+
"1.1", "-1.1", "1.0001", "-1.0001",
492+
# Medium values
493+
"10.0", "-10.0", "20.0", "-20.0",
494+
# Large values
495+
"100.0", "200.0", "700.0", "1000.0",
496+
"-100.0", "-200.0", "-700.0", "-1000.0",
497+
# Fractional values
498+
"0.5", "-0.5", "1.5", "-1.5", "2.5", "-2.5",
499+
# Special values
500+
"inf", "-inf", "nan", "-nan"
501+
])
502+
def test_hyperbolic_functions(op, val):
503+
"""Comprehensive test for hyperbolic functions: sinh, cosh, tanh, arcsinh, arccosh, arctanh"""
504+
op_func = getattr(np, op)
505+
506+
quad_val = QuadPrecision(val)
507+
float_val = float(val)
508+
509+
quad_result = op_func(quad_val)
510+
float_result = op_func(float_val)
511+
512+
# Handle NaN cases
513+
if np.isnan(float_result):
514+
assert np.isnan(
515+
float(quad_result)), f"Expected NaN for {op}({val}), got {float(quad_result)}"
516+
return
517+
518+
# Handle infinity cases
519+
if np.isinf(float_result):
520+
assert np.isinf(
521+
float(quad_result)), f"Expected inf for {op}({val}), got {float(quad_result)}"
522+
assert np.sign(float_result) == np.sign(
523+
float(quad_result)), f"Infinity sign mismatch for {op}({val})"
524+
return
525+
526+
# For finite non-zero results
527+
# Use relative tolerance for exponential functions due to their rapid growth
528+
rtol = 1e-14 if abs(float_result) < 1e100 else 1e-10
529+
np.testing.assert_allclose(float(quad_result), float_result, rtol=rtol, atol=1e-15,
530+
err_msg=f"Value mismatch for {op}({val})")
531+
532+
# Check sign for zero results
533+
if float_result == 0.0:
534+
assert np.signbit(float_result) == np.signbit(
535+
quad_result), f"Zero sign mismatch for {op}({val})"

0 commit comments

Comments
 (0)