1use crate::Integer;
2use core::mem;
3use num_traits::{checked_pow, PrimInt};
45/// Provides methods to compute an integer's square root, cube root,
6/// and arbitrary `n`th root.
7pub trait Roots: Integer {
8/// Returns the truncated principal `n`th root of an integer
9 /// -- `if x >= 0 { ⌊ⁿ√x⌋ } else { ⌈ⁿ√x⌉ }`
10 ///
11 /// This is solving for `r` in `rⁿ = x`, rounding toward zero.
12 /// If `x` is positive, the result will satisfy `rⁿ ≤ x < (r+1)ⁿ`.
13 /// If `x` is negative and `n` is odd, then `(r-1)ⁿ < x ≤ rⁿ`.
14 ///
15 /// # Panics
16 ///
17 /// Panics if `n` is zero:
18 ///
19 /// ```should_panic
20 /// # use num_integer::Roots;
21 /// println!("can't compute ⁰√x : {}", 123.nth_root(0));
22 /// ```
23 ///
24 /// or if `n` is even and `self` is negative:
25 ///
26 /// ```should_panic
27 /// # use num_integer::Roots;
28 /// println!("no imaginary numbers... {}", (-1).nth_root(10));
29 /// ```
30 ///
31 /// # Examples
32 ///
33 /// ```
34 /// use num_integer::Roots;
35 ///
36 /// let x: i32 = 12345;
37 /// assert_eq!(x.nth_root(1), x);
38 /// assert_eq!(x.nth_root(2), x.sqrt());
39 /// assert_eq!(x.nth_root(3), x.cbrt());
40 /// assert_eq!(x.nth_root(4), 10);
41 /// assert_eq!(x.nth_root(13), 2);
42 /// assert_eq!(x.nth_root(14), 1);
43 /// assert_eq!(x.nth_root(std::u32::MAX), 1);
44 ///
45 /// assert_eq!(std::i32::MAX.nth_root(30), 2);
46 /// assert_eq!(std::i32::MAX.nth_root(31), 1);
47 /// assert_eq!(std::i32::MIN.nth_root(31), -2);
48 /// assert_eq!((std::i32::MIN + 1).nth_root(31), -1);
49 ///
50 /// assert_eq!(std::u32::MAX.nth_root(31), 2);
51 /// assert_eq!(std::u32::MAX.nth_root(32), 1);
52 /// ```
53fn nth_root(&self, n: u32) -> Self;
5455/// Returns the truncated principal square root of an integer -- `⌊√x⌋`
56 ///
57 /// This is solving for `r` in `r² = x`, rounding toward zero.
58 /// The result will satisfy `r² ≤ x < (r+1)²`.
59 ///
60 /// # Panics
61 ///
62 /// Panics if `self` is less than zero:
63 ///
64 /// ```should_panic
65 /// # use num_integer::Roots;
66 /// println!("no imaginary numbers... {}", (-1).sqrt());
67 /// ```
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use num_integer::Roots;
73 ///
74 /// let x: i32 = 12345;
75 /// assert_eq!((x * x).sqrt(), x);
76 /// assert_eq!((x * x + 1).sqrt(), x);
77 /// assert_eq!((x * x - 1).sqrt(), x - 1);
78 /// ```
79#[inline]
80fn sqrt(&self) -> Self {
81self.nth_root(2)
82 }
8384/// Returns the truncated principal cube root of an integer --
85 /// `if x >= 0 { ⌊∛x⌋ } else { ⌈∛x⌉ }`
86 ///
87 /// This is solving for `r` in `r³ = x`, rounding toward zero.
88 /// If `x` is positive, the result will satisfy `r³ ≤ x < (r+1)³`.
89 /// If `x` is negative, then `(r-1)³ < x ≤ r³`.
90 ///
91 /// # Examples
92 ///
93 /// ```
94 /// use num_integer::Roots;
95 ///
96 /// let x: i32 = 1234;
97 /// assert_eq!((x * x * x).cbrt(), x);
98 /// assert_eq!((x * x * x + 1).cbrt(), x);
99 /// assert_eq!((x * x * x - 1).cbrt(), x - 1);
100 ///
101 /// assert_eq!((-(x * x * x)).cbrt(), -x);
102 /// assert_eq!((-(x * x * x + 1)).cbrt(), -x);
103 /// assert_eq!((-(x * x * x - 1)).cbrt(), -(x - 1));
104 /// ```
105#[inline]
106fn cbrt(&self) -> Self {
107self.nth_root(3)
108 }
109}
110111/// Returns the truncated principal square root of an integer --
112/// see [Roots::sqrt](trait.Roots.html#method.sqrt).
113#[inline]
114pub fn sqrt<T: Roots>(x: T) -> T {
115x.sqrt()
116}
117118/// Returns the truncated principal cube root of an integer --
119/// see [Roots::cbrt](trait.Roots.html#method.cbrt).
120#[inline]
121pub fn cbrt<T: Roots>(x: T) -> T {
122x.cbrt()
123}
124125/// Returns the truncated principal `n`th root of an integer --
126/// see [Roots::nth_root](trait.Roots.html#tymethod.nth_root).
127#[inline]
128pub fn nth_root<T: Roots>(x: T, n: u32) -> T {
129x.nth_root(n)
130}
131132macro_rules! signed_roots {
133 ($T:ty, $U:ty) => {
134impl Roots for $T {
135#[inline]
136fn nth_root(&self, n: u32) -> Self {
137if *self >= 0 {
138 (*self as $U).nth_root(n) as Self
139} else {
140assert!(n.is_odd(), "even roots of a negative are imaginary");
141 -((self.wrapping_neg() as $U).nth_root(n) as Self)
142 }
143 }
144145#[inline]
146fn sqrt(&self) -> Self {
147assert!(*self >= 0, "the square root of a negative is imaginary");
148 (*self as $U).sqrt() as Self
149}
150151#[inline]
152fn cbrt(&self) -> Self {
153if *self >= 0 {
154 (*self as $U).cbrt() as Self
155} else {
156 -((self.wrapping_neg() as $U).cbrt() as Self)
157 }
158 }
159 }
160 };
161}
162163impl Roots for i8 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as u8).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as u8).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as u8).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as u8).cbrt() as Self
} else { -((self.wrapping_neg() as u8).cbrt() as Self) }
}
}signed_roots!(i8, u8);
164impl Roots for i16 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as u16).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as u16).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as u16).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as u16).cbrt() as Self
} else { -((self.wrapping_neg() as u16).cbrt() as Self) }
}
}signed_roots!(i16, u16);
165impl Roots for i32 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as u32).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as u32).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as u32).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as u32).cbrt() as Self
} else { -((self.wrapping_neg() as u32).cbrt() as Self) }
}
}signed_roots!(i32, u32);
166impl Roots for i64 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as u64).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as u64).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as u64).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as u64).cbrt() as Self
} else { -((self.wrapping_neg() as u64).cbrt() as Self) }
}
}signed_roots!(i64, u64);
167impl Roots for i128 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as u128).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as u128).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as u128).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as u128).cbrt() as Self
} else { -((self.wrapping_neg() as u128).cbrt() as Self) }
}
}signed_roots!(i128, u128);
168impl Roots for isize {
#[inline]
fn nth_root(&self, n: u32) -> Self {
if *self >= 0 {
(*self as usize).nth_root(n) as Self
} else {
if !n.is_odd() {
::core::panicking::panic("even roots of a negative are imaginary")
};
-((self.wrapping_neg() as usize).nth_root(n) as Self)
}
}
#[inline]
fn sqrt(&self) -> Self {
if !(*self >= 0) {
::core::panicking::panic("the square root of a negative is imaginary")
};
(*self as usize).sqrt() as Self
}
#[inline]
fn cbrt(&self) -> Self {
if *self >= 0 {
(*self as usize).cbrt() as Self
} else { -((self.wrapping_neg() as usize).cbrt() as Self) }
}
}signed_roots!(isize, usize);
169170#[inline]
171fn fixpoint<T, F>(mut x: T, f: F) -> T
172where
173T: Integer + Copy,
174 F: Fn(T) -> T,
175{
176let mut xn = f(x);
177while x < xn {
178 x = xn;
179 xn = f(x);
180 }
181while x > xn {
182 x = xn;
183 xn = f(x);
184 }
185x186}
187188#[inline]
189fn bits<T>() -> u32 {
1908 * mem::size_of::<T>() as u32191}
192193#[inline]
194fn log2<T: PrimInt>(x: T) -> u32 {
195if true {
if !(x > T::zero()) {
::core::panicking::panic("assertion failed: x > T::zero()")
};
};debug_assert!(x > T::zero());
196bits::<T>() - 1 - x.leading_zeros()
197}
198199macro_rules! unsigned_roots {
200 ($T:ident) => {
201impl Roots for $T {
202#[inline]
203fn nth_root(&self, n: u32) -> Self {
204fn go(a: $T, n: u32) -> $T {
205// Specialize small roots
206match n {
2070 => panic!("can't find a root of degree 0!"),
2081 => return a,
2092 => return a.sqrt(),
2103 => return a.cbrt(),
211_ => (),
212 }
213214// The root of values less than 2ⁿ can only be 0 or 1.
215if bits::<$T>() <= n || a < (1 << n) {
216return (a > 0) as $T;
217 }
218219if bits::<$T>() > 64 {
220// 128-bit division is slow, so do a bitwise `nth_root` until it's small enough.
221return if a <= core::u64::MAX as $T {
222 (a as u64).nth_root(n) as $T
223} else {
224let lo = (a >> n).nth_root(n) << 1;
225let hi = lo + 1;
226// 128-bit `checked_mul` also involves division, but we can't always
227 // compute `hiⁿ` without risking overflow. Try to avoid it though...
228if hi.next_power_of_two().trailing_zeros() * n >= bits::<$T>() {
229match checked_pow(hi, n as usize) {
230Some(x) if x <= a => hi,
231_ => lo,
232 }
233 } else {
234if hi.pow(n) <= a {
235 hi
236 } else {
237 lo
238 }
239 }
240 };
241 }
242243#[cfg(feature = "std")]
244 #[inline]
245fn guess(x: $T, n: u32) -> $T {
246// for smaller inputs, `f64` doesn't justify its cost.
247if bits::<$T>() <= 32 || x <= core::u32::MAX as $T {
2481 << ((log2(x) + n - 1) / n)
249 } else {
250 ((x as f64).ln() / f64::from(n)).exp() as $T
251}
252 }
253254#[cfg(not(feature = "std"))]
255 #[inline]
256fn guess(x: $T, n: u32) -> $T {
2571 << ((log2(x) + n - 1) / n)
258 }
259260// https://en.wikipedia.org/wiki/Nth_root_algorithm
261let n1 = n - 1;
262let next = |x: $T| {
263let y = match checked_pow(x, n1 as usize) {
264Some(ax) => a / ax,
265None => 0,
266 };
267 (y + x * n1 as $T) / n as $T
268};
269 fixpoint(guess(a, n), next)
270 }
271 go(*self, n)
272 }
273274#[inline]
275fn sqrt(&self) -> Self {
276fn go(a: $T) -> $T {
277if bits::<$T>() > 64 {
278// 128-bit division is slow, so do a bitwise `sqrt` until it's small enough.
279return if a <= core::u64::MAX as $T {
280 (a as u64).sqrt() as $T
281} else {
282let lo = (a >> 2u32).sqrt() << 1;
283let hi = lo + 1;
284if hi * hi <= a {
285 hi
286 } else {
287 lo
288 }
289 };
290 }
291292if a < 4 {
293return (a > 0) as $T;
294 }
295296#[cfg(feature = "std")]
297 #[inline]
298fn guess(x: $T) -> $T {
299 (x as f64).sqrt() as $T
300}
301302#[cfg(not(feature = "std"))]
303 #[inline]
304fn guess(x: $T) -> $T {
3051 << ((log2(x) + 1) / 2)
306 }
307308// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
309let next = |x: $T| (a / x + x) >> 1;
310 fixpoint(guess(a), next)
311 }
312 go(*self)
313 }
314315#[inline]
316fn cbrt(&self) -> Self {
317fn go(a: $T) -> $T {
318if bits::<$T>() > 64 {
319// 128-bit division is slow, so do a bitwise `cbrt` until it's small enough.
320return if a <= core::u64::MAX as $T {
321 (a as u64).cbrt() as $T
322} else {
323let lo = (a >> 3u32).cbrt() << 1;
324let hi = lo + 1;
325if hi * hi * hi <= a {
326 hi
327 } else {
328 lo
329 }
330 };
331 }
332333if bits::<$T>() <= 32 {
334// Implementation based on Hacker's Delight `icbrt2`
335let mut x = a;
336let mut y2 = 0;
337let mut y = 0;
338let smax = bits::<$T>() / 3;
339for s in (0..smax + 1).rev() {
340let s = s * 3;
341 y2 *= 4;
342 y *= 2;
343let b = 3 * (y2 + y) + 1;
344if x >> s >= b {
345 x -= b << s;
346 y2 += 2 * y + 1;
347 y += 1;
348 }
349 }
350return y;
351 }
352353if a < 8 {
354return (a > 0) as $T;
355 }
356if a <= core::u32::MAX as $T {
357return (a as u32).cbrt() as $T;
358 }
359360#[cfg(feature = "std")]
361 #[inline]
362fn guess(x: $T) -> $T {
363 (x as f64).cbrt() as $T
364}
365366#[cfg(not(feature = "std"))]
367 #[inline]
368fn guess(x: $T) -> $T {
3691 << ((log2(x) + 2) / 3)
370 }
371372// https://en.wikipedia.org/wiki/Cube_root#Numerical_methods
373let next = |x: $T| (a / (x * x) + x * 2) / 3;
374 fixpoint(guess(a), next)
375 }
376 go(*self)
377 }
378 }
379 };
380}
381382impl Roots for u8 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: u8, n: u32) -> u8 {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<u8>() <= n || a < (1 << n) { return (a > 0) as u8; }
if bits::<u8>() > 64 {
return if a <= core::u64::MAX as u8 {
(a as u64).nth_root(n) as u8
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<u8>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: u8, n: u32) -> u8 {
if bits::<u8>() <= 32 || x <= core::u32::MAX as u8 {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as u8 }
}
let n1 = n - 1;
let next =
|x: u8|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as u8) / n as u8
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: u8) -> u8 {
if bits::<u8>() > 64 {
return if a <= core::u64::MAX as u8 {
(a as u64).sqrt() as u8
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as u8; }
#[inline]
fn guess(x: u8) -> u8 { (x as f64).sqrt() as u8 }
let next = |x: u8| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: u8) -> u8 {
if bits::<u8>() > 64 {
return if a <= core::u64::MAX as u8 {
(a as u64).cbrt() as u8
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<u8>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<u8>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as u8; }
if a <= core::u32::MAX as u8 { return (a as u32).cbrt() as u8; }
#[inline]
fn guess(x: u8) -> u8 { (x as f64).cbrt() as u8 }
let next = |x: u8| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(u8);
383impl Roots for u16 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: u16, n: u32) -> u16 {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<u16>() <= n || a < (1 << n) { return (a > 0) as u16; }
if bits::<u16>() > 64 {
return if a <= core::u64::MAX as u16 {
(a as u64).nth_root(n) as u16
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<u16>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: u16, n: u32) -> u16 {
if bits::<u16>() <= 32 || x <= core::u32::MAX as u16 {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as u16 }
}
let n1 = n - 1;
let next =
|x: u16|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as u16) / n as u16
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: u16) -> u16 {
if bits::<u16>() > 64 {
return if a <= core::u64::MAX as u16 {
(a as u64).sqrt() as u16
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as u16; }
#[inline]
fn guess(x: u16) -> u16 { (x as f64).sqrt() as u16 }
let next = |x: u16| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: u16) -> u16 {
if bits::<u16>() > 64 {
return if a <= core::u64::MAX as u16 {
(a as u64).cbrt() as u16
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<u16>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<u16>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as u16; }
if a <= core::u32::MAX as u16 { return (a as u32).cbrt() as u16; }
#[inline]
fn guess(x: u16) -> u16 { (x as f64).cbrt() as u16 }
let next = |x: u16| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(u16);
384impl Roots for u32 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: u32, n: u32) -> u32 {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<u32>() <= n || a < (1 << n) { return (a > 0) as u32; }
if bits::<u32>() > 64 {
return if a <= core::u64::MAX as u32 {
(a as u64).nth_root(n) as u32
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<u32>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: u32, n: u32) -> u32 {
if bits::<u32>() <= 32 || x <= core::u32::MAX as u32 {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as u32 }
}
let n1 = n - 1;
let next =
|x: u32|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as u32) / n as u32
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: u32) -> u32 {
if bits::<u32>() > 64 {
return if a <= core::u64::MAX as u32 {
(a as u64).sqrt() as u32
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as u32; }
#[inline]
fn guess(x: u32) -> u32 { (x as f64).sqrt() as u32 }
let next = |x: u32| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: u32) -> u32 {
if bits::<u32>() > 64 {
return if a <= core::u64::MAX as u32 {
(a as u64).cbrt() as u32
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<u32>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<u32>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as u32; }
if a <= core::u32::MAX as u32 { return (a as u32).cbrt() as u32; }
#[inline]
fn guess(x: u32) -> u32 { (x as f64).cbrt() as u32 }
let next = |x: u32| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(u32);
385impl Roots for u64 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: u64, n: u32) -> u64 {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<u64>() <= n || a < (1 << n) { return (a > 0) as u64; }
if bits::<u64>() > 64 {
return if a <= core::u64::MAX as u64 {
(a as u64).nth_root(n) as u64
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<u64>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: u64, n: u32) -> u64 {
if bits::<u64>() <= 32 || x <= core::u32::MAX as u64 {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as u64 }
}
let n1 = n - 1;
let next =
|x: u64|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as u64) / n as u64
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: u64) -> u64 {
if bits::<u64>() > 64 {
return if a <= core::u64::MAX as u64 {
(a as u64).sqrt() as u64
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as u64; }
#[inline]
fn guess(x: u64) -> u64 { (x as f64).sqrt() as u64 }
let next = |x: u64| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: u64) -> u64 {
if bits::<u64>() > 64 {
return if a <= core::u64::MAX as u64 {
(a as u64).cbrt() as u64
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<u64>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<u64>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as u64; }
if a <= core::u32::MAX as u64 { return (a as u32).cbrt() as u64; }
#[inline]
fn guess(x: u64) -> u64 { (x as f64).cbrt() as u64 }
let next = |x: u64| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(u64);
386impl Roots for u128 {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: u128, n: u32) -> u128 {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<u128>() <= n || a < (1 << n) { return (a > 0) as u128; }
if bits::<u128>() > 64 {
return if a <= core::u64::MAX as u128 {
(a as u64).nth_root(n) as u128
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<u128>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: u128, n: u32) -> u128 {
if bits::<u128>() <= 32 || x <= core::u32::MAX as u128 {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as u128 }
}
let n1 = n - 1;
let next =
|x: u128|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as u128) / n as u128
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: u128) -> u128 {
if bits::<u128>() > 64 {
return if a <= core::u64::MAX as u128 {
(a as u64).sqrt() as u128
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as u128; }
#[inline]
fn guess(x: u128) -> u128 { (x as f64).sqrt() as u128 }
let next = |x: u128| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: u128) -> u128 {
if bits::<u128>() > 64 {
return if a <= core::u64::MAX as u128 {
(a as u64).cbrt() as u128
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<u128>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<u128>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as u128; }
if a <= core::u32::MAX as u128 {
return (a as u32).cbrt() as u128;
}
#[inline]
fn guess(x: u128) -> u128 { (x as f64).cbrt() as u128 }
let next = |x: u128| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(u128);
387impl Roots for usize {
#[inline]
fn nth_root(&self, n: u32) -> Self {
fn go(a: usize, n: u32) -> usize {
match n {
0 =>
::core::panicking::panic("can't find a root of degree 0!"),
1 => return a,
2 => return a.sqrt(),
3 => return a.cbrt(),
_ => (),
}
if bits::<usize>() <= n || a < (1 << n) {
return (a > 0) as usize;
}
if bits::<usize>() > 64 {
return if a <= core::u64::MAX as usize {
(a as u64).nth_root(n) as usize
} else {
let lo = (a >> n).nth_root(n) << 1;
let hi = lo + 1;
if hi.next_power_of_two().trailing_zeros() * n >=
bits::<usize>() {
match checked_pow(hi, n as usize) {
Some(x) if x <= a => hi,
_ => lo,
}
} else { if hi.pow(n) <= a { hi } else { lo } }
};
}
#[inline]
fn guess(x: usize, n: u32) -> usize {
if bits::<usize>() <= 32 || x <= core::u32::MAX as usize {
1 << ((log2(x) + n - 1) / n)
} else { ((x as f64).ln() / f64::from(n)).exp() as usize }
}
let n1 = n - 1;
let next =
|x: usize|
{
let y =
match checked_pow(x, n1 as usize) {
Some(ax) => a / ax,
None => 0,
};
(y + x * n1 as usize) / n as usize
};
fixpoint(guess(a, n), next)
}
go(*self, n)
}
#[inline]
fn sqrt(&self) -> Self {
fn go(a: usize) -> usize {
if bits::<usize>() > 64 {
return if a <= core::u64::MAX as usize {
(a as u64).sqrt() as usize
} else {
let lo = (a >> 2u32).sqrt() << 1;
let hi = lo + 1;
if hi * hi <= a { hi } else { lo }
};
}
if a < 4 { return (a > 0) as usize; }
#[inline]
fn guess(x: usize) -> usize { (x as f64).sqrt() as usize }
let next = |x: usize| (a / x + x) >> 1;
fixpoint(guess(a), next)
}
go(*self)
}
#[inline]
fn cbrt(&self) -> Self {
fn go(a: usize) -> usize {
if bits::<usize>() > 64 {
return if a <= core::u64::MAX as usize {
(a as u64).cbrt() as usize
} else {
let lo = (a >> 3u32).cbrt() << 1;
let hi = lo + 1;
if hi * hi * hi <= a { hi } else { lo }
};
}
if bits::<usize>() <= 32 {
let mut x = a;
let mut y2 = 0;
let mut y = 0;
let smax = bits::<usize>() / 3;
for s in (0..smax + 1).rev() {
let s = s * 3;
y2 *= 4;
y *= 2;
let b = 3 * (y2 + y) + 1;
if x >> s >= b { x -= b << s; y2 += 2 * y + 1; y += 1; }
}
return y;
}
if a < 8 { return (a > 0) as usize; }
if a <= core::u32::MAX as usize {
return (a as u32).cbrt() as usize;
}
#[inline]
fn guess(x: usize) -> usize { (x as f64).cbrt() as usize }
let next = |x: usize| (a / (x * x) + x * 2) / 3;
fixpoint(guess(a), next)
}
go(*self)
}
}unsigned_roots!(usize);