-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Stabilization report
API summary
i*:n.isqrt()(panics ifnis negative) andn.checked_isqrt()(Noneifnis negative) (accepted by @dtolnay without ACP)u*:n.isqrt()(accepted by @dtolnay without ACP)NonZeroU*:n.isqrt()(ACP accepted)- all added methods are
const fn - fairly speedy implementations of those methods (available in the latest nightly compiler)
const fn concerns
If a better implementation comes along that can't be const fn, const_eval_select can be used to combine the better implementation with the current implementation to maintain const fn.
Experience report
These projects use the isqrt feature (note that only five pages of results are allowed, so there may be more uses):
- Uses of
#![feature(isqrt)] - Uses of
.isqrt() - Uses of
.checked_isqrt()(right now, there appear to be very few uses that aren'trust-lang/rustforks)
Standard libraries of programming languages
The following languages have an integer square root function in the standard library: Chapel, Common Lisp, Crystal, Julia, Maple, Python 3, Racket, Ruby, SageMath, Scheme, and Tcl.
Rust crates
integer-sqrt (6.3 million downloads of all versions; GitHub search)
num-bigint (133 million downloads of all versions)
rug (590 thousand downloads of all versions)
Other languages
Implementation history
- Enhancement request made during Rust 1.55: [ER] isqrt() function for integral values rust-lang/rust#89273
isqrtandchecked_isqrtmethods added to primitive types during 1.74 nightly: Add "integer square root" method to integer primitive types rust-lang/rust#116176- ACP accepted for
isqrtmethod on unsignedNonZerotypes during 1.80 nightly: ACP:isqrtforNonZero<uN>rust-lang/libs-team#391 isqrtmethod added to unsignedNonZerotypes during 1.81 nightly: AddisqrttoNonZero<uN>rust-lang/rust#126199- Sped up all relevant methods during 1.82 nightly: Improved
checked_isqrtandisqrtmethods rust-lang/rust#128166
Performance
The current implementation is based on a lookup table for 8-bit integers and "unrolled" recursive Karatsuba square root for larger types. The performance is decent, but it can be beaten with f32::sqrt and f64::sqrt for 16-bit through 64-bit integers (64 bit needs a slight adjustment to correct for imprecision). Even 128-bit integers could be sped up by using Karatsuba square root combined with the 64-bit floating point-based algorithm.
It isn't done that way because:
- Rust has no runtime detection of fast floating point hardware square root instructions (software-based floating point square roots are likely to be slower than the current implementation).
- Rust has no way to allow the Linux kernel and similar projects to forbid floating point arithmetic and to communicate that to
corelibrary code via acfgsetting or similar.
Ignoring floating point implementations, there are also faster algorithms that use only integer operations (for example the GMP library has faster implementations). I'm not a lawyer, but I believe that porting those to Rust would be considered a derivative work, and thus require adherence to the original code's license. Since the Rust standard library appears to be dual licensed under Apache 2.0 and MIT and since GMP is licensed under both LGPL 2 and LGPL 3, we'd have to complicate our licensing situation to port the GMP code.
Is there anything else that needs to be taken care of before the isqrt feature is stabilized?