MCPcopy Create free account
hub / github.com/SoftbearStudios/bitcode / unpack_arithmetic_less_than

Function unpack_arithmetic_less_than

src/pack.rs:253–336  ·  view source on GitHub ↗

`FACTOR_POW_DIVISOR == (FACTOR as usize).pow(factor_to_divisor:: () as u32)` but as a constant.

(
        input: &mut &[u8],
        length: usize,
        out: &mut Vec<u8>,
    )

Source from the content-addressed store, hash-verified

251
252 /// `FACTOR_POW_DIVISOR == (FACTOR as usize).pow(factor_to_divisor::<FACTOR>() as u32)` but as a constant.
253 fn unpack_arithmetic_less_than<
254 const N: usize,
255 const HISTOGRAM: usize,
256 const FACTOR: usize,
257 const FACTOR_POW_DIVISOR: usize,
258 >(
259 input: &mut &[u8],
260 length: usize,
261 out: &mut Vec<u8>,
262 ) -> Result<[usize; HISTOGRAM]> {
263 assert!(HISTOGRAM == N || HISTOGRAM == 0);
264 assert!(FACTOR >= 2 && FACTOR >= N);
265 let divisor = factor_to_divisor::<FACTOR>();
266 assert_eq!(FACTOR.pow(divisor as u32), FACTOR_POW_DIVISOR);
267
268 let original_input = *input;
269 unpack_arithmetic::<FACTOR>(input, length, out)?;
270 if HISTOGRAM == 0 {
271 check_less_than::<N, HISTOGRAM, FACTOR>(out)
272 } else {
273 let floor = length / divisor;
274 let ceil = crate::nightly::div_ceil_usize(length, divisor);
275 let whole = &original_input[..floor];
276
277 // Can only `partial_with_garbage % FACTOR` partial_length times as the rest are undefined garbage.
278 let partial_length = length - floor * divisor;
279 let partial_with_garbage = original_input[floor..ceil].first().copied();
280
281 // POPCNT is much faster than histogram.
282 let histogram = if FACTOR == 2 {
283 assert_eq!(N, 2);
284 assert_eq!(divisor, 8);
285 let mut one_count = 0;
286 let mut whole = whole;
287 while let Ok(chunk) = consume_byte_arrays(&mut whole, 1) {
288 one_count += u64::from_ne_bytes(chunk[0]).count_ones() as usize;
289 }
290 for &byte in whole {
291 one_count += byte.count_ones() as usize;
292 }
293 if let Some(partial_with_garbage) = partial_with_garbage {
294 // Set undefined garbage bits to zero.
295 let partial = partial_with_garbage << (divisor - partial_length);
296 one_count += partial.count_ones() as usize;
297 }
298 Ok(std::array::from_fn(|i| match i {
299 0 => length - one_count,
300 1 => one_count,
301 _ => unreachable!(),
302 }))
303 } else {
304 check_histogram(if whole.len() < 100 {
305 // Simple path: histogram of unpacked bytes.
306 let mut histogram = [0; FACTOR];
307 for &v in out.iter() {
308 // Safety: unpack_arithmetic::<FACTOR> returns bytes < FACTOR.
309 unsafe { *histogram.get_unchecked_mut(v as usize) += 1 };
310 }

Callers

nothing calls this directly

Calls 5

consume_byte_arraysFunction · 0.85
check_histogramFunction · 0.85
histogramFunction · 0.85
unpack_histogramFunction · 0.85
lenMethod · 0.45

Tested by

no test coverage detected