| 1 | #[cfg (feature = "public-test-deps" )] |
| 2 | pub use implementation::trailing_zeros; |
| 3 | #[cfg (not(feature = "public-test-deps" ))] |
| 4 | pub(crate) use implementation::trailing_zeros; |
| 5 | |
| 6 | mod implementation { |
| 7 | use crate::int::{CastInto, Int}; |
| 8 | |
| 9 | /// Returns number of trailing binary zeros in `x`. |
| 10 | #[allow (dead_code)] |
| 11 | pub fn trailing_zeros<T: Int + CastInto<u32> + CastInto<u16> + CastInto<u8>>(x: T) -> usize { |
| 12 | let mut x = x; |
| 13 | let mut r: u32 = 0; |
| 14 | let mut t: u32; |
| 15 | |
| 16 | const { assert!(T::BITS <= 64) }; |
| 17 | if T::BITS >= 64 { |
| 18 | r += ((CastInto::<u32>::cast(x) == 0) as u32) << 5; // if (x has no 32 small bits) t = 32 else 0 |
| 19 | x >>= r; // remove 32 zero bits |
| 20 | } |
| 21 | |
| 22 | if T::BITS >= 32 { |
| 23 | t = ((CastInto::<u16>::cast(x) == 0) as u32) << 4; // if (x has no 16 small bits) t = 16 else 0 |
| 24 | r += t; |
| 25 | x >>= t; // x = [0 - 0xFFFF] + higher garbage bits |
| 26 | } |
| 27 | |
| 28 | const { assert!(T::BITS >= 16) }; |
| 29 | t = ((CastInto::<u8>::cast(x) == 0) as u32) << 3; |
| 30 | x >>= t; // x = [0 - 0xFF] + higher garbage bits |
| 31 | r += t; |
| 32 | |
| 33 | let mut x: u8 = x.cast(); |
| 34 | |
| 35 | t = (((x & 0x0F) == 0) as u32) << 2; |
| 36 | x >>= t; // x = [0 - 0xF] + higher garbage bits |
| 37 | r += t; |
| 38 | |
| 39 | t = (((x & 0x3) == 0) as u32) << 1; |
| 40 | x >>= t; // x = [0 - 0x3] + higher garbage bits |
| 41 | r += t; |
| 42 | |
| 43 | x &= 3; |
| 44 | |
| 45 | r as usize + ((2 - (x >> 1) as usize) & (((x & 1) == 0) as usize).wrapping_neg()) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | intrinsics! { |
| 50 | /// Returns the number of trailing binary zeros in `x` (32 bit version). |
| 51 | pub extern "C" fn __ctzsi2(x: u32) -> usize { |
| 52 | trailing_zeros(x) |
| 53 | } |
| 54 | |
| 55 | /// Returns the number of trailing binary zeros in `x` (64 bit version). |
| 56 | pub extern "C" fn __ctzdi2(x: u64) -> usize { |
| 57 | trailing_zeros(x) |
| 58 | } |
| 59 | |
| 60 | /// Returns the number of trailing binary zeros in `x` (128 bit version). |
| 61 | pub extern "C" fn __ctzti2(x: u128) -> usize { |
| 62 | let lo = x as u64; |
| 63 | if lo == 0 { |
| 64 | 64 + __ctzdi2((x >> 64) as u64) |
| 65 | } else { |
| 66 | __ctzdi2(lo) |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |