1use crate::Limb;
7
8#[cfg_attr(not(feature = "alloc"), allow(dead_code))]
10#[inline(always)]
11pub(crate) const fn from_bytes(nbytes: usize) -> u32 {
12 mul(nbytes, 8)
13}
14
15#[inline(always)]
17pub(crate) const fn from_limbs(nlimbs: usize) -> u32 {
18 mul(nlimbs, Limb::BITS)
19}
20
21#[cfg_attr(not(feature = "alloc"), allow(dead_code))]
24#[inline(always)]
25pub(crate) const fn to_bytes(nbits: u32) -> usize {
26 u32_to_usize(div_ceil_pow2(nbits, 3))
27}
28
29#[inline(always)]
32pub(crate) const fn to_limbs(nbits: u32) -> usize {
33 u32_to_usize(to_limbs_u32(nbits))
34}
35
36#[inline(always)]
38pub(crate) const fn to_limbs_u32(nbits: u32) -> u32 {
39 div_ceil_pow2(nbits, Limb::LOG2_BITS)
40}
41
42#[inline(always)]
44const fn div_ceil_pow2(n: u32, log2: u32) -> u32 {
45 let mask = (1 << log2) - 1;
46 (n >> log2).wrapping_add(((n & mask).wrapping_add(mask)) >> log2)
47}
48
49#[inline(always)]
50const fn u32_to_usize(n: u32) -> usize {
51 const {
52 assert!(usize::BITS >= u32::BITS, "usize too small");
54 }
55
56 n as usize
57}
58
59#[allow(
60 clippy::cast_possible_truncation,
61 reason = "assertion ensures panic instead of truncation"
62)]
63#[inline(always)]
64const fn usize_to_u32(n: usize) -> u32 {
65 debug_assert!(n < u32_to_usize(u32::MAX), "u32 overflow");
66 n as u32
67}
68
69#[inline(always)]
70const fn mul(size: usize, n: u32) -> u32 {
71 if cfg!(debug_assertions) {
72 usize_to_u32(size).checked_mul(n).expect("u32 overflow")
73 } else {
74 usize_to_u32(size) * n
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 #[test]
81 fn from_bytes() {
82 assert_eq!(super::from_bytes(0), 0);
83 assert_eq!(super::from_bytes(1), 8);
84 assert_eq!(super::from_bytes(2), 16);
85 }
86
87 #[test]
88 fn to_bytes() {
89 assert_eq!(super::to_bytes(0), 0);
90 assert_eq!(super::to_bytes(1), 1);
91 assert_eq!(super::to_bytes(8), 1);
92 assert_eq!(super::to_bytes(9), 2);
93 assert_eq!(super::to_bytes(16), 2);
94 assert_eq!(super::to_bytes(17), 3);
95 }
96
97 #[test]
98 fn to_limbs() {
99 use crate::Limb;
100
101 assert_eq!(super::to_limbs(0), 0);
102 assert_eq!(super::to_limbs(1), 1);
103 assert_eq!(super::to_limbs(Limb::BITS), 1);
104 assert_eq!(super::to_limbs(Limb::BITS + 1), 2);
105 assert_eq!(
106 super::to_limbs(u32::MAX),
107 u32::MAX.div_ceil(Limb::BITS) as usize
108 );
109 }
110}