1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Count of leading zero bytes in a [`U512`].
use super::U512;
impl U512 {
/// Returns the number of leading zero bytes in the 512-bit value.
///
/// Counts full zero bytes from the most significant position.
/// Returns 64 for zero, 0 when the most significant byte is non-zero.
///
/// # Examples
///
/// ```
/// use cnfy_uint::u512::U512;
///
/// assert_eq!(U512::ZERO.leading_zero_bytes(), 64);
/// assert_eq!(U512::ONE.leading_zero_bytes(), 63);
/// ```
#[inline]
pub const fn leading_zero_bytes(&self) -> u32 {
if self.0[7] != 0 {
return self.0[7].leading_zeros() / 8;
}
if self.0[6] != 0 {
return 8 + self.0[6].leading_zeros() / 8;
}
if self.0[5] != 0 {
return 16 + self.0[5].leading_zeros() / 8;
}
if self.0[4] != 0 {
return 24 + self.0[4].leading_zeros() / 8;
}
if self.0[3] != 0 {
return 32 + self.0[3].leading_zeros() / 8;
}
if self.0[2] != 0 {
return 40 + self.0[2].leading_zeros() / 8;
}
if self.0[1] != 0 {
return 48 + self.0[1].leading_zeros() / 8;
}
if self.0[0] != 0 {
return 56 + self.0[0].leading_zeros() / 8;
}
64
}
}
#[cfg(test)]
mod ai_tests {
use super::*;
/// Zero has 64 leading zero bytes.
#[test]
fn zero() {
assert_eq!(U512::ZERO.leading_zero_bytes(), 64);
}
/// One has 63 leading zero bytes (only the last byte is non-zero).
#[test]
fn one() {
assert_eq!(U512::ONE.leading_zero_bytes(), 63);
}
/// Max value has no leading zero bytes.
#[test]
fn max() {
assert_eq!(U512::MAX.leading_zero_bytes(), 0);
}
/// Value with non-zero second limb.
#[test]
fn second_limb() {
assert_eq!(
U512::from_be_limbs([0, 1, 0, 0, 0, 0, 0, 0]).leading_zero_bytes(),
15,
);
}
/// Value with non-zero fifth limb.
#[test]
fn fifth_limb() {
assert_eq!(
U512::from_be_limbs([0, 0, 0, 0, 0x100, 0, 0, 0]).leading_zero_bytes(),
38,
);
}
/// Value filling first byte exactly.
#[test]
fn first_byte_full() {
assert_eq!(
U512::from_be_limbs([0xFF00000000000000, 0, 0, 0, 0, 0, 0, 0]).leading_zero_bytes(),
0,
);
}
/// LSB limb with small value.
#[test]
fn lsb_limb_small() {
assert_eq!(
U512::from_be_limbs([0, 0, 0, 0, 0, 0, 0, 0xFF]).leading_zero_bytes(),
63,
);
}
}