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