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
Accuracy of sinh and complex cos/sin #247
Conversation
return x + (x * x * x) / 6 + (x * x * x * x * x) / 120; | ||
} else { | ||
return (Math.exp(x) - Math.exp(-x)) / 2; | ||
} |
There was a problem hiding this comment.
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;
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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. |
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.
Thanks a lot @pavpanchekha |
Accuracy of sinh and complex cos/sin
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]: |
The
sin
andcos
function for complex arguments, and thesinh
function for real arguments, are inaccurate when the inputs are very small. This is becauseMath.exp(x) - Math.exp(-x)
returns zero for small x, instead of the more accurate2x
.This patch replaces
sinh
by a Taylor expansion when the input is small, which increases accuracy.