1use super::HeaplessBigInt;
16use crate::MachineWord;
17use const_num_traits::{
18 HighestOne, IsolateHighestOne, IsolateLowestOne, LowestOne, One, Personality, PrimBits,
19 WrappingSub, Zero,
20};
21
22impl<T, const CAP: usize, P: Personality> HighestOne for HeaplessBigInt<T, CAP, P>
23where
24 T: MachineWord,
25{
26 fn highest_one(self) -> Option<u32> {
27 let bl = self.bit_length();
29 if bl == 0 { None } else { Some(bl as u32 - 1) }
30 }
31}
32
33impl<T, const CAP: usize, P: Personality> LowestOne for HeaplessBigInt<T, CAP, P>
34where
35 T: MachineWord,
36{
37 fn lowest_one(self) -> Option<u32> {
38 if <Self as Zero>::is_zero(&self) {
39 None
40 } else {
41 Some(PrimBits::trailing_zeros(self))
42 }
43 }
44}
45
46impl<T, const CAP: usize, P: Personality> IsolateHighestOne for HeaplessBigInt<T, CAP, P>
47where
48 T: MachineWord,
49{
50 type Output = Self;
51 fn isolate_highest_one(self) -> Self {
52 match self.highest_one() {
53 None => self,
55 Some(pos) => {
56 <Self as One>::one().widened(core::cmp::max(1, self.len())) << (pos as usize)
57 }
58 }
59 }
60}
61
62impl<T, const CAP: usize, P: Personality> IsolateLowestOne for HeaplessBigInt<T, CAP, P>
63where
64 T: MachineWord,
65{
66 type Output = Self;
67 fn isolate_lowest_one(self) -> Self {
68 let neg = <Self as WrappingSub>::wrapping_sub(<Self as Zero>::zero(), self);
71 self & neg
72 }
73}
74
75impl<T, const CAP: usize, P: Personality> HighestOne for &HeaplessBigInt<T, CAP, P>
80where
81 T: MachineWord,
82{
83 fn highest_one(self) -> Option<u32> {
84 <HeaplessBigInt<T, CAP, P> as HighestOne>::highest_one(*self)
85 }
86}
87
88impl<T, const CAP: usize, P: Personality> LowestOne for &HeaplessBigInt<T, CAP, P>
89where
90 T: MachineWord,
91{
92 fn lowest_one(self) -> Option<u32> {
93 <HeaplessBigInt<T, CAP, P> as LowestOne>::lowest_one(*self)
94 }
95}
96
97impl<T, const CAP: usize, P: Personality> IsolateHighestOne for &HeaplessBigInt<T, CAP, P>
98where
99 T: MachineWord,
100{
101 type Output = HeaplessBigInt<T, CAP, P>;
102 fn isolate_highest_one(self) -> HeaplessBigInt<T, CAP, P> {
103 <HeaplessBigInt<T, CAP, P> as IsolateHighestOne>::isolate_highest_one(*self)
104 }
105}
106
107impl<T, const CAP: usize, P: Personality> IsolateLowestOne for &HeaplessBigInt<T, CAP, P>
108where
109 T: MachineWord,
110{
111 type Output = HeaplessBigInt<T, CAP, P>;
112 fn isolate_lowest_one(self) -> HeaplessBigInt<T, CAP, P> {
113 <HeaplessBigInt<T, CAP, P> as IsolateLowestOne>::isolate_lowest_one(*self)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::HeaplessBigInt;
120 use const_num_traits::{HighestOne, IsolateHighestOne, IsolateLowestOne, LowestOne};
121
122 type H = HeaplessBigInt<u8, 8>;
123
124 #[test]
125 fn indices() {
126 assert_eq!(HighestOne::highest_one(H::from(0u8)), None);
127 assert_eq!(HighestOne::highest_one(H::from(1u8)), Some(0));
128 assert_eq!(HighestOne::highest_one(H::from(0xB4u8)), Some(7));
129 assert_eq!(LowestOne::lowest_one(H::from(0u8)), None);
130 assert_eq!(LowestOne::lowest_one(H::from(0xB0u8)), Some(4));
131 assert_eq!(LowestOne::lowest_one(H::from(1u8)), Some(0));
132 }
133
134 #[test]
135 fn isolate_masks_and_width() {
136 let v = H::from(0xB4u8).widened(8);
138 let hi = IsolateHighestOne::isolate_highest_one(v);
139 assert_eq!(hi, H::from(0x80u8));
140 assert_eq!(hi.len(), 8);
141 let lo = IsolateLowestOne::isolate_lowest_one(v);
142 assert_eq!(lo, H::from(0x04u8));
143 assert_eq!(lo.len(), 8);
144
145 let z = H::new_zero_with_len(8);
147 assert_eq!(IsolateHighestOne::isolate_highest_one(z).len(), 8);
148 assert_eq!(IsolateLowestOne::isolate_lowest_one(z).len(), 8);
149
150 let z0 = H::new_zero_with_len(0);
153 assert_eq!(IsolateHighestOne::isolate_highest_one(z0).len(), 0);
154 assert_eq!(IsolateLowestOne::isolate_lowest_one(z0).len(), 0);
155 }
156
157 #[test]
159 fn by_ref_matches_value() {
160 let v = H::from(0xB4u8).widened(8);
161 let r = &v; assert_eq!(HighestOne::highest_one(r), HighestOne::highest_one(v));
163 assert_eq!(LowestOne::lowest_one(r), LowestOne::lowest_one(v));
164 assert_eq!(
165 IsolateHighestOne::isolate_highest_one(r),
166 IsolateHighestOne::isolate_highest_one(v)
167 );
168 assert_eq!(
169 IsolateLowestOne::isolate_lowest_one(r),
170 IsolateLowestOne::isolate_lowest_one(v)
171 );
172 }
173}