From 50b83ad3fc5faa0c37109d63256111e62faf27c6 Mon Sep 17 00:00:00 2001 From: 0PrashantYadav0 Date: Tue, 20 Oct 2026 18:44:04 +0530 Subject: [PATCH] fix: avoid premature overflow in `math/base/special/cosh` --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown_pkg_readmes status: na - task: lint_markdown_docs status: na - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: missing_dependencies - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../math/base/special/cosh/lib/main.js | 7 ++++++ .../math/base/special/cosh/manifest.json | 9 +++++--- .../@stdlib/math/base/special/cosh/src/main.c | 7 ++++++ .../math/base/special/cosh/test/test.js | 22 +++++++++++++++++++ .../base/special/cosh/test/test.native.js | 22 +++++++++++++++++++ 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/cosh/lib/main.js b/lib/node_modules/@stdlib/math/base/special/cosh/lib/main.js index cc2feb94a0b4..561cc48b3f92 100644 --- a/lib/node_modules/@stdlib/math/base/special/cosh/lib/main.js +++ b/lib/node_modules/@stdlib/math/base/special/cosh/lib/main.js @@ -36,6 +36,7 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' ); var exp = require( '@stdlib/math/base/special/exp' ); +var MAX_LN = require( '@stdlib/constants/float64/max-ln' ); // MAIN // @@ -78,6 +79,7 @@ var exp = require( '@stdlib/math/base/special/exp' ); * // returns NaN */ function cosh( x ) { + var t; if ( isnan( x ) ) { return x; } @@ -85,6 +87,11 @@ function cosh( x ) { x = -x; } if ( x > 21.0 ) { + // Avoid premature overflow by evaluating `exp(x/2) * exp(x/2) / 2`: + if ( x > MAX_LN ) { + t = exp( 0.5 * x ); + return ( 0.5 * t ) * t; + } return exp( x ) / 2.0; } return ( exp(x) + exp(-x) ) / 2.0; diff --git a/lib/node_modules/@stdlib/math/base/special/cosh/manifest.json b/lib/node_modules/@stdlib/math/base/special/cosh/manifest.json index 8ca7869951dd..677fe8079ed6 100644 --- a/lib/node_modules/@stdlib/math/base/special/cosh/manifest.json +++ b/lib/node_modules/@stdlib/math/base/special/cosh/manifest.json @@ -38,7 +38,8 @@ "dependencies": [ "@stdlib/math/base/napi/unary", "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/exp" + "@stdlib/math/base/special/exp", + "@stdlib/constants/float64/max-ln" ] }, { @@ -53,7 +54,8 @@ "libpath": [], "dependencies": [ "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/exp" + "@stdlib/math/base/special/exp", + "@stdlib/constants/float64/max-ln" ] }, { @@ -68,7 +70,8 @@ "libpath": [], "dependencies": [ "@stdlib/math/base/assert/is-nan", - "@stdlib/math/base/special/exp" + "@stdlib/math/base/special/exp", + "@stdlib/constants/float64/max-ln" ] } ] diff --git a/lib/node_modules/@stdlib/math/base/special/cosh/src/main.c b/lib/node_modules/@stdlib/math/base/special/cosh/src/main.c index 1eb98ae87712..408524cf0274 100644 --- a/lib/node_modules/@stdlib/math/base/special/cosh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/cosh/src/main.c @@ -33,6 +33,7 @@ #include "stdlib/math/base/special/cosh.h" #include "stdlib/math/base/assert/is_nan.h" #include "stdlib/math/base/special/exp.h" +#include "stdlib/constants/float64/max_ln.h" /** * Computes the hyperbolic cosine of a double-precision floating-point number. @@ -61,6 +62,7 @@ */ double stdlib_base_cosh( const double x ) { double xc; + double t; if ( stdlib_base_is_nan( x ) ) { return x; } @@ -70,6 +72,11 @@ double stdlib_base_cosh( const double x ) { xc = x; } if ( xc > 21.0 ) { + // Avoid premature overflow by evaluating `exp(x/2) * exp(x/2) / 2`: + if ( xc > STDLIB_CONSTANT_FLOAT64_MAX_LN ) { + t = stdlib_base_exp( 0.5 * xc ); + return ( 0.5 * t ) * t; + } return stdlib_base_exp( xc ) / 2.0; } return ( stdlib_base_exp( xc ) + stdlib_base_exp( -xc ) ) / 2.0; diff --git a/lib/node_modules/@stdlib/math/base/special/cosh/test/test.js b/lib/node_modules/@stdlib/math/base/special/cosh/test/test.js index 308daea12051..2a1755f26b3b 100644 --- a/lib/node_modules/@stdlib/math/base/special/cosh/test/test.js +++ b/lib/node_modules/@stdlib/math/base/special/cosh/test/test.js @@ -120,3 +120,25 @@ tape( 'the function returns `+infinity` if provided a `-infinity`', function tes t.strictEqual( v, PINF, 'returns expected value' ); t.end(); }); + +tape( 'the function does not overflow for values whose hyperbolic cosine is representable', function test( t ) { + var expected; + var x; + var v; + var i; + + x = [ 709.9, 710.0, 710.4 ]; + expected = [ + 1.010701028059782e+308, + 1.1169973830808555e+308, + 1.6663642832806496e+308 + ]; + for ( i = 0; i < x.length; i++ ) { + v = cosh( x[ i ] ); + t.strictEqual( isAlmostSameValue( v, expected[ i ], 2 ), true, 'returns expected value' ); + v = cosh( -x[ i ] ); + t.strictEqual( isAlmostSameValue( v, expected[ i ], 2 ), true, 'returns expected value' ); + } + t.strictEqual( cosh( 711.0 ), PINF, 'returns expected value' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/math/base/special/cosh/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/cosh/test/test.native.js index c84d74dfc19c..f0f196e5f68f 100644 --- a/lib/node_modules/@stdlib/math/base/special/cosh/test/test.native.js +++ b/lib/node_modules/@stdlib/math/base/special/cosh/test/test.native.js @@ -129,3 +129,25 @@ tape( 'the function returns `+infinity` if provided a `-infinity`', opts, functi t.strictEqual( v, PINF, 'returns expected value' ); t.end(); }); + +tape( 'the function does not overflow for values whose hyperbolic cosine is representable', opts, function test( t ) { + var expected; + var x; + var v; + var i; + + x = [ 709.9, 710.0, 710.4 ]; + expected = [ + 1.010701028059782e+308, + 1.1169973830808555e+308, + 1.6663642832806496e+308 + ]; + for ( i = 0; i < x.length; i++ ) { + v = cosh( x[ i ] ); + t.strictEqual( isAlmostSameValue( v, expected[ i ], 2 ), true, 'returns expected value' ); + v = cosh( -x[ i ] ); + t.strictEqual( isAlmostSameValue( v, expected[ i ], 2 ), true, 'returns expected value' ); + } + t.strictEqual( cosh( 711.0 ), PINF, 'returns expected value' ); + t.end(); +});