1pub mod bits {
15 #[inline(always)]
20 pub fn sign_extend_leq8_to_i8(value: u8, width: u32) -> i8 {
21 (value.wrapping_shl(8 - width) as i8).wrapping_shr(8 - width)
25 }
26
27 #[inline(always)]
30 pub fn sign_extend_leq16_to_i16(value: u16, width: u32) -> i16 {
31 (value.wrapping_shl(16 - width) as i16).wrapping_shr(16 - width)
32 }
33
34 #[inline(always)]
37 pub fn sign_extend_leq32_to_i32(value: u32, width: u32) -> i32 {
38 (value.wrapping_shl(32 - width) as i32).wrapping_shr(32 - width)
39 }
40
41 #[inline(always)]
44 pub fn sign_extend_leq64_to_i64(value: u64, width: u32) -> i64 {
45 (value.wrapping_shl(64 - width) as i64).wrapping_shr(64 - width)
46 }
47
48 #[inline(always)]
50 pub fn mask_at(idx: u32) -> u8 {
51 debug_assert!(idx <= 7);
52 1 << idx
53 }
54
55 #[inline(always)]
57 pub fn mask_upper_eq(idx: u32) -> u8 {
58 debug_assert!(idx <= 7);
59 !((1 << idx) - 1)
60 }
61
62 #[inline(always)]
64 pub fn mask_upper(idx: u32) -> u8 {
65 debug_assert!(idx <= 7);
66 !((1 << idx) - 1) ^ (1 << idx)
67 }
68
69 #[inline(always)]
71 pub fn mask_lower_eq(idx: u32) -> u8 {
72 debug_assert!(idx <= 7);
73 ((1 << idx) - 1) ^ (1 << idx)
74 }
75
76 #[inline(always)]
78 pub fn mask_lower(idx: u32) -> u8 {
79 debug_assert!(idx <= 7);
80 (1 << idx) - 1
81 }
82
83 #[inline(always)]
86 pub fn mask_range(upper: u32, lower: u32) -> u8 {
87 debug_assert!(upper <= 8);
88 debug_assert!(lower <= 8);
89 ((0xff_u32 << upper) ^ (0xff_u32 << lower)) as u8
90 }
91
92 #[inline(always)]
94 pub fn trailing_ones_u8(value: u8) -> u32 {
95 (!value & value.wrapping_add(1)).trailing_zeros()
96 }
97
98 #[inline(always)]
100 pub fn trailing_ones_u16(value: u16) -> u32 {
101 (!value & value.wrapping_add(1)).trailing_zeros()
102 }
103
104 #[inline(always)]
106 pub fn trailing_ones_u32(value: u32) -> u32 {
107 (!value & value.wrapping_add(1)).trailing_zeros()
108 }
109
110 #[inline(always)]
112 pub fn trailing_ones_u64(value: u64) -> u32 {
113 (!value & value.wrapping_add(1)).trailing_zeros()
114 }
115
116 #[inline(always)]
119 pub fn contains_ones_byte_u16(value: u16) -> bool {
120 ((value & !value.wrapping_add(0x0101)) & 0x8080) != 0
121 }
122
123 #[inline(always)]
126 pub fn contains_ones_byte_u32(value: u32) -> bool {
127 ((value & !value.wrapping_add(0x0101_0101)) & 0x8080_8080) != 0
128 }
129
130 #[inline(always)]
133 pub fn contains_ones_byte_u64(value: u64) -> bool {
134 ((value & !value.wrapping_add(0x0101_0101_0101_0101)) & 0x8080_8080_8080_8080) != 0
135 }
136
137 #[test]
138 fn verify_trailing_ones() {
139 assert_eq!(trailing_ones_u32(0), 0);
140 assert_eq!(trailing_ones_u32(1), 1);
141 assert_eq!(trailing_ones_u32(2), 0);
142 assert_eq!(trailing_ones_u32(3), 2);
143 assert_eq!(trailing_ones_u32(0xf00f_7fff), 15);
144 assert_eq!(trailing_ones_u32(0xffff_ffff), 32);
145 }
146
147 #[test]
148 fn verify_masks() {
149 assert_eq!(mask_at(0), 0b0000_0001);
150 assert_eq!(mask_at(1), 0b0000_0010);
151 assert_eq!(mask_at(2), 0b0000_0100);
152 assert_eq!(mask_at(3), 0b0000_1000);
153 assert_eq!(mask_at(4), 0b0001_0000);
154 assert_eq!(mask_at(5), 0b0010_0000);
155 assert_eq!(mask_at(6), 0b0100_0000);
156 assert_eq!(mask_at(7), 0b1000_0000);
157
158 assert_eq!(mask_upper(0), 0b1111_1110);
159 assert_eq!(mask_upper(1), 0b1111_1100);
160 assert_eq!(mask_upper(2), 0b1111_1000);
161 assert_eq!(mask_upper(3), 0b1111_0000);
162 assert_eq!(mask_upper(4), 0b1110_0000);
163 assert_eq!(mask_upper(5), 0b1100_0000);
164 assert_eq!(mask_upper(6), 0b1000_0000);
165 assert_eq!(mask_upper(7), 0b0000_0000);
166
167 assert_eq!(mask_upper_eq(0), 0b1111_1111);
168 assert_eq!(mask_upper_eq(1), 0b1111_1110);
169 assert_eq!(mask_upper_eq(2), 0b1111_1100);
170 assert_eq!(mask_upper_eq(3), 0b1111_1000);
171 assert_eq!(mask_upper_eq(4), 0b1111_0000);
172 assert_eq!(mask_upper_eq(5), 0b1110_0000);
173 assert_eq!(mask_upper_eq(6), 0b1100_0000);
174 assert_eq!(mask_upper_eq(7), 0b1000_0000);
175
176 assert_eq!(mask_lower(0), 0b0000_0000);
177 assert_eq!(mask_lower(1), 0b0000_0001);
178 assert_eq!(mask_lower(2), 0b0000_0011);
179 assert_eq!(mask_lower(3), 0b0000_0111);
180 assert_eq!(mask_lower(4), 0b0000_1111);
181 assert_eq!(mask_lower(5), 0b0001_1111);
182 assert_eq!(mask_lower(6), 0b0011_1111);
183 assert_eq!(mask_lower(7), 0b0111_1111);
184
185 assert_eq!(mask_lower_eq(0), 0b0000_0001);
186 assert_eq!(mask_lower_eq(1), 0b0000_0011);
187 assert_eq!(mask_lower_eq(2), 0b0000_0111);
188 assert_eq!(mask_lower_eq(3), 0b0000_1111);
189 assert_eq!(mask_lower_eq(4), 0b0001_1111);
190 assert_eq!(mask_lower_eq(5), 0b0011_1111);
191 assert_eq!(mask_lower_eq(6), 0b0111_1111);
192 assert_eq!(mask_lower_eq(7), 0b1111_1111);
193
194 assert_eq!(mask_range(0, 0), 0b0000_0000);
195 assert_eq!(mask_range(1, 1), 0b0000_0000);
196 assert_eq!(mask_range(7, 7), 0b0000_0000);
197 assert_eq!(mask_range(1, 0), 0b0000_0001);
198 assert_eq!(mask_range(2, 0), 0b0000_0011);
199 assert_eq!(mask_range(7, 0), 0b0111_1111);
200 assert_eq!(mask_range(5, 2), 0b0001_1100);
201 assert_eq!(mask_range(7, 2), 0b0111_1100);
202 assert_eq!(mask_range(8, 2), 0b1111_1100);
203 }
204}
205
206pub mod clamp {
207 #[inline]
211 pub fn clamp_u8(val: u16) -> u8 {
212 if val & !0xff == 0 {
213 val as u8
214 }
215 else {
216 0xff
217 }
218 }
219
220 #[inline]
222 pub fn clamp_i8(val: i16) -> i8 {
223 if val.wrapping_add(0x80) & !0xff == 0 {
229 val as i8
230 }
231 else {
232 0x7f ^ val.wrapping_shr(15) as i8
241 }
242 }
243
244 #[inline]
246 pub fn clamp_u16(val: u32) -> u16 {
247 if val & !0xffff == 0 {
248 val as u16
249 }
250 else {
251 0xffff
252 }
253 }
254
255 #[inline]
257 pub fn clamp_i16(val: i32) -> i16 {
258 if val.wrapping_add(0x8000) & !0xffff == 0 {
259 val as i16
260 }
261 else {
262 0x7fff ^ val.wrapping_shr(31) as i16
263 }
264 }
265
266 #[inline]
268 pub fn clamp_u24(val: u32) -> u32 {
269 if val & !0x00ff_ffff == 0 {
270 val
271 }
272 else {
273 0x00ff_ffff
274 }
275 }
276
277 #[inline]
279 pub fn clamp_i24(val: i32) -> i32 {
280 if val.wrapping_add(0x0080_0000) & !0x00ff_ffff == 0 {
281 val
282 }
283 else {
284 0x007f_ffff ^ val.wrapping_shr(31)
285 }
286 }
287
288 #[inline]
290 pub fn clamp_u32(val: u64) -> u32 {
291 if val & !0xffff_ffff == 0 {
292 val as u32
293 }
294 else {
295 0xffff_ffff
296 }
297 }
298
299 #[inline]
301 pub fn clamp_i32(val: i64) -> i32 {
302 if val.wrapping_add(0x8000_0000) & !0xffff_ffff == 0 {
303 val as i32
304 }
305 else {
306 0x7fff_ffff ^ val.wrapping_shr(63) as i32
307 }
308 }
309
310 #[inline]
312 pub fn clamp_f32(val: f32) -> f32 {
313 let mut clamped = val;
317 clamped = if clamped > 1.0 { 1.0 } else { clamped };
318 clamped = if clamped < -1.0 { -1.0 } else { clamped };
319 clamped
320 }
321
322 #[inline]
324 pub fn clamp_f64(val: f64) -> f64 {
325 let mut clamped = val;
326 clamped = if clamped > 1.0 { 1.0 } else { clamped };
327 clamped = if clamped < -1.0 { -1.0 } else { clamped };
328 clamped
329 }
330
331 #[cfg(test)]
332 mod tests {
333 use super::*;
334 use std::{i16, i32, i64, i8, u16, u32, u64, u8};
335
336 #[test]
337 fn verify_clamp() {
338 assert_eq!(clamp_u8(256u16), u8::MAX);
339 assert_eq!(clamp_u8(u16::MAX), u8::MAX);
340
341 assert_eq!(clamp_i8(128i16), i8::MAX);
342 assert_eq!(clamp_i8(-129i16), i8::MIN);
343 assert_eq!(clamp_i8(i16::MAX), i8::MAX);
344 assert_eq!(clamp_i8(i16::MIN), i8::MIN);
345
346 assert_eq!(clamp_u16(65536u32), u16::MAX);
347 assert_eq!(clamp_u16(u32::MAX), u16::MAX);
348
349 assert_eq!(clamp_i16(32_768i32), i16::MAX);
350 assert_eq!(clamp_i16(-32_769i32), i16::MIN);
351 assert_eq!(clamp_i16(i32::MAX), i16::MAX);
352 assert_eq!(clamp_i16(i32::MIN), i16::MIN);
353
354 assert_eq!(clamp_u32(4_294_967_296u64), u32::MAX);
355 assert_eq!(clamp_u32(u64::MAX), u32::MAX);
356
357 assert_eq!(clamp_i32(2_147_483_648i64), i32::MAX);
358 assert_eq!(clamp_i32(-2_147_483_649i64), i32::MIN);
359 assert_eq!(clamp_i32(i64::MAX), i32::MAX);
360 assert_eq!(clamp_i32(i64::MIN), i32::MIN);
361
362 assert_eq!(clamp_f32(1.1), 1.0);
363 assert_eq!(clamp_f32(5.6), 1.0);
364 assert_eq!(clamp_f32(0.5), 0.5);
365 assert_eq!(clamp_f32(-1.1), -1.0);
366 assert_eq!(clamp_f32(-5.6), -1.0);
367 assert_eq!(clamp_f32(-0.5), -0.5);
368
369 assert_eq!(clamp_f64(1.1), 1.0);
370 assert_eq!(clamp_f64(5.6), 1.0);
371 assert_eq!(clamp_f64(0.5), 0.5);
372 assert_eq!(clamp_f64(-1.1), -1.0);
373 assert_eq!(clamp_f64(-5.6), -1.0);
374 assert_eq!(clamp_f64(-0.5), -0.5);
375 }
376 }
377}