Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accuracy of sinh and complex cos/sin #247

Merged
merged 3 commits into from Dec 14, 2014

Conversation

pavpanchekha
Copy link
Contributor

The sin and cos function for complex arguments, and the sinh function for real arguments, are inaccurate when the inputs are very small. This is because Math.exp(x) - Math.exp(-x) returns zero for small x, instead of the more accurate 2x.

This patch replaces sinh by a Taylor expansion when the input is small, which increases accuracy.

return x + (x * x * x) / 6 + (x * x * x * x * x) / 120;
} else {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style note: You have a return statement in the if, so you don't need the else.

if (Math.abs(x) < 1) {
  return x + (x * x * x) / 6 + (x * x * x * x * x) / 120;
}
return (Math.exp(x) - Math.exp(-x)) / 2;

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both versions are ok. @BigFav version is more compact, but on the other hand, an explicit else shows very clearly that the second return is only occurring in an else case (there are rules of thumb that say that every if should have an else prevents cases similar to these tricky fall-though cases of switches). Both are fine with me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it as is for now, but would be happy with whatever you decide.

@BigFav
Copy link
Collaborator

BigFav commented Dec 13, 2014

Good job catching this case. Most of my comments are style related (with the only exception of the failed test case), so hopefully this will be merged pretty smoothly.

@josdejong
Copy link
Owner

Thanks @pavpanchekha, nice improvement! Can you please fix this round-off error making the unit tests fail? After that I will merge your PR.

The fix is to test that the imaginary part is nonzero,
not that it is exactly 1e-100.
In some software / hardware combos,
it seems to return 1.0000000000000001e-100.
@josdejong
Copy link
Owner

Thanks a lot @pavpanchekha

josdejong added a commit that referenced this pull request Dec 14, 2014
@josdejong josdejong merged commit 77e32bb into josdejong:develop Dec 14, 2014
@jrus
Copy link

jrus commented Oct 19, 2015

This 5th degree taylor expansion of sinh is quite far off when you get close to -1 or 1. For example, for x = 0.99, it’s off by about 1.87e-4. I assume that’s dramatically more error than you want in a math library.

For a graph of the error, here’s Wolfram Alpha: http://www.wolframalpha.com/input/?i=sinh%28x%29+-+%28x+%2B+%281%2F6%29+*+x%5E3+%2B+%281%2F120%29+*+x+%5E+5%29+from+-1+to+1

The GNU Scientific Library uses the degree 17 Taylor expansion for computing sinh in the range [-1, 1]:
https://github.com/ampl/gsl/blob/1a819c2daab24f5f/specfunc/trig.c#L39-L52

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants