ospf_rust_math/algebra/operator/algorithmic/
trailing_zeros.rs1use std::borrow::Borrow;
2use std::ops::{BitOr, ShrAssign};
3
4use crate::algebra::concept::{Arithmetic, SemiArithmetic};
5
6pub trait TrailingZeros {
7 fn trailing_zeros(self) -> usize;
8}
9
10default impl<T: Arithmetic + ShrAssign<usize>> TrailingZeros for T
11where
12 for<'a> &'a T: BitOr<&'a T, Output = T>,
13{
14 fn trailing_zeros(mut self) -> usize {
15 if &self == T::ZERO {
16 return size_of::<T>();
17 }
18
19 let mut counter = 0;
20 while &(&self | T::ONE) == T::ZERO {
21 counter += 1;
22 self >>= 1;
23 }
24 counter
25 }
26}
27
28macro_rules! int_trailing_zeros_impl {
29 ($($type:ident)*) => ($(
30 impl TrailingZeros for $type {
31 fn trailing_zeros(self) -> usize {
32 <$type>::trailing_zeros(self) as usize
33 }
34 }
35
36 impl TrailingZeros for &$type {
37 fn trailing_zeros(self) -> usize {
38 <$type>::trailing_zeros(*self) as usize
39 }
40 }
41 )*);
42}
43int_trailing_zeros_impl! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
44
45#[cfg(test)]
46mod tests {
47 use std::fmt::Debug;
48 use std::ops::Mul;
49
50 use crate::algebra::concept::Integer;
51
52 use super::*;
53
54 fn test_int<T: Integer + TrailingZeros + Debug>()
55 where
56 for<'a> &'a T: Mul<Output = T>,
57 {
58 assert_eq!(
59 T::ZERO.clone().trailing_zeros(),
60 size_of::<T>() * 8
61 );
62 assert_eq!(T::ONE.clone().trailing_zeros(), 0);
63 assert_eq!(T::TWO.clone().trailing_zeros(), 1);
64 assert_eq!(T::THREE.clone().trailing_zeros(), 0);
65 assert_eq!(T::FIVE.clone().trailing_zeros(), 0);
66 assert_eq!(T::TEN.clone().trailing_zeros(), 1);
67 assert_eq!((T::TWO * T::TEN).trailing_zeros(), 2);
68 }
69
70 #[test]
71 fn test() {
72 test_int::<i8>();
73 test_int::<i16>();
74 test_int::<i32>();
75 test_int::<i64>();
76 test_int::<i128>();
77 test_int::<u8>();
78 test_int::<u16>();
79 test_int::<u32>();
80 test_int::<u64>();
81 test_int::<u128>();
82 }
83}