Skip to content

fix: avoid cancellation near one in math/base/special/asech - #16110

Draft
Abhist17 wants to merge 1 commit into
stdlib-js:developfrom
Abhist17:fix/asech-near-one
Draft

Abhist17 wants to merge 1 commit into
stdlib-js:developfrom
Abhist17:fix/asech-near-one

Conversation

@Abhist17

Copy link
Copy Markdown
Contributor

Description

What is the purpose of this pull request?

This pull request:

  • evaluates math/base/special/asech as log1p( ((1-x) + sqrt((1-x)*(1+x)))/x ) for 0.5 <= x <= 1 (JS and C), instead of acosh( 1/x ).

acosh( 1/x ) depends on 1/x - 1, and rounding 1/x loses its low bits. Near one, those bits are most of the result:

var asech = require( '@stdlib/math/base/special/asech' );

asech( 0.999999999999999 );
// develop: 4.712160915387241e-8
// this PR: 4.470348358154299e-8 (256-bit BigFloat: 4.470348358154299e-8)

In [0.5, 1], 1-x is exact, so the new form has no cancellation. Elsewhere the function is unchanged.

  • regenerates data.json in 256-bit BigFloat. It was generated with Julia's Float64 asech, which is also acosh(inv(x)), so its reference values carried the same error.
  • adds near_one.json, 1000 values 1 - 10^k for k in [-16, -1]. develop is off by up to about 2^30 ULPs on it, and this PR is within 2. data.json is checked at 2 ULPs instead of 1, since against the exact reference six of its 2003 points are 2 ULPs off.

Related Issues

Does this pull request have any related issues?

None. asec, acoth and acsc have the same f( 1/x ) construction and lose accuracy near |x| = 1 too (acoth( 1.000000001 ) and asec( 1.000000001 ) are off by about 3e5 and 3e6 ULPs). I'll send those separately.

Questions

Any questions for reviewers of this pull request?

No.

Other

Any other information relevant to this pull request? This may include screenshots, references, and/or implementation notes.

test.js and test.native.js: 5008 pass.

Checklist

Please ensure the following tasks are completed before submitting this pull request.

AI Assistance

When authoring the changes proposed in this PR, did you use any kind of AI assistance?

  • Yes
  • No

If you answered "yes" above, how did you use AI assistance?

  • Code generation (e.g., when writing an implementation or fixing a bug)
  • Test/benchmark generation
  • Documentation (including examples)
  • Research and understanding

`acosh( 1/x )` loses the low bits of `1/x - 1` to the rounding of `1/x`,
and near one those bits are most of the result: `asech( 1 - 1e-15 )` was
off by 5% (`4.712e-8` for `4.470e-8`). For `0.5 <= x <= 1`, evaluate
`log1p( ((1-x) + sqrt((1-x)*(1+x)))/x )` instead, where `1-x` is exact.

The fixtures were generated with Julia's Float64 `asech`, which is also
`acosh(inv(x))`; they are now evaluated in BigFloat, with a new set of
values close to one.

Signed-off-by: Abhist17 <abhistkamle.170903@gmail.com>
@Abhist17
Abhist17 requested a review from a team October 13, 2026 13:25
@stdlib-bot stdlib-bot added Math Issue or pull request specific to math functionality. Needs Review A pull request which needs code review. labels Oct 13, 2026
@stdlib-bot

Copy link
Copy Markdown
Contributor

Coverage Report

Package Statements Branches Functions Lines
math/base/special/asech $\\color{green}168/168$
$\\color{green}+100.00\\%$
$\\color{green}8/8$
$\\color{green}+100.00\\%$
$\\color{green}2/2$
$\\color{green}+100.00\\%$
$\\color{green}168/168$
$\\color{green}+100.00\\%$

The above coverage report was generated for the changes in this PR.

@Abhist17
Abhist17 marked this pull request as draft October 14, 2026 04:16
@stdlib-bot stdlib-bot removed the Needs Review A pull request which needs code review. label Oct 14, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Math Issue or pull request specific to math functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants