Always const-eval the gcd in slice::align_to_offsets
This commit is contained in:
parent
333b920fee
commit
b5ee324d79
1 changed files with 6 additions and 37 deletions
|
@ -3474,44 +3474,13 @@ impl<T> [T] {
|
||||||
// Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>)
|
// Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>)
|
||||||
//
|
//
|
||||||
// Luckily since all this is constant-evaluated... performance here matters not!
|
// Luckily since all this is constant-evaluated... performance here matters not!
|
||||||
#[inline]
|
const fn gcd(a: usize, b: usize) -> usize {
|
||||||
fn gcd(a: usize, b: usize) -> usize {
|
if b == 0 { a } else { gcd(b, a % b) }
|
||||||
use crate::intrinsics;
|
|
||||||
// iterative stein’s algorithm
|
|
||||||
// We should still make this `const fn` (and revert to recursive algorithm if we do)
|
|
||||||
// because relying on llvm to consteval all this is… well, it makes me uncomfortable.
|
|
||||||
|
|
||||||
// SAFETY: `a` and `b` are checked to be non-zero values.
|
|
||||||
let (ctz_a, mut ctz_b) = unsafe {
|
|
||||||
if a == 0 {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
if b == 0 {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
(intrinsics::cttz_nonzero(a), intrinsics::cttz_nonzero(b))
|
|
||||||
};
|
|
||||||
let k = ctz_a.min(ctz_b);
|
|
||||||
let mut a = a >> ctz_a;
|
|
||||||
let mut b = b;
|
|
||||||
loop {
|
|
||||||
// remove all factors of 2 from b
|
|
||||||
b >>= ctz_b;
|
|
||||||
if a > b {
|
|
||||||
mem::swap(&mut a, &mut b);
|
|
||||||
}
|
|
||||||
b = b - a;
|
|
||||||
// SAFETY: `b` is checked to be non-zero.
|
|
||||||
unsafe {
|
|
||||||
if b == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ctz_b = intrinsics::cttz_nonzero(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a << k
|
|
||||||
}
|
}
|
||||||
let gcd: usize = gcd(mem::size_of::<T>(), mem::size_of::<U>());
|
|
||||||
|
// Explicitly wrap the function call in a const block so it gets
|
||||||
|
// constant-evaluated even in debug mode.
|
||||||
|
let gcd: usize = const { gcd(mem::size_of::<T>(), mem::size_of::<U>()) };
|
||||||
let ts: usize = mem::size_of::<U>() / gcd;
|
let ts: usize = mem::size_of::<U>() / gcd;
|
||||||
let us: usize = mem::size_of::<T>() / gcd;
|
let us: usize = mem::size_of::<T>() / gcd;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue