-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add integer square root #10549
Add integer square root #10549
Conversation
To get this to run correctly for 64-bits ints I had to do this:
|
My tests show Newton's method is faster.
|
Your tests are correct. My setup for for that was extremely broken, and I was also using a different impl of your Newton's method. Here's what I'm woking off currently: https://gist.github.com/kimburgess/6a57c220d431fdae1e43b4c2db636708 Results from a local machine:
It feels almost dirty, but based on this and given that precision does not degrade until moving into the high ranges of a UInt64 a good option seems to be just taking advantage of the FPU and casting up all signed integers and unsigned up to 32 bit, switching to Newton's method for UInt64's (all, for simplicity), then bumping up to LibGMP for BigInts. |
Interesting! I get similar relative results running your benchmark code. However, the
Also, Given that the If you want to feel Given that the |
Just thinking. If you want to create a single hybrid method, then do the fastest for |
1bdf7a6 added in I agree with the comments on the issue thread that bumping this out of For perf, here's a sample for random inputs across each type. Y-axis is iterations / second as provided by |
Also, obligatory "premature optimisation is the root of all evil"... yes maybe, but it's fun! |
I'd probably prefer adding just a correct default implementation first. Performance optimizations can always be figured out afterwards. The method should be next to |
The complexity with this being
Both Newton's method and the abacus algorithm this implements yield correct results for all primitive types. As above, this does appear to provide the better performance in the majority of use cases, and also consistent performance within each type. @jzakiya you likely have significantly more experience in this area though so very open to contradiction of that statement if there's something that I'm missing. |
You can define isqrt in Math. Define it for primitives by default, and add an overload for BigIn inside big_int.cr |
Not sure what went on with the |
I suppose that segfault might warrant a separate investigation but yeah it's unlikely to be related to the changes here. It happens somewehere in a finalize handler. Could just be an LLVM bug or some never-reproducible coincidence 🤷 |
Hey @kimburgess can you provide a link to your benchmark code that created the data for the different Int types. I find those results very interesting (surprising) and maybe I can get some academic types I know to investigate why they occur. |
Sure thing. Here's what generated those outputs along with the raw results from my local runs: https://gist.github.com/kimburgess/f85038f4fb9ee9315d9d8b16b41b115f. Columns in the csv's are:
One extremely solid point from another recent PR is that |
Thank you @kimburgess. |
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.
Thank you!
Adds an integer square root operation to stdlib.
Resolves #10545