|
3 | 3 | use crate::cmp::Ordering;
|
4 | 4 | use crate::fmt;
|
5 | 5 | use crate::hash::{Hash, Hasher};
|
| 6 | +use crate::hint; |
6 | 7 | use crate::intrinsics;
|
7 | 8 | use crate::marker::{Freeze, StructuralPartialEq};
|
8 | 9 | use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
|
@@ -1204,6 +1205,58 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
|
1204 | 1205 |
|
1205 | 1206 | intrinsics::ctpop(self.get()) < 2
|
1206 | 1207 | }
|
| 1208 | + |
| 1209 | + /// Returns the square root of the number, rounded down. |
| 1210 | + /// |
| 1211 | + /// # Examples |
| 1212 | + /// |
| 1213 | + /// Basic usage: |
| 1214 | + /// ``` |
| 1215 | + /// #![feature(isqrt)] |
| 1216 | + /// # use std::num::NonZero; |
| 1217 | + /// # |
| 1218 | + /// # fn main() { test().unwrap(); } |
| 1219 | + /// # fn test() -> Option<()> { |
| 1220 | + #[doc = concat!("let ten = NonZero::new(10", stringify!($Int), ")?;")] |
| 1221 | + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] |
| 1222 | + /// |
| 1223 | + /// assert_eq!(ten.isqrt(), three); |
| 1224 | + /// # Some(()) |
| 1225 | + /// # } |
| 1226 | + #[unstable(feature = "isqrt", issue = "116226")] |
| 1227 | + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] |
| 1228 | + #[must_use = "this returns the result of the operation, \ |
| 1229 | + without modifying the original"] |
| 1230 | + #[inline] |
| 1231 | + pub const fn isqrt(self) -> Self { |
| 1232 | + // The algorithm is based on the one presented in |
| 1233 | + // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)> |
| 1234 | + // which cites as source the following C code: |
| 1235 | + // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>. |
| 1236 | + |
| 1237 | + let mut op = self.get(); |
| 1238 | + let mut res = 0; |
| 1239 | + let mut one = 1 << (self.ilog2() & !1); |
| 1240 | + |
| 1241 | + while one != 0 { |
| 1242 | + if op >= res + one { |
| 1243 | + op -= res + one; |
| 1244 | + res = (res >> 1) + one; |
| 1245 | + } else { |
| 1246 | + res >>= 1; |
| 1247 | + } |
| 1248 | + one >>= 2; |
| 1249 | + } |
| 1250 | + |
| 1251 | + // SAFETY: The result fits in an integer with half as many bits. |
| 1252 | + // Inform the optimizer about it. |
| 1253 | + unsafe { |
| 1254 | + hint::assert_unchecked(res < 1 << (Self::BITS / 2)); |
| 1255 | + } |
| 1256 | + |
| 1257 | + // SAFETY: The result is positive. |
| 1258 | + unsafe { Self::new_unchecked(res) } |
| 1259 | + } |
1207 | 1260 | };
|
1208 | 1261 |
|
1209 | 1262 | // Associated items for signed nonzero types only.
|
|
0 commit comments