@@ -100,9 +100,9 @@ def test_array_minmax(op, a, b):
100
100
np .testing .assert_array_equal (quad_res .astype (float ), float_res )
101
101
102
102
# 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 } )"
106
106
107
107
108
108
@pytest .mark .parametrize ("op" , ["amin" , "amax" , "nanmin" , "nanmax" ])
@@ -119,9 +119,9 @@ def test_array_aminmax(op, a, b):
119
119
np .testing .assert_array_equal (np .array (quad_res ).astype (float ), float_res )
120
120
121
121
# 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 } )"
125
125
126
126
127
127
@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):
478
478
numpy_negative = numpy_result < 0
479
479
480
480
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