Skip to content

Commit 9133458

Browse files
committed
Add isqrt to NonZero<uN>
1 parent f626162 commit 9133458

File tree

3 files changed

+56
-31
lines changed

3 files changed

+56
-31
lines changed

library/core/src/num/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#![stable(feature = "rust1", since = "1.0.0")]
44

55
use crate::ascii;
6-
use crate::hint;
76
use crate::intrinsics;
87
use crate::mem;
98
use crate::str::FromStr;

library/core/src/num/nonzero.rs

+53
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::cmp::Ordering;
44
use crate::fmt;
55
use crate::hash::{Hash, Hasher};
6+
use crate::hint;
67
use crate::intrinsics;
78
use crate::marker::{Freeze, StructuralPartialEq};
89
use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
@@ -1204,6 +1205,58 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
12041205

12051206
intrinsics::ctpop(self.get()) < 2
12061207
}
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+
}
12071260
};
12081261

12091262
// Associated items for signed nonzero types only.

library/core/src/num/uint_macros.rs

+3-30
Original file line numberDiff line numberDiff line change
@@ -2579,37 +2579,10 @@ macro_rules! uint_impl {
25792579
without modifying the original"]
25802580
#[inline]
25812581
pub const fn isqrt(self) -> Self {
2582-
if self < 2 {
2583-
return self;
2582+
match NonZero::new(self) {
2583+
Some(x) => x.isqrt().get(),
2584+
None => 0,
25842585
}
2585-
2586-
// The algorithm is based on the one presented in
2587-
// <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)>
2588-
// which cites as source the following C code:
2589-
// <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>.
2590-
2591-
let mut op = self;
2592-
let mut res = 0;
2593-
let mut one = 1 << (self.ilog2() & !1);
2594-
2595-
while one != 0 {
2596-
if op >= res + one {
2597-
op -= res + one;
2598-
res = (res >> 1) + one;
2599-
} else {
2600-
res >>= 1;
2601-
}
2602-
one >>= 2;
2603-
}
2604-
2605-
// SAFETY: the result is positive and fits in an integer with half as many bits.
2606-
// Inform the optimizer about it.
2607-
unsafe {
2608-
hint::assert_unchecked(0 < res);
2609-
hint::assert_unchecked(res < 1 << (Self::BITS / 2));
2610-
}
2611-
2612-
res
26132586
}
26142587

26152588
/// Performs Euclidean division.

0 commit comments

Comments
 (0)