-
Notifications
You must be signed in to change notification settings - Fork 475
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
Compute acos with less cancellation near x=1 #217
base: master
Are you sure you want to change the base?
Conversation
Interesting. I'll take a look. I wonder if the new formula is faster or slower? I wonder if there are any instances where the old formula is correct and the new formula is off by one unit in the last place (as the old formula is in your two new tests)? Can you provide any further evidence that the new formula is less prone to cancellation? |
I will gladly respond to these questions. Here are my best answers at the moment:
I would expect this method to be about the same, possibly slightly faster. It has an add, a subtract, a divide, a square root, an arctangent, and an integer multiplication. The old method, using arcsine, uses one more subtract and one more multipliction since it uses the formula Since you asked, I compared how each does on my machine (just the version of firefox I am using, 109.0.1 I suppose). I used each version of the code for 5 trials, doing the full set of 979 tests which both pass, including those commented out in the distributed version of the module but not including the two new cases. The old version took 3147, 3148, 3176, 3188, and 3236 milliseconds. The new version took 3086, 3088, 3119, 3123, and 3145 milliseconds. So, comparing the medians we find a typical improvement of 57 milliseconds for 979 tests. Not much compared to the variation from one trial to the next, but there is definitely a noticeable speed improvement.
I am not sure. I have had Hypothesis running for a few hours searching for any cases where the new formula gives an incorrect digit and I have yet to find one, although I have found a similar off-by-one error in the sine function, which I have yet to explain. Currently I only have my tool configured to search with one precision setting and one rounding mode, so it is reasonable to suspect there may be errors in other rounding modes. The new formula does pass all the old tests, however. If this introduces a regression then it is not a documented regression. Perhaps it will be fruitful to expand this tool to search for errors for other configurations of rounding mode and precision as well. This should be fairly straightforward to set up, though it will take some time.
The cancellation in the old method happens mostly at the last step, subtracting The following example illustrates why this is a problem. If In contrast, the new method gets all cancellation over with early, entirely in the To make things more explicit, I have added the following test cases based on the example I gave above. I will add these to the pull request momentarily.
|
For those interested: you can make the example given more rigorous by noting |
Previously
decimal.js
used the formulaacos(x) = pi/2 - asin(x)
, which has significant cancellation near x=1. I propose that instead we use the formulaacos(x)=2*atan(sqrt( (1-x)/(1+x) ))
, which has less cancellation.In addition, I provide two test cases where the old formula gives an incorrect digit, and where the new formula gives the correct answer.
I found these test cases using the Python tool
hypothesis
, comparing against the Python librarympmath
. I independently verified the test cases against Mathematica. I have also included the code used to generate those cases, in/test/hypothesis
. This may be useful in the future to generate more test cases.