Skip to main content

lance_bitpacking/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4// NOTICE:
5// This file is a modification of the `fastlanes` crate: https://github.com/spiraldb/fastlanes
6// It is modified to allow a rust stable build
7//
8// The original code can be accessed at
9//      https://github.com/spiraldb/fastlanes/blob/8e0ff374f815d919d0c0ebdccf5ffd9e6dc7d663/src/bitpacking.rs
10//      https://github.com/spiraldb/fastlanes/blob/8e0ff374f815d919d0c0ebdccf5ffd9e6dc7d663/src/lib.rs
11//      https://github.com/spiraldb/fastlanes/blob/8e0ff374f815d919d0c0ebdccf5ffd9e6dc7d663/src/macros.rs
12//
13// The original code is licensed under the Apache Software License:
14// https://github.com/spiraldb/fastlanes/blob/8e0ff374f815d919d0c0ebdccf5ffd9e6dc7d663/LICENSE
15
16use arrayref::{array_mut_ref, array_ref};
17use core::mem::{MaybeUninit, size_of};
18
19mod bitpacker_internal;
20
21pub use bitpacker_internal::{BitPacker, BitPacker4x, BitPacker8x};
22
23pub const FL_ORDER: [usize; 8] = [0, 4, 2, 6, 1, 5, 3, 7];
24
25pub trait FastLanes: Sized + Copy {
26    const T: usize = size_of::<Self>() * 8;
27    const LANES: usize = 1024 / Self::T;
28}
29
30// Implement the trait for basic unsigned integer types
31impl FastLanes for u8 {}
32impl FastLanes for u16 {}
33impl FastLanes for u32 {}
34impl FastLanes for u64 {}
35
36macro_rules! pack {
37    ($T:ty, $W:expr, $packed:expr, $lane:expr, | $_1:tt $idx:ident | $($body:tt)*) => {
38        macro_rules! __kernel__ {( $_1 $idx:ident ) => ( $($body)* )}
39        {
40            use paste::paste;
41
42            // The number of bits of T.
43            const T: usize = <$T>::T;
44
45            #[inline(always)]
46            fn index(row: usize, lane: usize) -> usize {
47                let o = row / 8;
48                let s = row % 8;
49                (FL_ORDER[o] * 16) + (s * 128) + lane
50            }
51
52            if $W == 0 {
53                // Nothing to do if W is 0, since the packed array is zero bytes.
54            } else if $W == T {
55                // Special case for W=T, we can just copy the input value directly to the packed value.
56                paste!(seq_t!(row in $T {
57                    let idx = index(row, $lane);
58                    $packed[<$T>::LANES * row + $lane].write(__kernel__!(idx));
59                }));
60            } else {
61                // A mask of W bits.
62                let mask: $T = (1 << $W) - 1;
63
64                // First we loop over each lane in the virtual 1024 bit word.
65                let mut tmp: $T = 0;
66
67                // Loop over each of the rows of the lane.
68                // Inlining this loop means all branches are known at compile time and
69                // the code is auto-vectorized for SIMD execution.
70                paste!(seq_t!(row in $T {
71                    let idx = index(row, $lane);
72                    let src = __kernel__!(idx);
73                    let src = src & mask;
74
75                    // Shift the src bits into their position in the tmp output variable.
76                    if row == 0 {
77                        tmp = src;
78                    } else {
79                        tmp |= src << (row * $W) % T;
80                    }
81
82                    // If the next packed position is after our current one, then we have filled
83                    // the current output and we can write the packed value.
84                    let curr_word: usize = (row * $W) / T;
85                    let next_word: usize = ((row + 1) * $W) / T;
86
87                    #[allow(unused_assignments)]
88                    if next_word > curr_word {
89                        $packed[<$T>::LANES * curr_word + $lane].write(tmp);
90                        let remaining_bits: usize = ((row + 1) * $W) % T;
91                        // Keep the remaining bits for the next packed value.
92                        tmp = src >> $W - remaining_bits;
93                    }
94                }));
95            }
96        }
97    };
98}
99
100macro_rules! unpack {
101    ($T:ty, $W:expr, $packed:expr, $lane:expr, | $_1:tt $idx:ident, $_2:tt $elem:ident | $($body:tt)*) => {
102        macro_rules! __kernel__ {( $_1 $idx:ident, $_2 $elem:ident ) => ( $($body)* )}
103        {
104            use paste::paste;
105
106            // The number of bits of T.
107            const T: usize = <$T>::T;
108
109            #[inline(always)]
110            fn index(row: usize, lane: usize) -> usize {
111                let o = row / 8;
112                let s = row % 8;
113                (FL_ORDER[o] * 16) + (s * 128) + lane
114            }
115
116            if $W == 0 {
117                // Special case for W=0, we just need to zero the output.
118                // We'll still respect the iteration order in case the kernel has side effects.
119                paste!(seq_t!(row in $T {
120                    let idx = index(row, $lane);
121                    let zero: $T = 0;
122                    __kernel__!(idx, zero);
123                }));
124            } else if $W == T {
125                // Special case for W=T, we can just copy the packed value directly to the output.
126                paste!(seq_t!(row in $T {
127                    let idx = index(row, $lane);
128                    let src = $packed[<$T>::LANES * row + $lane];
129                    __kernel__!(idx, src);
130                }));
131            } else {
132                #[inline]
133                fn mask(width: usize) -> $T {
134                    if width == T { <$T>::MAX } else { (1 << (width % T)) - 1 }
135                }
136
137                let mut src: $T = $packed[$lane];
138                let mut tmp: $T;
139
140                paste!(seq_t!(row in $T {
141                    // Figure out the packed positions
142                    let curr_word: usize = (row * $W) / T;
143                    let next_word = ((row + 1) * $W) / T;
144
145                    let shift = (row * $W) % T;
146
147                    if next_word > curr_word {
148                        // Consume some bits from the curr packed input, the remainder are in the next
149                        // packed input value
150                        let remaining_bits = ((row + 1) * $W) % T;
151                        let current_bits = $W - remaining_bits;
152                        tmp = (src >> shift) & mask(current_bits);
153
154                        if next_word < $W {
155                            // Load the next packed value
156                            src = $packed[<$T>::LANES * next_word + $lane];
157                            // Consume the remaining bits from the next input value.
158                            tmp |= (src & mask(remaining_bits)) << current_bits;
159                        }
160                    } else {
161                        // Otherwise, just grab W bits from the src value
162                        tmp = (src >> shift) & mask($W);
163                    }
164
165                    // Write out the unpacked value
166                    let idx = index(row, $lane);
167                    __kernel__!(idx, tmp);
168                }));
169            }
170        }
171    };
172}
173
174// Macro for repeating a code block bit_size_of::<T> times.
175macro_rules! seq_t {
176    ($ident:ident in u8 $body:tt) => {seq_macro::seq!($ident in 0..8 $body)};
177    ($ident:ident in u16 $body:tt) => {seq_macro::seq!($ident in 0..16 $body)};
178    ($ident:ident in u32 $body:tt) => {seq_macro::seq!($ident in 0..32 $body)};
179    ($ident:ident in u64 $body:tt) => {seq_macro::seq!($ident in 0..64 $body)};
180}
181
182/// `BitPack` into a compile-time known bit-width.
183pub trait BitPacking: FastLanes {
184    /// Packs 1024 elements into `W` bits each, where `W` is runtime-known instead of
185    /// compile-time known.
186    ///
187    /// # Safety
188    /// The input slice must be of exactly length 1024. The output slice must be of length
189    /// `1024 * W / T`, where `T` is the bit-width of Self and `W` is the packed width.
190    /// These lengths are checked only with `debug_assert` (i.e., not checked on release builds).
191    unsafe fn unchecked_pack(width: usize, input: &[Self], output: &mut [Self]);
192
193    /// Unpacks 1024 elements from `W` bits each, where `W` is runtime-known instead of
194    /// compile-time known.
195    ///
196    /// # Safety
197    /// The input slice must be of length `1024 * W / T`, where `T` is the bit-width of Self and `W`
198    /// is the packed width. The output slice must be of exactly length 1024.
199    /// These lengths are checked only with `debug_assert` (i.e., not checked on release builds).
200    unsafe fn unchecked_unpack(width: usize, input: &[Self], output: &mut [Self]);
201}
202
203/// Bitpacking kernels that can initialize previously uninitialized output storage.
204pub trait BitPackingUninit: BitPacking {
205    /// Packs into potentially uninitialized output storage.
206    ///
207    /// # Safety
208    /// The input and output lengths have the same requirements as
209    /// [`BitPacking::unchecked_pack`]. Every output element is initialized on return.
210    unsafe fn unchecked_pack_uninit(width: usize, input: &[Self], output: &mut [MaybeUninit<Self>]);
211
212    /// Unpacks into potentially uninitialized output storage.
213    ///
214    /// # Safety
215    /// The input and output lengths have the same requirements as
216    /// [`BitPacking::unchecked_unpack`]. Every output element is initialized on return.
217    unsafe fn unchecked_unpack_uninit(
218        width: usize,
219        input: &[Self],
220        output: &mut [MaybeUninit<Self>],
221    );
222}
223
224macro_rules! impl_bitpacking_compat {
225    ($ty:ty) => {
226        impl BitPacking for $ty {
227            unsafe fn unchecked_pack(width: usize, input: &[Self], output: &mut [Self]) {
228                let output = unsafe {
229                    core::slice::from_raw_parts_mut(
230                        output.as_mut_ptr().cast::<MaybeUninit<Self>>(),
231                        output.len(),
232                    )
233                };
234                unsafe { <Self as BitPackingUninit>::unchecked_pack_uninit(width, input, output) };
235            }
236
237            unsafe fn unchecked_unpack(width: usize, input: &[Self], output: &mut [Self]) {
238                let output = unsafe {
239                    core::slice::from_raw_parts_mut(
240                        output.as_mut_ptr().cast::<MaybeUninit<Self>>(),
241                        output.len(),
242                    )
243                };
244                unsafe {
245                    <Self as BitPackingUninit>::unchecked_unpack_uninit(width, input, output)
246                };
247            }
248        }
249    };
250}
251
252impl_bitpacking_compat!(u8);
253impl_bitpacking_compat!(u16);
254impl_bitpacking_compat!(u32);
255impl_bitpacking_compat!(u64);
256
257impl BitPackingUninit for u8 {
258    unsafe fn unchecked_pack_uninit(
259        width: usize,
260        input: &[Self],
261        output: &mut [MaybeUninit<Self>],
262    ) {
263        let packed_len = 128 * width / size_of::<Self>();
264        debug_assert_eq!(
265            output.len(),
266            packed_len,
267            "Output buffer must be of size 1024 * W / T"
268        );
269        debug_assert_eq!(input.len(), 1024, "Input buffer must be of size 1024");
270        debug_assert!(
271            width <= Self::T,
272            "Width must be less than or equal to {}",
273            Self::T
274        );
275
276        match width {
277            0 => {
278                // Nothing to write when width is zero.
279            }
280            1 => pack_8_1(
281                array_ref![input, 0, 1024],
282                array_mut_ref![output, 0, 1024 / 8],
283            ),
284            2 => pack_8_2(
285                array_ref![input, 0, 1024],
286                array_mut_ref![output, 0, 1024 * 2 / 8],
287            ),
288            3 => pack_8_3(
289                array_ref![input, 0, 1024],
290                array_mut_ref![output, 0, 1024 * 3 / 8],
291            ),
292            4 => pack_8_4(
293                array_ref![input, 0, 1024],
294                array_mut_ref![output, 0, 1024 * 4 / 8],
295            ),
296            5 => pack_8_5(
297                array_ref![input, 0, 1024],
298                array_mut_ref![output, 0, 1024 * 5 / 8],
299            ),
300            6 => pack_8_6(
301                array_ref![input, 0, 1024],
302                array_mut_ref![output, 0, 1024 * 6 / 8],
303            ),
304            7 => pack_8_7(
305                array_ref![input, 0, 1024],
306                array_mut_ref![output, 0, 1024 * 7 / 8],
307            ),
308            8 => pack_8_8(
309                array_ref![input, 0, 1024],
310                array_mut_ref![output, 0, 1024 * 8 / 8],
311            ),
312
313            _ => unreachable!("Unsupported width: {}", width),
314        }
315    }
316
317    unsafe fn unchecked_unpack_uninit(
318        width: usize,
319        input: &[Self],
320        output: &mut [MaybeUninit<Self>],
321    ) {
322        let packed_len = 128 * width / size_of::<Self>();
323        debug_assert_eq!(
324            input.len(),
325            packed_len,
326            "Input buffer must be of size 1024 * W / T"
327        );
328        debug_assert_eq!(output.len(), 1024, "Output buffer must be of size 1024");
329        debug_assert!(
330            width <= Self::T,
331            "Width must be less than or equal to {}",
332            Self::T
333        );
334
335        match width {
336            0 => {
337                // A zero-width packed chunk implies all zeros.
338                output.fill(MaybeUninit::new(0));
339            }
340            1 => unpack_8_1(
341                array_ref![input, 0, 1024 / 8],
342                array_mut_ref![output, 0, 1024],
343            ),
344            2 => unpack_8_2(
345                array_ref![input, 0, 1024 * 2 / 8],
346                array_mut_ref![output, 0, 1024],
347            ),
348            3 => unpack_8_3(
349                array_ref![input, 0, 1024 * 3 / 8],
350                array_mut_ref![output, 0, 1024],
351            ),
352            4 => unpack_8_4(
353                array_ref![input, 0, 1024 * 4 / 8],
354                array_mut_ref![output, 0, 1024],
355            ),
356            5 => unpack_8_5(
357                array_ref![input, 0, 1024 * 5 / 8],
358                array_mut_ref![output, 0, 1024],
359            ),
360            6 => unpack_8_6(
361                array_ref![input, 0, 1024 * 6 / 8],
362                array_mut_ref![output, 0, 1024],
363            ),
364            7 => unpack_8_7(
365                array_ref![input, 0, 1024 * 7 / 8],
366                array_mut_ref![output, 0, 1024],
367            ),
368            8 => unpack_8_8(
369                array_ref![input, 0, 1024 * 8 / 8],
370                array_mut_ref![output, 0, 1024],
371            ),
372
373            _ => unreachable!("Unsupported width: {}", width),
374        }
375    }
376}
377
378impl BitPackingUninit for u16 {
379    unsafe fn unchecked_pack_uninit(
380        width: usize,
381        input: &[Self],
382        output: &mut [MaybeUninit<Self>],
383    ) {
384        let packed_len = 128 * width / size_of::<Self>();
385        debug_assert_eq!(
386            output.len(),
387            packed_len,
388            "Output buffer must be of size 1024 * W / T"
389        );
390        debug_assert_eq!(input.len(), 1024, "Input buffer must be of size 1024");
391        debug_assert!(
392            width <= Self::T,
393            "Width must be less than or equal to {}",
394            Self::T
395        );
396
397        match width {
398            0 => {
399                // Nothing to write when width is zero.
400            }
401            1 => pack_16_1(
402                array_ref![input, 0, 1024],
403                array_mut_ref![output, 0, 1024 / 16],
404            ),
405            2 => pack_16_2(
406                array_ref![input, 0, 1024],
407                array_mut_ref![output, 0, 1024 * 2 / 16],
408            ),
409            3 => pack_16_3(
410                array_ref![input, 0, 1024],
411                array_mut_ref![output, 0, 1024 * 3 / 16],
412            ),
413            4 => pack_16_4(
414                array_ref![input, 0, 1024],
415                array_mut_ref![output, 0, 1024 * 4 / 16],
416            ),
417            5 => pack_16_5(
418                array_ref![input, 0, 1024],
419                array_mut_ref![output, 0, 1024 * 5 / 16],
420            ),
421            6 => pack_16_6(
422                array_ref![input, 0, 1024],
423                array_mut_ref![output, 0, 1024 * 6 / 16],
424            ),
425            7 => pack_16_7(
426                array_ref![input, 0, 1024],
427                array_mut_ref![output, 0, 1024 * 7 / 16],
428            ),
429            8 => pack_16_8(
430                array_ref![input, 0, 1024],
431                array_mut_ref![output, 0, 1024 * 8 / 16],
432            ),
433            9 => pack_16_9(
434                array_ref![input, 0, 1024],
435                array_mut_ref![output, 0, 1024 * 9 / 16],
436            ),
437
438            10 => pack_16_10(
439                array_ref![input, 0, 1024],
440                array_mut_ref![output, 0, 1024 * 10 / 16],
441            ),
442            11 => pack_16_11(
443                array_ref![input, 0, 1024],
444                array_mut_ref![output, 0, 1024 * 11 / 16],
445            ),
446            12 => pack_16_12(
447                array_ref![input, 0, 1024],
448                array_mut_ref![output, 0, 1024 * 12 / 16],
449            ),
450            13 => pack_16_13(
451                array_ref![input, 0, 1024],
452                array_mut_ref![output, 0, 1024 * 13 / 16],
453            ),
454            14 => pack_16_14(
455                array_ref![input, 0, 1024],
456                array_mut_ref![output, 0, 1024 * 14 / 16],
457            ),
458            15 => pack_16_15(
459                array_ref![input, 0, 1024],
460                array_mut_ref![output, 0, 1024 * 15 / 16],
461            ),
462            16 => pack_16_16(
463                array_ref![input, 0, 1024],
464                array_mut_ref![output, 0, 1024 * 16 / 16],
465            ),
466
467            _ => unreachable!("Unsupported width: {}", width),
468        }
469    }
470
471    unsafe fn unchecked_unpack_uninit(
472        width: usize,
473        input: &[Self],
474        output: &mut [MaybeUninit<Self>],
475    ) {
476        let packed_len = 128 * width / size_of::<Self>();
477        debug_assert_eq!(
478            input.len(),
479            packed_len,
480            "Input buffer must be of size 1024 * W / T"
481        );
482        debug_assert_eq!(output.len(), 1024, "Output buffer must be of size 1024");
483        debug_assert!(
484            width <= Self::T,
485            "Width must be less than or equal to {}",
486            Self::T
487        );
488
489        match width {
490            0 => {
491                output.fill(MaybeUninit::new(0));
492            }
493            1 => unpack_16_1(
494                array_ref![input, 0, 1024 / 16],
495                array_mut_ref![output, 0, 1024],
496            ),
497            2 => unpack_16_2(
498                array_ref![input, 0, 1024 * 2 / 16],
499                array_mut_ref![output, 0, 1024],
500            ),
501            3 => unpack_16_3(
502                array_ref![input, 0, 1024 * 3 / 16],
503                array_mut_ref![output, 0, 1024],
504            ),
505            4 => unpack_16_4(
506                array_ref![input, 0, 1024 * 4 / 16],
507                array_mut_ref![output, 0, 1024],
508            ),
509            5 => unpack_16_5(
510                array_ref![input, 0, 1024 * 5 / 16],
511                array_mut_ref![output, 0, 1024],
512            ),
513            6 => unpack_16_6(
514                array_ref![input, 0, 1024 * 6 / 16],
515                array_mut_ref![output, 0, 1024],
516            ),
517            7 => unpack_16_7(
518                array_ref![input, 0, 1024 * 7 / 16],
519                array_mut_ref![output, 0, 1024],
520            ),
521            8 => unpack_16_8(
522                array_ref![input, 0, 1024 * 8 / 16],
523                array_mut_ref![output, 0, 1024],
524            ),
525            9 => unpack_16_9(
526                array_ref![input, 0, 1024 * 9 / 16],
527                array_mut_ref![output, 0, 1024],
528            ),
529
530            10 => unpack_16_10(
531                array_ref![input, 0, 1024 * 10 / 16],
532                array_mut_ref![output, 0, 1024],
533            ),
534            11 => unpack_16_11(
535                array_ref![input, 0, 1024 * 11 / 16],
536                array_mut_ref![output, 0, 1024],
537            ),
538            12 => unpack_16_12(
539                array_ref![input, 0, 1024 * 12 / 16],
540                array_mut_ref![output, 0, 1024],
541            ),
542            13 => unpack_16_13(
543                array_ref![input, 0, 1024 * 13 / 16],
544                array_mut_ref![output, 0, 1024],
545            ),
546            14 => unpack_16_14(
547                array_ref![input, 0, 1024 * 14 / 16],
548                array_mut_ref![output, 0, 1024],
549            ),
550            15 => unpack_16_15(
551                array_ref![input, 0, 1024 * 15 / 16],
552                array_mut_ref![output, 0, 1024],
553            ),
554            16 => unpack_16_16(
555                array_ref![input, 0, 1024 * 16 / 16],
556                array_mut_ref![output, 0, 1024],
557            ),
558
559            _ => unreachable!("Unsupported width: {}", width),
560        }
561    }
562}
563
564impl BitPackingUninit for u32 {
565    unsafe fn unchecked_pack_uninit(
566        width: usize,
567        input: &[Self],
568        output: &mut [MaybeUninit<Self>],
569    ) {
570        let packed_len = 128 * width / size_of::<Self>();
571        debug_assert_eq!(
572            output.len(),
573            packed_len,
574            "Output buffer must be of size 1024 * W / T"
575        );
576        debug_assert_eq!(input.len(), 1024, "Input buffer must be of size 1024");
577        debug_assert!(
578            width <= Self::T,
579            "Width must be less than or equal to {}",
580            Self::T
581        );
582
583        match width {
584            0 => {
585                // Nothing to write when width is zero.
586            }
587            1 => pack_32_1(
588                array_ref![input, 0, 1024],
589                array_mut_ref![output, 0, 1024 / 32],
590            ),
591            2 => pack_32_2(
592                array_ref![input, 0, 1024],
593                array_mut_ref![output, 0, 1024 * 2 / 32],
594            ),
595            3 => pack_32_3(
596                array_ref![input, 0, 1024],
597                array_mut_ref![output, 0, 1024 * 3 / 32],
598            ),
599            4 => pack_32_4(
600                array_ref![input, 0, 1024],
601                array_mut_ref![output, 0, 1024 * 4 / 32],
602            ),
603            5 => pack_32_5(
604                array_ref![input, 0, 1024],
605                array_mut_ref![output, 0, 1024 * 5 / 32],
606            ),
607            6 => pack_32_6(
608                array_ref![input, 0, 1024],
609                array_mut_ref![output, 0, 1024 * 6 / 32],
610            ),
611            7 => pack_32_7(
612                array_ref![input, 0, 1024],
613                array_mut_ref![output, 0, 1024 * 7 / 32],
614            ),
615            8 => pack_32_8(
616                array_ref![input, 0, 1024],
617                array_mut_ref![output, 0, 1024 * 8 / 32],
618            ),
619            9 => pack_32_9(
620                array_ref![input, 0, 1024],
621                array_mut_ref![output, 0, 1024 * 9 / 32],
622            ),
623
624            10 => pack_32_10(
625                array_ref![input, 0, 1024],
626                array_mut_ref![output, 0, 1024 * 10 / 32],
627            ),
628            11 => pack_32_11(
629                array_ref![input, 0, 1024],
630                array_mut_ref![output, 0, 1024 * 11 / 32],
631            ),
632            12 => pack_32_12(
633                array_ref![input, 0, 1024],
634                array_mut_ref![output, 0, 1024 * 12 / 32],
635            ),
636            13 => pack_32_13(
637                array_ref![input, 0, 1024],
638                array_mut_ref![output, 0, 1024 * 13 / 32],
639            ),
640            14 => pack_32_14(
641                array_ref![input, 0, 1024],
642                array_mut_ref![output, 0, 1024 * 14 / 32],
643            ),
644            15 => pack_32_15(
645                array_ref![input, 0, 1024],
646                array_mut_ref![output, 0, 1024 * 15 / 32],
647            ),
648            16 => pack_32_16(
649                array_ref![input, 0, 1024],
650                array_mut_ref![output, 0, 1024 * 16 / 32],
651            ),
652            17 => pack_32_17(
653                array_ref![input, 0, 1024],
654                array_mut_ref![output, 0, 1024 * 17 / 32],
655            ),
656            18 => pack_32_18(
657                array_ref![input, 0, 1024],
658                array_mut_ref![output, 0, 1024 * 18 / 32],
659            ),
660            19 => pack_32_19(
661                array_ref![input, 0, 1024],
662                array_mut_ref![output, 0, 1024 * 19 / 32],
663            ),
664
665            20 => pack_32_20(
666                array_ref![input, 0, 1024],
667                array_mut_ref![output, 0, 1024 * 20 / 32],
668            ),
669            21 => pack_32_21(
670                array_ref![input, 0, 1024],
671                array_mut_ref![output, 0, 1024 * 21 / 32],
672            ),
673            22 => pack_32_22(
674                array_ref![input, 0, 1024],
675                array_mut_ref![output, 0, 1024 * 22 / 32],
676            ),
677            23 => pack_32_23(
678                array_ref![input, 0, 1024],
679                array_mut_ref![output, 0, 1024 * 23 / 32],
680            ),
681            24 => pack_32_24(
682                array_ref![input, 0, 1024],
683                array_mut_ref![output, 0, 1024 * 24 / 32],
684            ),
685            25 => pack_32_25(
686                array_ref![input, 0, 1024],
687                array_mut_ref![output, 0, 1024 * 25 / 32],
688            ),
689            26 => pack_32_26(
690                array_ref![input, 0, 1024],
691                array_mut_ref![output, 0, 1024 * 26 / 32],
692            ),
693            27 => pack_32_27(
694                array_ref![input, 0, 1024],
695                array_mut_ref![output, 0, 1024 * 27 / 32],
696            ),
697            28 => pack_32_28(
698                array_ref![input, 0, 1024],
699                array_mut_ref![output, 0, 1024 * 28 / 32],
700            ),
701            29 => pack_32_29(
702                array_ref![input, 0, 1024],
703                array_mut_ref![output, 0, 1024 * 29 / 32],
704            ),
705
706            30 => pack_32_30(
707                array_ref![input, 0, 1024],
708                array_mut_ref![output, 0, 1024 * 30 / 32],
709            ),
710            31 => pack_32_31(
711                array_ref![input, 0, 1024],
712                array_mut_ref![output, 0, 1024 * 31 / 32],
713            ),
714            32 => pack_32_32(
715                array_ref![input, 0, 1024],
716                array_mut_ref![output, 0, 1024 * 32 / 32],
717            ),
718
719            _ => unreachable!("Unsupported width: {}", width),
720        }
721    }
722
723    unsafe fn unchecked_unpack_uninit(
724        width: usize,
725        input: &[Self],
726        output: &mut [MaybeUninit<Self>],
727    ) {
728        let packed_len = 128 * width / size_of::<Self>();
729        debug_assert_eq!(
730            input.len(),
731            packed_len,
732            "Input buffer must be of size 1024 * W / T"
733        );
734        debug_assert_eq!(output.len(), 1024, "Output buffer must be of size 1024");
735        debug_assert!(
736            width <= Self::T,
737            "Width must be less than or equal to {}",
738            Self::T
739        );
740
741        match width {
742            0 => {
743                output.fill(MaybeUninit::new(0));
744            }
745            1 => unpack_32_1(
746                array_ref![input, 0, 1024 / 32],
747                array_mut_ref![output, 0, 1024],
748            ),
749            2 => unpack_32_2(
750                array_ref![input, 0, 1024 * 2 / 32],
751                array_mut_ref![output, 0, 1024],
752            ),
753            3 => unpack_32_3(
754                array_ref![input, 0, 1024 * 3 / 32],
755                array_mut_ref![output, 0, 1024],
756            ),
757            4 => unpack_32_4(
758                array_ref![input, 0, 1024 * 4 / 32],
759                array_mut_ref![output, 0, 1024],
760            ),
761            5 => unpack_32_5(
762                array_ref![input, 0, 1024 * 5 / 32],
763                array_mut_ref![output, 0, 1024],
764            ),
765            6 => unpack_32_6(
766                array_ref![input, 0, 1024 * 6 / 32],
767                array_mut_ref![output, 0, 1024],
768            ),
769            7 => unpack_32_7(
770                array_ref![input, 0, 1024 * 7 / 32],
771                array_mut_ref![output, 0, 1024],
772            ),
773            8 => unpack_32_8(
774                array_ref![input, 0, 1024 * 8 / 32],
775                array_mut_ref![output, 0, 1024],
776            ),
777            9 => unpack_32_9(
778                array_ref![input, 0, 1024 * 9 / 32],
779                array_mut_ref![output, 0, 1024],
780            ),
781
782            10 => unpack_32_10(
783                array_ref![input, 0, 1024 * 10 / 32],
784                array_mut_ref![output, 0, 1024],
785            ),
786            11 => unpack_32_11(
787                array_ref![input, 0, 1024 * 11 / 32],
788                array_mut_ref![output, 0, 1024],
789            ),
790            12 => unpack_32_12(
791                array_ref![input, 0, 1024 * 12 / 32],
792                array_mut_ref![output, 0, 1024],
793            ),
794            13 => unpack_32_13(
795                array_ref![input, 0, 1024 * 13 / 32],
796                array_mut_ref![output, 0, 1024],
797            ),
798            14 => unpack_32_14(
799                array_ref![input, 0, 1024 * 14 / 32],
800                array_mut_ref![output, 0, 1024],
801            ),
802            15 => unpack_32_15(
803                array_ref![input, 0, 1024 * 15 / 32],
804                array_mut_ref![output, 0, 1024],
805            ),
806            16 => unpack_32_16(
807                array_ref![input, 0, 1024 * 16 / 32],
808                array_mut_ref![output, 0, 1024],
809            ),
810            17 => unpack_32_17(
811                array_ref![input, 0, 1024 * 17 / 32],
812                array_mut_ref![output, 0, 1024],
813            ),
814            18 => unpack_32_18(
815                array_ref![input, 0, 1024 * 18 / 32],
816                array_mut_ref![output, 0, 1024],
817            ),
818            19 => unpack_32_19(
819                array_ref![input, 0, 1024 * 19 / 32],
820                array_mut_ref![output, 0, 1024],
821            ),
822
823            20 => unpack_32_20(
824                array_ref![input, 0, 1024 * 20 / 32],
825                array_mut_ref![output, 0, 1024],
826            ),
827            21 => unpack_32_21(
828                array_ref![input, 0, 1024 * 21 / 32],
829                array_mut_ref![output, 0, 1024],
830            ),
831            22 => unpack_32_22(
832                array_ref![input, 0, 1024 * 22 / 32],
833                array_mut_ref![output, 0, 1024],
834            ),
835            23 => unpack_32_23(
836                array_ref![input, 0, 1024 * 23 / 32],
837                array_mut_ref![output, 0, 1024],
838            ),
839            24 => unpack_32_24(
840                array_ref![input, 0, 1024 * 24 / 32],
841                array_mut_ref![output, 0, 1024],
842            ),
843            25 => unpack_32_25(
844                array_ref![input, 0, 1024 * 25 / 32],
845                array_mut_ref![output, 0, 1024],
846            ),
847            26 => unpack_32_26(
848                array_ref![input, 0, 1024 * 26 / 32],
849                array_mut_ref![output, 0, 1024],
850            ),
851            27 => unpack_32_27(
852                array_ref![input, 0, 1024 * 27 / 32],
853                array_mut_ref![output, 0, 1024],
854            ),
855            28 => unpack_32_28(
856                array_ref![input, 0, 1024 * 28 / 32],
857                array_mut_ref![output, 0, 1024],
858            ),
859            29 => unpack_32_29(
860                array_ref![input, 0, 1024 * 29 / 32],
861                array_mut_ref![output, 0, 1024],
862            ),
863
864            30 => unpack_32_30(
865                array_ref![input, 0, 1024 * 30 / 32],
866                array_mut_ref![output, 0, 1024],
867            ),
868            31 => unpack_32_31(
869                array_ref![input, 0, 1024 * 31 / 32],
870                array_mut_ref![output, 0, 1024],
871            ),
872            32 => unpack_32_32(
873                array_ref![input, 0, 1024 * 32 / 32],
874                array_mut_ref![output, 0, 1024],
875            ),
876
877            _ => unreachable!("Unsupported width: {}", width),
878        }
879    }
880}
881
882impl BitPackingUninit for u64 {
883    unsafe fn unchecked_pack_uninit(
884        width: usize,
885        input: &[Self],
886        output: &mut [MaybeUninit<Self>],
887    ) {
888        let packed_len = 128 * width / size_of::<Self>();
889        debug_assert_eq!(
890            output.len(),
891            packed_len,
892            "Output buffer must be of size 1024 * W / T"
893        );
894        debug_assert_eq!(input.len(), 1024, "Input buffer must be of size 1024");
895        debug_assert!(
896            width <= Self::T,
897            "Width must be less than or equal to {}",
898            Self::T
899        );
900
901        match width {
902            0 => {
903                // Nothing to write when width is zero.
904            }
905            1 => pack_64_1(
906                array_ref![input, 0, 1024],
907                array_mut_ref![output, 0, 1024 / 64],
908            ),
909            2 => pack_64_2(
910                array_ref![input, 0, 1024],
911                array_mut_ref![output, 0, 1024 * 2 / 64],
912            ),
913            3 => pack_64_3(
914                array_ref![input, 0, 1024],
915                array_mut_ref![output, 0, 1024 * 3 / 64],
916            ),
917            4 => pack_64_4(
918                array_ref![input, 0, 1024],
919                array_mut_ref![output, 0, 1024 * 4 / 64],
920            ),
921            5 => pack_64_5(
922                array_ref![input, 0, 1024],
923                array_mut_ref![output, 0, 1024 * 5 / 64],
924            ),
925            6 => pack_64_6(
926                array_ref![input, 0, 1024],
927                array_mut_ref![output, 0, 1024 * 6 / 64],
928            ),
929            7 => pack_64_7(
930                array_ref![input, 0, 1024],
931                array_mut_ref![output, 0, 1024 * 7 / 64],
932            ),
933            8 => pack_64_8(
934                array_ref![input, 0, 1024],
935                array_mut_ref![output, 0, 1024 * 8 / 64],
936            ),
937            9 => pack_64_9(
938                array_ref![input, 0, 1024],
939                array_mut_ref![output, 0, 1024 * 9 / 64],
940            ),
941
942            10 => pack_64_10(
943                array_ref![input, 0, 1024],
944                array_mut_ref![output, 0, 1024 * 10 / 64],
945            ),
946            11 => pack_64_11(
947                array_ref![input, 0, 1024],
948                array_mut_ref![output, 0, 1024 * 11 / 64],
949            ),
950            12 => pack_64_12(
951                array_ref![input, 0, 1024],
952                array_mut_ref![output, 0, 1024 * 12 / 64],
953            ),
954            13 => pack_64_13(
955                array_ref![input, 0, 1024],
956                array_mut_ref![output, 0, 1024 * 13 / 64],
957            ),
958            14 => pack_64_14(
959                array_ref![input, 0, 1024],
960                array_mut_ref![output, 0, 1024 * 14 / 64],
961            ),
962            15 => pack_64_15(
963                array_ref![input, 0, 1024],
964                array_mut_ref![output, 0, 1024 * 15 / 64],
965            ),
966            16 => pack_64_16(
967                array_ref![input, 0, 1024],
968                array_mut_ref![output, 0, 1024 * 16 / 64],
969            ),
970            17 => pack_64_17(
971                array_ref![input, 0, 1024],
972                array_mut_ref![output, 0, 1024 * 17 / 64],
973            ),
974            18 => pack_64_18(
975                array_ref![input, 0, 1024],
976                array_mut_ref![output, 0, 1024 * 18 / 64],
977            ),
978            19 => pack_64_19(
979                array_ref![input, 0, 1024],
980                array_mut_ref![output, 0, 1024 * 19 / 64],
981            ),
982
983            20 => pack_64_20(
984                array_ref![input, 0, 1024],
985                array_mut_ref![output, 0, 1024 * 20 / 64],
986            ),
987            21 => pack_64_21(
988                array_ref![input, 0, 1024],
989                array_mut_ref![output, 0, 1024 * 21 / 64],
990            ),
991            22 => pack_64_22(
992                array_ref![input, 0, 1024],
993                array_mut_ref![output, 0, 1024 * 22 / 64],
994            ),
995            23 => pack_64_23(
996                array_ref![input, 0, 1024],
997                array_mut_ref![output, 0, 1024 * 23 / 64],
998            ),
999            24 => pack_64_24(
1000                array_ref![input, 0, 1024],
1001                array_mut_ref![output, 0, 1024 * 24 / 64],
1002            ),
1003            25 => pack_64_25(
1004                array_ref![input, 0, 1024],
1005                array_mut_ref![output, 0, 1024 * 25 / 64],
1006            ),
1007            26 => pack_64_26(
1008                array_ref![input, 0, 1024],
1009                array_mut_ref![output, 0, 1024 * 26 / 64],
1010            ),
1011            27 => pack_64_27(
1012                array_ref![input, 0, 1024],
1013                array_mut_ref![output, 0, 1024 * 27 / 64],
1014            ),
1015            28 => pack_64_28(
1016                array_ref![input, 0, 1024],
1017                array_mut_ref![output, 0, 1024 * 28 / 64],
1018            ),
1019            29 => pack_64_29(
1020                array_ref![input, 0, 1024],
1021                array_mut_ref![output, 0, 1024 * 29 / 64],
1022            ),
1023
1024            30 => pack_64_30(
1025                array_ref![input, 0, 1024],
1026                array_mut_ref![output, 0, 1024 * 30 / 64],
1027            ),
1028            31 => pack_64_31(
1029                array_ref![input, 0, 1024],
1030                array_mut_ref![output, 0, 1024 * 31 / 64],
1031            ),
1032            32 => pack_64_32(
1033                array_ref![input, 0, 1024],
1034                array_mut_ref![output, 0, 1024 * 32 / 64],
1035            ),
1036            33 => pack_64_33(
1037                array_ref![input, 0, 1024],
1038                array_mut_ref![output, 0, 1024 * 33 / 64],
1039            ),
1040            34 => pack_64_34(
1041                array_ref![input, 0, 1024],
1042                array_mut_ref![output, 0, 1024 * 34 / 64],
1043            ),
1044            35 => pack_64_35(
1045                array_ref![input, 0, 1024],
1046                array_mut_ref![output, 0, 1024 * 35 / 64],
1047            ),
1048            36 => pack_64_36(
1049                array_ref![input, 0, 1024],
1050                array_mut_ref![output, 0, 1024 * 36 / 64],
1051            ),
1052            37 => pack_64_37(
1053                array_ref![input, 0, 1024],
1054                array_mut_ref![output, 0, 1024 * 37 / 64],
1055            ),
1056            38 => pack_64_38(
1057                array_ref![input, 0, 1024],
1058                array_mut_ref![output, 0, 1024 * 38 / 64],
1059            ),
1060            39 => pack_64_39(
1061                array_ref![input, 0, 1024],
1062                array_mut_ref![output, 0, 1024 * 39 / 64],
1063            ),
1064
1065            40 => pack_64_40(
1066                array_ref![input, 0, 1024],
1067                array_mut_ref![output, 0, 1024 * 40 / 64],
1068            ),
1069            41 => pack_64_41(
1070                array_ref![input, 0, 1024],
1071                array_mut_ref![output, 0, 1024 * 41 / 64],
1072            ),
1073            42 => pack_64_42(
1074                array_ref![input, 0, 1024],
1075                array_mut_ref![output, 0, 1024 * 42 / 64],
1076            ),
1077            43 => pack_64_43(
1078                array_ref![input, 0, 1024],
1079                array_mut_ref![output, 0, 1024 * 43 / 64],
1080            ),
1081            44 => pack_64_44(
1082                array_ref![input, 0, 1024],
1083                array_mut_ref![output, 0, 1024 * 44 / 64],
1084            ),
1085            45 => pack_64_45(
1086                array_ref![input, 0, 1024],
1087                array_mut_ref![output, 0, 1024 * 45 / 64],
1088            ),
1089            46 => pack_64_46(
1090                array_ref![input, 0, 1024],
1091                array_mut_ref![output, 0, 1024 * 46 / 64],
1092            ),
1093            47 => pack_64_47(
1094                array_ref![input, 0, 1024],
1095                array_mut_ref![output, 0, 1024 * 47 / 64],
1096            ),
1097            48 => pack_64_48(
1098                array_ref![input, 0, 1024],
1099                array_mut_ref![output, 0, 1024 * 48 / 64],
1100            ),
1101            49 => pack_64_49(
1102                array_ref![input, 0, 1024],
1103                array_mut_ref![output, 0, 1024 * 49 / 64],
1104            ),
1105
1106            50 => pack_64_50(
1107                array_ref![input, 0, 1024],
1108                array_mut_ref![output, 0, 1024 * 50 / 64],
1109            ),
1110            51 => pack_64_51(
1111                array_ref![input, 0, 1024],
1112                array_mut_ref![output, 0, 1024 * 51 / 64],
1113            ),
1114            52 => pack_64_52(
1115                array_ref![input, 0, 1024],
1116                array_mut_ref![output, 0, 1024 * 52 / 64],
1117            ),
1118            53 => pack_64_53(
1119                array_ref![input, 0, 1024],
1120                array_mut_ref![output, 0, 1024 * 53 / 64],
1121            ),
1122            54 => pack_64_54(
1123                array_ref![input, 0, 1024],
1124                array_mut_ref![output, 0, 1024 * 54 / 64],
1125            ),
1126            55 => pack_64_55(
1127                array_ref![input, 0, 1024],
1128                array_mut_ref![output, 0, 1024 * 55 / 64],
1129            ),
1130            56 => pack_64_56(
1131                array_ref![input, 0, 1024],
1132                array_mut_ref![output, 0, 1024 * 56 / 64],
1133            ),
1134            57 => pack_64_57(
1135                array_ref![input, 0, 1024],
1136                array_mut_ref![output, 0, 1024 * 57 / 64],
1137            ),
1138            58 => pack_64_58(
1139                array_ref![input, 0, 1024],
1140                array_mut_ref![output, 0, 1024 * 58 / 64],
1141            ),
1142            59 => pack_64_59(
1143                array_ref![input, 0, 1024],
1144                array_mut_ref![output, 0, 1024 * 59 / 64],
1145            ),
1146
1147            60 => pack_64_60(
1148                array_ref![input, 0, 1024],
1149                array_mut_ref![output, 0, 1024 * 60 / 64],
1150            ),
1151            61 => pack_64_61(
1152                array_ref![input, 0, 1024],
1153                array_mut_ref![output, 0, 1024 * 61 / 64],
1154            ),
1155            62 => pack_64_62(
1156                array_ref![input, 0, 1024],
1157                array_mut_ref![output, 0, 1024 * 62 / 64],
1158            ),
1159            63 => pack_64_63(
1160                array_ref![input, 0, 1024],
1161                array_mut_ref![output, 0, 1024 * 63 / 64],
1162            ),
1163            64 => pack_64_64(
1164                array_ref![input, 0, 1024],
1165                array_mut_ref![output, 0, 1024 * 64 / 64],
1166            ),
1167
1168            _ => unreachable!("Unsupported width: {}", width),
1169        }
1170    }
1171
1172    unsafe fn unchecked_unpack_uninit(
1173        width: usize,
1174        input: &[Self],
1175        output: &mut [MaybeUninit<Self>],
1176    ) {
1177        let packed_len = 128 * width / size_of::<Self>();
1178        debug_assert_eq!(
1179            input.len(),
1180            packed_len,
1181            "Input buffer must be of size 1024 * W / T"
1182        );
1183        debug_assert_eq!(output.len(), 1024, "Output buffer must be of size 1024");
1184        debug_assert!(
1185            width <= Self::T,
1186            "Width must be less than or equal to {}",
1187            Self::T
1188        );
1189
1190        match width {
1191            0 => {
1192                output.fill(MaybeUninit::new(0));
1193            }
1194            1 => unpack_64_1(
1195                array_ref![input, 0, 1024 / 64],
1196                array_mut_ref![output, 0, 1024],
1197            ),
1198            2 => unpack_64_2(
1199                array_ref![input, 0, 1024 * 2 / 64],
1200                array_mut_ref![output, 0, 1024],
1201            ),
1202            3 => unpack_64_3(
1203                array_ref![input, 0, 1024 * 3 / 64],
1204                array_mut_ref![output, 0, 1024],
1205            ),
1206            4 => unpack_64_4(
1207                array_ref![input, 0, 1024 * 4 / 64],
1208                array_mut_ref![output, 0, 1024],
1209            ),
1210            5 => unpack_64_5(
1211                array_ref![input, 0, 1024 * 5 / 64],
1212                array_mut_ref![output, 0, 1024],
1213            ),
1214            6 => unpack_64_6(
1215                array_ref![input, 0, 1024 * 6 / 64],
1216                array_mut_ref![output, 0, 1024],
1217            ),
1218            7 => unpack_64_7(
1219                array_ref![input, 0, 1024 * 7 / 64],
1220                array_mut_ref![output, 0, 1024],
1221            ),
1222            8 => unpack_64_8(
1223                array_ref![input, 0, 1024 * 8 / 64],
1224                array_mut_ref![output, 0, 1024],
1225            ),
1226            9 => unpack_64_9(
1227                array_ref![input, 0, 1024 * 9 / 64],
1228                array_mut_ref![output, 0, 1024],
1229            ),
1230
1231            10 => unpack_64_10(
1232                array_ref![input, 0, 1024 * 10 / 64],
1233                array_mut_ref![output, 0, 1024],
1234            ),
1235            11 => unpack_64_11(
1236                array_ref![input, 0, 1024 * 11 / 64],
1237                array_mut_ref![output, 0, 1024],
1238            ),
1239            12 => unpack_64_12(
1240                array_ref![input, 0, 1024 * 12 / 64],
1241                array_mut_ref![output, 0, 1024],
1242            ),
1243            13 => unpack_64_13(
1244                array_ref![input, 0, 1024 * 13 / 64],
1245                array_mut_ref![output, 0, 1024],
1246            ),
1247            14 => unpack_64_14(
1248                array_ref![input, 0, 1024 * 14 / 64],
1249                array_mut_ref![output, 0, 1024],
1250            ),
1251            15 => unpack_64_15(
1252                array_ref![input, 0, 1024 * 15 / 64],
1253                array_mut_ref![output, 0, 1024],
1254            ),
1255            16 => unpack_64_16(
1256                array_ref![input, 0, 1024 * 16 / 64],
1257                array_mut_ref![output, 0, 1024],
1258            ),
1259            17 => unpack_64_17(
1260                array_ref![input, 0, 1024 * 17 / 64],
1261                array_mut_ref![output, 0, 1024],
1262            ),
1263            18 => unpack_64_18(
1264                array_ref![input, 0, 1024 * 18 / 64],
1265                array_mut_ref![output, 0, 1024],
1266            ),
1267            19 => unpack_64_19(
1268                array_ref![input, 0, 1024 * 19 / 64],
1269                array_mut_ref![output, 0, 1024],
1270            ),
1271
1272            20 => unpack_64_20(
1273                array_ref![input, 0, 1024 * 20 / 64],
1274                array_mut_ref![output, 0, 1024],
1275            ),
1276            21 => unpack_64_21(
1277                array_ref![input, 0, 1024 * 21 / 64],
1278                array_mut_ref![output, 0, 1024],
1279            ),
1280            22 => unpack_64_22(
1281                array_ref![input, 0, 1024 * 22 / 64],
1282                array_mut_ref![output, 0, 1024],
1283            ),
1284            23 => unpack_64_23(
1285                array_ref![input, 0, 1024 * 23 / 64],
1286                array_mut_ref![output, 0, 1024],
1287            ),
1288            24 => unpack_64_24(
1289                array_ref![input, 0, 1024 * 24 / 64],
1290                array_mut_ref![output, 0, 1024],
1291            ),
1292            25 => unpack_64_25(
1293                array_ref![input, 0, 1024 * 25 / 64],
1294                array_mut_ref![output, 0, 1024],
1295            ),
1296            26 => unpack_64_26(
1297                array_ref![input, 0, 1024 * 26 / 64],
1298                array_mut_ref![output, 0, 1024],
1299            ),
1300            27 => unpack_64_27(
1301                array_ref![input, 0, 1024 * 27 / 64],
1302                array_mut_ref![output, 0, 1024],
1303            ),
1304            28 => unpack_64_28(
1305                array_ref![input, 0, 1024 * 28 / 64],
1306                array_mut_ref![output, 0, 1024],
1307            ),
1308            29 => unpack_64_29(
1309                array_ref![input, 0, 1024 * 29 / 64],
1310                array_mut_ref![output, 0, 1024],
1311            ),
1312
1313            30 => unpack_64_30(
1314                array_ref![input, 0, 1024 * 30 / 64],
1315                array_mut_ref![output, 0, 1024],
1316            ),
1317            31 => unpack_64_31(
1318                array_ref![input, 0, 1024 * 31 / 64],
1319                array_mut_ref![output, 0, 1024],
1320            ),
1321            32 => unpack_64_32(
1322                array_ref![input, 0, 1024 * 32 / 64],
1323                array_mut_ref![output, 0, 1024],
1324            ),
1325            33 => unpack_64_33(
1326                array_ref![input, 0, 1024 * 33 / 64],
1327                array_mut_ref![output, 0, 1024],
1328            ),
1329            34 => unpack_64_34(
1330                array_ref![input, 0, 1024 * 34 / 64],
1331                array_mut_ref![output, 0, 1024],
1332            ),
1333            35 => unpack_64_35(
1334                array_ref![input, 0, 1024 * 35 / 64],
1335                array_mut_ref![output, 0, 1024],
1336            ),
1337            36 => unpack_64_36(
1338                array_ref![input, 0, 1024 * 36 / 64],
1339                array_mut_ref![output, 0, 1024],
1340            ),
1341            37 => unpack_64_37(
1342                array_ref![input, 0, 1024 * 37 / 64],
1343                array_mut_ref![output, 0, 1024],
1344            ),
1345            38 => unpack_64_38(
1346                array_ref![input, 0, 1024 * 38 / 64],
1347                array_mut_ref![output, 0, 1024],
1348            ),
1349            39 => unpack_64_39(
1350                array_ref![input, 0, 1024 * 39 / 64],
1351                array_mut_ref![output, 0, 1024],
1352            ),
1353
1354            40 => unpack_64_40(
1355                array_ref![input, 0, 1024 * 40 / 64],
1356                array_mut_ref![output, 0, 1024],
1357            ),
1358            41 => unpack_64_41(
1359                array_ref![input, 0, 1024 * 41 / 64],
1360                array_mut_ref![output, 0, 1024],
1361            ),
1362            42 => unpack_64_42(
1363                array_ref![input, 0, 1024 * 42 / 64],
1364                array_mut_ref![output, 0, 1024],
1365            ),
1366            43 => unpack_64_43(
1367                array_ref![input, 0, 1024 * 43 / 64],
1368                array_mut_ref![output, 0, 1024],
1369            ),
1370            44 => unpack_64_44(
1371                array_ref![input, 0, 1024 * 44 / 64],
1372                array_mut_ref![output, 0, 1024],
1373            ),
1374            45 => unpack_64_45(
1375                array_ref![input, 0, 1024 * 45 / 64],
1376                array_mut_ref![output, 0, 1024],
1377            ),
1378            46 => unpack_64_46(
1379                array_ref![input, 0, 1024 * 46 / 64],
1380                array_mut_ref![output, 0, 1024],
1381            ),
1382            47 => unpack_64_47(
1383                array_ref![input, 0, 1024 * 47 / 64],
1384                array_mut_ref![output, 0, 1024],
1385            ),
1386            48 => unpack_64_48(
1387                array_ref![input, 0, 1024 * 48 / 64],
1388                array_mut_ref![output, 0, 1024],
1389            ),
1390            49 => unpack_64_49(
1391                array_ref![input, 0, 1024 * 49 / 64],
1392                array_mut_ref![output, 0, 1024],
1393            ),
1394
1395            50 => unpack_64_50(
1396                array_ref![input, 0, 1024 * 50 / 64],
1397                array_mut_ref![output, 0, 1024],
1398            ),
1399            51 => unpack_64_51(
1400                array_ref![input, 0, 1024 * 51 / 64],
1401                array_mut_ref![output, 0, 1024],
1402            ),
1403            52 => unpack_64_52(
1404                array_ref![input, 0, 1024 * 52 / 64],
1405                array_mut_ref![output, 0, 1024],
1406            ),
1407            53 => unpack_64_53(
1408                array_ref![input, 0, 1024 * 53 / 64],
1409                array_mut_ref![output, 0, 1024],
1410            ),
1411            54 => unpack_64_54(
1412                array_ref![input, 0, 1024 * 54 / 64],
1413                array_mut_ref![output, 0, 1024],
1414            ),
1415            55 => unpack_64_55(
1416                array_ref![input, 0, 1024 * 55 / 64],
1417                array_mut_ref![output, 0, 1024],
1418            ),
1419            56 => unpack_64_56(
1420                array_ref![input, 0, 1024 * 56 / 64],
1421                array_mut_ref![output, 0, 1024],
1422            ),
1423            57 => unpack_64_57(
1424                array_ref![input, 0, 1024 * 57 / 64],
1425                array_mut_ref![output, 0, 1024],
1426            ),
1427            58 => unpack_64_58(
1428                array_ref![input, 0, 1024 * 58 / 64],
1429                array_mut_ref![output, 0, 1024],
1430            ),
1431            59 => unpack_64_59(
1432                array_ref![input, 0, 1024 * 59 / 64],
1433                array_mut_ref![output, 0, 1024],
1434            ),
1435
1436            60 => unpack_64_60(
1437                array_ref![input, 0, 1024 * 60 / 64],
1438                array_mut_ref![output, 0, 1024],
1439            ),
1440            61 => unpack_64_61(
1441                array_ref![input, 0, 1024 * 61 / 64],
1442                array_mut_ref![output, 0, 1024],
1443            ),
1444            62 => unpack_64_62(
1445                array_ref![input, 0, 1024 * 62 / 64],
1446                array_mut_ref![output, 0, 1024],
1447            ),
1448            63 => unpack_64_63(
1449                array_ref![input, 0, 1024 * 63 / 64],
1450                array_mut_ref![output, 0, 1024],
1451            ),
1452            64 => unpack_64_64(
1453                array_ref![input, 0, 1024 * 64 / 64],
1454                array_mut_ref![output, 0, 1024],
1455            ),
1456
1457            _ => unreachable!("Unsupported width: {}", width),
1458        }
1459    }
1460}
1461
1462macro_rules! unpack_8 {
1463    ($name:ident, $bits:expr) => {
1464        fn $name(input: &[u8; 1024 * $bits / u8::T], output: &mut [MaybeUninit<u8>; 1024]) {
1465            for lane in 0..u8::LANES {
1466                unpack!(u8, $bits, input, lane, |$idx, $elem| {
1467                    output[$idx].write($elem);
1468                });
1469            }
1470        }
1471    };
1472}
1473
1474unpack_8!(unpack_8_1, 1);
1475unpack_8!(unpack_8_2, 2);
1476unpack_8!(unpack_8_3, 3);
1477unpack_8!(unpack_8_4, 4);
1478unpack_8!(unpack_8_5, 5);
1479unpack_8!(unpack_8_6, 6);
1480unpack_8!(unpack_8_7, 7);
1481unpack_8!(unpack_8_8, 8);
1482
1483macro_rules! pack_8 {
1484    ($name:ident, $bits:expr) => {
1485        fn $name(input: &[u8; 1024], output: &mut [MaybeUninit<u8>; 1024 * $bits / u8::T]) {
1486            for lane in 0..u8::LANES {
1487                pack!(u8, $bits, output, lane, |$idx| { input[$idx] });
1488            }
1489        }
1490    };
1491}
1492pack_8!(pack_8_1, 1);
1493pack_8!(pack_8_2, 2);
1494pack_8!(pack_8_3, 3);
1495pack_8!(pack_8_4, 4);
1496pack_8!(pack_8_5, 5);
1497pack_8!(pack_8_6, 6);
1498pack_8!(pack_8_7, 7);
1499pack_8!(pack_8_8, 8);
1500
1501macro_rules! unpack_16 {
1502    ($name:ident, $bits:expr) => {
1503        fn $name(input: &[u16; 1024 * $bits / u16::T], output: &mut [MaybeUninit<u16>; 1024]) {
1504            for lane in 0..u16::LANES {
1505                unpack!(u16, $bits, input, lane, |$idx, $elem| {
1506                    output[$idx].write($elem);
1507                });
1508            }
1509        }
1510    };
1511}
1512
1513unpack_16!(unpack_16_1, 1);
1514unpack_16!(unpack_16_2, 2);
1515unpack_16!(unpack_16_3, 3);
1516unpack_16!(unpack_16_4, 4);
1517unpack_16!(unpack_16_5, 5);
1518unpack_16!(unpack_16_6, 6);
1519unpack_16!(unpack_16_7, 7);
1520unpack_16!(unpack_16_8, 8);
1521unpack_16!(unpack_16_9, 9);
1522unpack_16!(unpack_16_10, 10);
1523unpack_16!(unpack_16_11, 11);
1524unpack_16!(unpack_16_12, 12);
1525unpack_16!(unpack_16_13, 13);
1526unpack_16!(unpack_16_14, 14);
1527unpack_16!(unpack_16_15, 15);
1528unpack_16!(unpack_16_16, 16);
1529
1530macro_rules! pack_16 {
1531    ($name:ident, $bits:expr) => {
1532        fn $name(input: &[u16; 1024], output: &mut [MaybeUninit<u16>; 1024 * $bits / u16::T]) {
1533            for lane in 0..u16::LANES {
1534                pack!(u16, $bits, output, lane, |$idx| { input[$idx] });
1535            }
1536        }
1537    };
1538}
1539
1540pack_16!(pack_16_1, 1);
1541pack_16!(pack_16_2, 2);
1542pack_16!(pack_16_3, 3);
1543pack_16!(pack_16_4, 4);
1544pack_16!(pack_16_5, 5);
1545pack_16!(pack_16_6, 6);
1546pack_16!(pack_16_7, 7);
1547pack_16!(pack_16_8, 8);
1548pack_16!(pack_16_9, 9);
1549pack_16!(pack_16_10, 10);
1550pack_16!(pack_16_11, 11);
1551pack_16!(pack_16_12, 12);
1552pack_16!(pack_16_13, 13);
1553pack_16!(pack_16_14, 14);
1554pack_16!(pack_16_15, 15);
1555pack_16!(pack_16_16, 16);
1556
1557macro_rules! unpack_32 {
1558    ($name:ident, $bit_width:expr) => {
1559        fn $name(input: &[u32; 1024 * $bit_width / u32::T], output: &mut [MaybeUninit<u32>; 1024]) {
1560            for lane in 0..u32::LANES {
1561                unpack!(u32, $bit_width, input, lane, |$idx, $elem| {
1562                    output[$idx].write($elem);
1563                });
1564            }
1565        }
1566    };
1567}
1568
1569unpack_32!(unpack_32_1, 1);
1570unpack_32!(unpack_32_2, 2);
1571unpack_32!(unpack_32_3, 3);
1572unpack_32!(unpack_32_4, 4);
1573unpack_32!(unpack_32_5, 5);
1574unpack_32!(unpack_32_6, 6);
1575unpack_32!(unpack_32_7, 7);
1576unpack_32!(unpack_32_8, 8);
1577unpack_32!(unpack_32_9, 9);
1578unpack_32!(unpack_32_10, 10);
1579unpack_32!(unpack_32_11, 11);
1580unpack_32!(unpack_32_12, 12);
1581unpack_32!(unpack_32_13, 13);
1582unpack_32!(unpack_32_14, 14);
1583unpack_32!(unpack_32_15, 15);
1584unpack_32!(unpack_32_16, 16);
1585unpack_32!(unpack_32_17, 17);
1586unpack_32!(unpack_32_18, 18);
1587unpack_32!(unpack_32_19, 19);
1588unpack_32!(unpack_32_20, 20);
1589unpack_32!(unpack_32_21, 21);
1590unpack_32!(unpack_32_22, 22);
1591unpack_32!(unpack_32_23, 23);
1592unpack_32!(unpack_32_24, 24);
1593unpack_32!(unpack_32_25, 25);
1594unpack_32!(unpack_32_26, 26);
1595unpack_32!(unpack_32_27, 27);
1596unpack_32!(unpack_32_28, 28);
1597unpack_32!(unpack_32_29, 29);
1598unpack_32!(unpack_32_30, 30);
1599unpack_32!(unpack_32_31, 31);
1600unpack_32!(unpack_32_32, 32);
1601
1602macro_rules! pack_32 {
1603    ($name:ident, $bits:expr) => {
1604        fn $name(
1605            input: &[u32; 1024],
1606            output: &mut [MaybeUninit<u32>; 1024 * $bits / u32::BITS as usize],
1607        ) {
1608            for lane in 0..u32::LANES {
1609                pack!(u32, $bits, output, lane, |$idx| { input[$idx] });
1610            }
1611        }
1612    };
1613}
1614
1615pack_32!(pack_32_1, 1);
1616pack_32!(pack_32_2, 2);
1617pack_32!(pack_32_3, 3);
1618pack_32!(pack_32_4, 4);
1619pack_32!(pack_32_5, 5);
1620pack_32!(pack_32_6, 6);
1621pack_32!(pack_32_7, 7);
1622pack_32!(pack_32_8, 8);
1623pack_32!(pack_32_9, 9);
1624pack_32!(pack_32_10, 10);
1625pack_32!(pack_32_11, 11);
1626pack_32!(pack_32_12, 12);
1627pack_32!(pack_32_13, 13);
1628pack_32!(pack_32_14, 14);
1629pack_32!(pack_32_15, 15);
1630pack_32!(pack_32_16, 16);
1631pack_32!(pack_32_17, 17);
1632pack_32!(pack_32_18, 18);
1633pack_32!(pack_32_19, 19);
1634pack_32!(pack_32_20, 20);
1635pack_32!(pack_32_21, 21);
1636pack_32!(pack_32_22, 22);
1637pack_32!(pack_32_23, 23);
1638pack_32!(pack_32_24, 24);
1639pack_32!(pack_32_25, 25);
1640pack_32!(pack_32_26, 26);
1641pack_32!(pack_32_27, 27);
1642pack_32!(pack_32_28, 28);
1643pack_32!(pack_32_29, 29);
1644pack_32!(pack_32_30, 30);
1645pack_32!(pack_32_31, 31);
1646pack_32!(pack_32_32, 32);
1647
1648macro_rules! unpack_64 {
1649    ($name:ident, $bit_width:expr) => {
1650        fn $name(input: &[u64; 1024 * $bit_width / u64::T], output: &mut [MaybeUninit<u64>; 1024]) {
1651            for lane in 0..u64::LANES {
1652                unpack!(u64, $bit_width, input, lane, |$idx, $elem| {
1653                    output[$idx].write($elem);
1654                });
1655            }
1656        }
1657    };
1658}
1659
1660unpack_64!(unpack_64_1, 1);
1661unpack_64!(unpack_64_2, 2);
1662unpack_64!(unpack_64_3, 3);
1663unpack_64!(unpack_64_4, 4);
1664unpack_64!(unpack_64_5, 5);
1665unpack_64!(unpack_64_6, 6);
1666unpack_64!(unpack_64_7, 7);
1667unpack_64!(unpack_64_8, 8);
1668unpack_64!(unpack_64_9, 9);
1669unpack_64!(unpack_64_10, 10);
1670unpack_64!(unpack_64_11, 11);
1671unpack_64!(unpack_64_12, 12);
1672unpack_64!(unpack_64_13, 13);
1673unpack_64!(unpack_64_14, 14);
1674unpack_64!(unpack_64_15, 15);
1675unpack_64!(unpack_64_16, 16);
1676unpack_64!(unpack_64_17, 17);
1677unpack_64!(unpack_64_18, 18);
1678unpack_64!(unpack_64_19, 19);
1679unpack_64!(unpack_64_20, 20);
1680unpack_64!(unpack_64_21, 21);
1681unpack_64!(unpack_64_22, 22);
1682unpack_64!(unpack_64_23, 23);
1683unpack_64!(unpack_64_24, 24);
1684unpack_64!(unpack_64_25, 25);
1685unpack_64!(unpack_64_26, 26);
1686unpack_64!(unpack_64_27, 27);
1687unpack_64!(unpack_64_28, 28);
1688unpack_64!(unpack_64_29, 29);
1689unpack_64!(unpack_64_30, 30);
1690unpack_64!(unpack_64_31, 31);
1691unpack_64!(unpack_64_32, 32);
1692
1693unpack_64!(unpack_64_33, 33);
1694unpack_64!(unpack_64_34, 34);
1695unpack_64!(unpack_64_35, 35);
1696unpack_64!(unpack_64_36, 36);
1697unpack_64!(unpack_64_37, 37);
1698unpack_64!(unpack_64_38, 38);
1699unpack_64!(unpack_64_39, 39);
1700unpack_64!(unpack_64_40, 40);
1701unpack_64!(unpack_64_41, 41);
1702unpack_64!(unpack_64_42, 42);
1703unpack_64!(unpack_64_43, 43);
1704unpack_64!(unpack_64_44, 44);
1705unpack_64!(unpack_64_45, 45);
1706unpack_64!(unpack_64_46, 46);
1707unpack_64!(unpack_64_47, 47);
1708unpack_64!(unpack_64_48, 48);
1709unpack_64!(unpack_64_49, 49);
1710unpack_64!(unpack_64_50, 50);
1711unpack_64!(unpack_64_51, 51);
1712unpack_64!(unpack_64_52, 52);
1713unpack_64!(unpack_64_53, 53);
1714unpack_64!(unpack_64_54, 54);
1715unpack_64!(unpack_64_55, 55);
1716unpack_64!(unpack_64_56, 56);
1717unpack_64!(unpack_64_57, 57);
1718unpack_64!(unpack_64_58, 58);
1719unpack_64!(unpack_64_59, 59);
1720unpack_64!(unpack_64_60, 60);
1721unpack_64!(unpack_64_61, 61);
1722unpack_64!(unpack_64_62, 62);
1723unpack_64!(unpack_64_63, 63);
1724unpack_64!(unpack_64_64, 64);
1725
1726macro_rules! pack_64 {
1727    ($name:ident, $bits:expr) => {
1728        fn $name(
1729            input: &[u64; 1024],
1730            output: &mut [MaybeUninit<u64>; 1024 * $bits / u64::BITS as usize],
1731        ) {
1732            for lane in 0..u64::LANES {
1733                pack!(u64, $bits, output, lane, |$idx| { input[$idx] });
1734            }
1735        }
1736    };
1737}
1738
1739pack_64!(pack_64_1, 1);
1740pack_64!(pack_64_2, 2);
1741pack_64!(pack_64_3, 3);
1742pack_64!(pack_64_4, 4);
1743pack_64!(pack_64_5, 5);
1744pack_64!(pack_64_6, 6);
1745pack_64!(pack_64_7, 7);
1746pack_64!(pack_64_8, 8);
1747pack_64!(pack_64_9, 9);
1748pack_64!(pack_64_10, 10);
1749pack_64!(pack_64_11, 11);
1750pack_64!(pack_64_12, 12);
1751pack_64!(pack_64_13, 13);
1752pack_64!(pack_64_14, 14);
1753pack_64!(pack_64_15, 15);
1754pack_64!(pack_64_16, 16);
1755pack_64!(pack_64_17, 17);
1756pack_64!(pack_64_18, 18);
1757pack_64!(pack_64_19, 19);
1758pack_64!(pack_64_20, 20);
1759pack_64!(pack_64_21, 21);
1760pack_64!(pack_64_22, 22);
1761pack_64!(pack_64_23, 23);
1762pack_64!(pack_64_24, 24);
1763pack_64!(pack_64_25, 25);
1764pack_64!(pack_64_26, 26);
1765pack_64!(pack_64_27, 27);
1766pack_64!(pack_64_28, 28);
1767pack_64!(pack_64_29, 29);
1768pack_64!(pack_64_30, 30);
1769pack_64!(pack_64_31, 31);
1770pack_64!(pack_64_32, 32);
1771
1772pack_64!(pack_64_33, 33);
1773pack_64!(pack_64_34, 34);
1774pack_64!(pack_64_35, 35);
1775pack_64!(pack_64_36, 36);
1776pack_64!(pack_64_37, 37);
1777pack_64!(pack_64_38, 38);
1778pack_64!(pack_64_39, 39);
1779pack_64!(pack_64_40, 40);
1780pack_64!(pack_64_41, 41);
1781pack_64!(pack_64_42, 42);
1782pack_64!(pack_64_43, 43);
1783pack_64!(pack_64_44, 44);
1784pack_64!(pack_64_45, 45);
1785pack_64!(pack_64_46, 46);
1786pack_64!(pack_64_47, 47);
1787pack_64!(pack_64_48, 48);
1788pack_64!(pack_64_49, 49);
1789pack_64!(pack_64_50, 50);
1790pack_64!(pack_64_51, 51);
1791pack_64!(pack_64_52, 52);
1792pack_64!(pack_64_53, 53);
1793pack_64!(pack_64_54, 54);
1794pack_64!(pack_64_55, 55);
1795pack_64!(pack_64_56, 56);
1796pack_64!(pack_64_57, 57);
1797pack_64!(pack_64_58, 58);
1798pack_64!(pack_64_59, 59);
1799pack_64!(pack_64_60, 60);
1800pack_64!(pack_64_61, 61);
1801pack_64!(pack_64_62, 62);
1802pack_64!(pack_64_63, 63);
1803pack_64!(pack_64_64, 64);
1804
1805#[cfg(test)]
1806mod test {
1807    use super::*;
1808    use bitpacking::{BitPacker as ExternalBitPacker, BitPacker4x as ExternalBitPacker4x};
1809    use core::array;
1810    // a fast random number generator
1811    pub struct XorShift {
1812        state: u64,
1813    }
1814
1815    impl XorShift {
1816        pub fn new(seed: u64) -> Self {
1817            Self { state: seed }
1818        }
1819
1820        pub fn next(&mut self) -> u64 {
1821            let mut x = self.state;
1822            x ^= x << 13;
1823            x ^= x >> 7;
1824            x ^= x << 17;
1825            self.state = x;
1826            x
1827        }
1828    }
1829
1830    fn mask_for_width(width: u8) -> u32 {
1831        match width {
1832            0 => 0,
1833            32 => u32::MAX,
1834            _ => (1u32 << width) - 1,
1835        }
1836    }
1837
1838    fn raw_bitpacker4x_case(width: u8, seed: u64) -> Vec<u32> {
1839        let mask = mask_for_width(width);
1840        let mut rng = XorShift::new(seed);
1841        (0..BitPacker4x::BLOCK_LEN)
1842            .map(|idx| match seed % 4 {
1843                0 => 0,
1844                1 => mask,
1845                2 => idx as u32 & mask,
1846                _ => (rng.next() as u32) & mask,
1847            })
1848            .collect()
1849    }
1850
1851    fn sorted_bitpacker4x_case(width: u8, seed: u64) -> (u32, Vec<u32>) {
1852        if width == 0 {
1853            return (17, vec![17; BitPacker4x::BLOCK_LEN]);
1854        }
1855        if width == 32 {
1856            return (0, vec![u32::MAX; BitPacker4x::BLOCK_LEN]);
1857        }
1858
1859        let mask = mask_for_width(width).min(127);
1860        let mut rng = XorShift::new(seed);
1861        let mut current = 17u32;
1862        let values = (0..BitPacker4x::BLOCK_LEN)
1863            .map(|_| {
1864                current += (rng.next() as u32) & mask;
1865                current
1866            })
1867            .collect();
1868        (17, values)
1869    }
1870
1871    #[test]
1872    fn test_bitpacker4x_raw_compatible_with_external_bitpacking() {
1873        let ours = BitPacker4x::new();
1874        let external = ExternalBitPacker4x::new();
1875
1876        for width in 0..=32 {
1877            for seed in [0, 1, 2, 123456789] {
1878                let values = raw_bitpacker4x_case(width, seed);
1879                assert_eq!(ours.num_bits(&values), external.num_bits(&values));
1880
1881                let mut actual = vec![0u8; BitPacker4x::compressed_block_size(width)];
1882                let actual_len = ours.compress(&values, &mut actual, width);
1883
1884                let mut expected = vec![0u8; ExternalBitPacker4x::compressed_block_size(width)];
1885                let expected_len = external.compress(&values, &mut expected, width);
1886
1887                assert_eq!(actual_len, expected_len);
1888                assert_eq!(actual, expected, "width {width} seed {seed}");
1889
1890                let mut decoded = vec![0u32; BitPacker4x::BLOCK_LEN];
1891                let consumed = ours.decompress(&actual, &mut decoded, width);
1892                assert_eq!(consumed, actual_len);
1893                assert_eq!(decoded, values);
1894            }
1895        }
1896    }
1897
1898    #[test]
1899    fn test_bitpacker4x_sorted_compatible_with_external_bitpacking() {
1900        let ours = BitPacker4x::new();
1901        let external = ExternalBitPacker4x::new();
1902
1903        for width in 0..=32 {
1904            for seed in [0, 1, 2, 123456789] {
1905                let (initial, values) = sorted_bitpacker4x_case(width, seed);
1906                assert_eq!(
1907                    ours.num_bits_sorted(initial, &values),
1908                    external.num_bits_sorted(initial, &values)
1909                );
1910
1911                let mut actual = vec![0u8; BitPacker4x::compressed_block_size(width)];
1912                let actual_len = ours.compress_sorted(initial, &values, &mut actual, width);
1913
1914                let mut expected = vec![0u8; ExternalBitPacker4x::compressed_block_size(width)];
1915                let expected_len = external.compress_sorted(initial, &values, &mut expected, width);
1916
1917                assert_eq!(actual_len, expected_len);
1918                assert_eq!(actual, expected, "width {width} seed {seed}");
1919
1920                let mut decoded = vec![0u32; BitPacker4x::BLOCK_LEN];
1921                let consumed = ours.decompress_sorted(initial, &actual, &mut decoded, width);
1922                assert_eq!(consumed, actual_len);
1923                assert_eq!(decoded, values);
1924            }
1925        }
1926    }
1927
1928    // a macro version of this function generalize u8, u16, u32, u64 takes very long time for a test build, so I
1929    // write it for each type separately
1930    fn pack_unpack_u8(bit_width: usize) {
1931        let mut values: [u8; 1024] = [0; 1024];
1932        let mut rng = XorShift::new(123456789);
1933        for value in &mut values {
1934            *value = (rng.next() % (1 << bit_width)) as u8;
1935        }
1936
1937        let mut packed = vec![MaybeUninit::uninit(); 1024 * bit_width / 8];
1938        for lane in 0..u8::LANES {
1939            // Always loop over lanes first. This is what the compiler vectorizes.
1940            pack!(u8, bit_width, packed, lane, |$pos| {
1941                values[$pos]
1942            });
1943        }
1944        // The pack kernel writes every element of the packed output.
1945        let packed =
1946            unsafe { core::slice::from_raw_parts(packed.as_ptr().cast::<u8>(), packed.len()) };
1947
1948        let mut unpacked: [u8; 1024] = [0; 1024];
1949        for lane in 0..u8::LANES {
1950            // Always loop over lanes first. This is what the compiler vectorizes.
1951            unpack!(u8, bit_width, packed, lane, |$idx, $elem| {
1952                unpacked[$idx] = $elem;
1953            });
1954        }
1955
1956        assert_eq!(values, unpacked);
1957    }
1958
1959    fn pack_unpack_u16(bit_width: usize) {
1960        let mut values: [u16; 1024] = [0; 1024];
1961        let mut rng = XorShift::new(123456789);
1962        for value in &mut values {
1963            *value = (rng.next() % (1 << bit_width)) as u16;
1964        }
1965
1966        let mut packed = vec![MaybeUninit::uninit(); 1024 * bit_width / 16];
1967        for lane in 0..u16::LANES {
1968            // Always loop over lanes first. This is what the compiler vectorizes.
1969            pack!(u16, bit_width, packed, lane, |$pos| {
1970                values[$pos]
1971            });
1972        }
1973        // The pack kernel writes every element of the packed output.
1974        let packed =
1975            unsafe { core::slice::from_raw_parts(packed.as_ptr().cast::<u16>(), packed.len()) };
1976
1977        let mut unpacked: [u16; 1024] = [0; 1024];
1978        for lane in 0..u16::LANES {
1979            // Always loop over lanes first. This is what the compiler vectorizes.
1980            unpack!(u16, bit_width, packed, lane, |$idx, $elem| {
1981                unpacked[$idx] = $elem;
1982            });
1983        }
1984
1985        assert_eq!(values, unpacked);
1986    }
1987
1988    fn pack_unpack_u32(bit_width: usize) {
1989        let mut values: [u32; 1024] = [0; 1024];
1990        let mut rng = XorShift::new(123456789);
1991        for value in &mut values {
1992            *value = (rng.next() % (1 << bit_width)) as u32;
1993        }
1994
1995        let mut packed = vec![MaybeUninit::uninit(); 1024 * bit_width / 32];
1996        for lane in 0..u32::LANES {
1997            // Always loop over lanes first. This is what the compiler vectorizes.
1998            pack!(u32, bit_width, packed, lane, |$pos| {
1999                values[$pos]
2000            });
2001        }
2002        // The pack kernel writes every element of the packed output.
2003        let packed =
2004            unsafe { core::slice::from_raw_parts(packed.as_ptr().cast::<u32>(), packed.len()) };
2005
2006        let mut unpacked: [u32; 1024] = [0; 1024];
2007        for lane in 0..u32::LANES {
2008            // Always loop over lanes first. This is what the compiler vectorizes.
2009            unpack!(u32, bit_width, packed, lane, |$idx, $elem| {
2010                unpacked[$idx] = $elem;
2011            });
2012        }
2013
2014        assert_eq!(values, unpacked);
2015    }
2016
2017    fn pack_unpack_u64(bit_width: usize) {
2018        let mut values: [u64; 1024] = [0; 1024];
2019        let mut rng = XorShift::new(123456789);
2020        if bit_width == 64 {
2021            for value in &mut values {
2022                *value = rng.next();
2023            }
2024        } else {
2025            for value in &mut values {
2026                *value = rng.next() % (1 << bit_width);
2027            }
2028        }
2029
2030        let mut packed = vec![MaybeUninit::uninit(); 1024 * bit_width / 64];
2031        for lane in 0..u64::LANES {
2032            // Always loop over lanes first. This is what the compiler vectorizes.
2033            pack!(u64, bit_width, packed, lane, |$pos| {
2034                values[$pos]
2035            });
2036        }
2037        // The pack kernel writes every element of the packed output.
2038        let packed =
2039            unsafe { core::slice::from_raw_parts(packed.as_ptr().cast::<u64>(), packed.len()) };
2040
2041        let mut unpacked: [u64; 1024] = [0; 1024];
2042        for lane in 0..u64::LANES {
2043            // Always loop over lanes first. This is what the compiler vectorizes.
2044            unpack!(u64, bit_width, packed, lane, |$idx, $elem| {
2045                unpacked[$idx] = $elem;
2046            });
2047        }
2048
2049        assert_eq!(values, unpacked);
2050    }
2051
2052    #[test]
2053    fn test_pack() {
2054        pack_unpack_u8(0);
2055        pack_unpack_u8(1);
2056        pack_unpack_u8(2);
2057        pack_unpack_u8(3);
2058        pack_unpack_u8(4);
2059        pack_unpack_u8(5);
2060        pack_unpack_u8(6);
2061        pack_unpack_u8(7);
2062        pack_unpack_u8(8);
2063
2064        pack_unpack_u16(0);
2065        pack_unpack_u16(1);
2066        pack_unpack_u16(2);
2067        pack_unpack_u16(3);
2068        pack_unpack_u16(4);
2069        pack_unpack_u16(5);
2070        pack_unpack_u16(6);
2071        pack_unpack_u16(7);
2072        pack_unpack_u16(8);
2073        pack_unpack_u16(9);
2074        pack_unpack_u16(10);
2075        pack_unpack_u16(11);
2076        pack_unpack_u16(12);
2077        pack_unpack_u16(13);
2078        pack_unpack_u16(14);
2079        pack_unpack_u16(15);
2080        pack_unpack_u16(16);
2081
2082        pack_unpack_u32(0);
2083        pack_unpack_u32(1);
2084        pack_unpack_u32(2);
2085        pack_unpack_u32(3);
2086        pack_unpack_u32(4);
2087        pack_unpack_u32(5);
2088        pack_unpack_u32(6);
2089        pack_unpack_u32(7);
2090        pack_unpack_u32(8);
2091        pack_unpack_u32(9);
2092        pack_unpack_u32(10);
2093        pack_unpack_u32(11);
2094        pack_unpack_u32(12);
2095        pack_unpack_u32(13);
2096        pack_unpack_u32(14);
2097        pack_unpack_u32(15);
2098        pack_unpack_u32(16);
2099        pack_unpack_u32(17);
2100        pack_unpack_u32(18);
2101        pack_unpack_u32(19);
2102        pack_unpack_u32(20);
2103        pack_unpack_u32(21);
2104        pack_unpack_u32(22);
2105        pack_unpack_u32(23);
2106        pack_unpack_u32(24);
2107        pack_unpack_u32(25);
2108        pack_unpack_u32(26);
2109        pack_unpack_u32(27);
2110        pack_unpack_u32(28);
2111        pack_unpack_u32(29);
2112        pack_unpack_u32(30);
2113        pack_unpack_u32(31);
2114        pack_unpack_u32(32);
2115
2116        pack_unpack_u64(0);
2117        pack_unpack_u64(1);
2118        pack_unpack_u64(2);
2119        pack_unpack_u64(3);
2120        pack_unpack_u64(4);
2121        pack_unpack_u64(5);
2122        pack_unpack_u64(6);
2123        pack_unpack_u64(7);
2124        pack_unpack_u64(8);
2125        pack_unpack_u64(9);
2126        pack_unpack_u64(10);
2127        pack_unpack_u64(11);
2128        pack_unpack_u64(12);
2129        pack_unpack_u64(13);
2130        pack_unpack_u64(14);
2131        pack_unpack_u64(15);
2132        pack_unpack_u64(16);
2133        pack_unpack_u64(17);
2134        pack_unpack_u64(18);
2135        pack_unpack_u64(19);
2136        pack_unpack_u64(20);
2137        pack_unpack_u64(21);
2138        pack_unpack_u64(22);
2139        pack_unpack_u64(23);
2140        pack_unpack_u64(24);
2141        pack_unpack_u64(25);
2142        pack_unpack_u64(26);
2143        pack_unpack_u64(27);
2144        pack_unpack_u64(28);
2145        pack_unpack_u64(29);
2146        pack_unpack_u64(30);
2147        pack_unpack_u64(31);
2148        pack_unpack_u64(32);
2149        pack_unpack_u64(33);
2150        pack_unpack_u64(34);
2151        pack_unpack_u64(35);
2152        pack_unpack_u64(36);
2153        pack_unpack_u64(37);
2154        pack_unpack_u64(38);
2155        pack_unpack_u64(39);
2156        pack_unpack_u64(40);
2157        pack_unpack_u64(41);
2158        pack_unpack_u64(42);
2159        pack_unpack_u64(43);
2160        pack_unpack_u64(44);
2161        pack_unpack_u64(45);
2162        pack_unpack_u64(46);
2163        pack_unpack_u64(47);
2164        pack_unpack_u64(48);
2165        pack_unpack_u64(49);
2166        pack_unpack_u64(50);
2167        pack_unpack_u64(51);
2168        pack_unpack_u64(52);
2169        pack_unpack_u64(53);
2170        pack_unpack_u64(54);
2171        pack_unpack_u64(55);
2172        pack_unpack_u64(56);
2173        pack_unpack_u64(57);
2174        pack_unpack_u64(58);
2175        pack_unpack_u64(59);
2176        pack_unpack_u64(60);
2177        pack_unpack_u64(61);
2178        pack_unpack_u64(62);
2179        pack_unpack_u64(63);
2180        pack_unpack_u64(64);
2181    }
2182
2183    fn unchecked_pack_unpack_u8(bit_width: usize) {
2184        let mut values = [0u8; 1024];
2185        let mut rng = XorShift::new(123456789);
2186        for value in &mut values {
2187            *value = (rng.next() % (1 << bit_width)) as u8;
2188        }
2189        let mut packed = vec![0; 1024 * bit_width / 8];
2190        unsafe {
2191            BitPacking::unchecked_pack(bit_width, &values, &mut packed);
2192        }
2193        let mut output = [0; 1024];
2194        unsafe { BitPacking::unchecked_unpack(bit_width, &packed, &mut output) };
2195        assert_eq!(values, output);
2196    }
2197
2198    fn unchecked_pack_unpack_u16(bit_width: usize) {
2199        let mut values = [0u16; 1024];
2200        let mut rng = XorShift::new(123456789);
2201        for value in &mut values {
2202            *value = (rng.next() % (1 << bit_width)) as u16;
2203        }
2204        let mut packed = vec![0; 1024 * bit_width / u16::T];
2205        unsafe {
2206            BitPacking::unchecked_pack(bit_width, &values, &mut packed);
2207        }
2208        let mut output = [0; 1024];
2209        unsafe { BitPacking::unchecked_unpack(bit_width, &packed, &mut output) };
2210        assert_eq!(values, output);
2211    }
2212
2213    fn unchecked_pack_unpack_u32(bit_width: usize) {
2214        let mut values = [0u32; 1024];
2215        let mut rng = XorShift::new(123456789);
2216        for value in &mut values {
2217            *value = (rng.next() % (1 << bit_width)) as u32;
2218        }
2219        let mut packed = vec![0; 1024 * bit_width / u32::T];
2220        unsafe {
2221            BitPacking::unchecked_pack(bit_width, &values, &mut packed);
2222        }
2223        let mut output = [0; 1024];
2224        unsafe { BitPacking::unchecked_unpack(bit_width, &packed, &mut output) };
2225        assert_eq!(values, output);
2226    }
2227
2228    fn unchecked_pack_unpack_u64(bit_width: usize) {
2229        let mut values = [0u64; 1024];
2230        let mut rng = XorShift::new(123456789);
2231        if bit_width == 64 {
2232            for value in &mut values {
2233                *value = rng.next();
2234            }
2235        } else {
2236            for value in &mut values {
2237                *value = rng.next() % (1 << bit_width);
2238            }
2239        }
2240        let mut packed = vec![0; 1024 * bit_width / u64::T];
2241        unsafe {
2242            BitPacking::unchecked_pack(bit_width, &values, &mut packed);
2243        }
2244        let mut output = [0; 1024];
2245        unsafe { BitPacking::unchecked_unpack(bit_width, &packed, &mut output) };
2246        assert_eq!(values, output);
2247    }
2248
2249    #[test]
2250    fn test_unchecked_pack() {
2251        let input = array::from_fn(|i| i as u32);
2252        let mut packed = [0; 320];
2253        unsafe { BitPacking::unchecked_pack(10, &input, &mut packed) };
2254        let mut output = [0; 1024];
2255        unsafe { BitPacking::unchecked_unpack(10, &packed, &mut output) };
2256        assert_eq!(input, output);
2257
2258        unchecked_pack_unpack_u8(1);
2259        unchecked_pack_unpack_u8(2);
2260        unchecked_pack_unpack_u8(3);
2261        unchecked_pack_unpack_u8(4);
2262        unchecked_pack_unpack_u8(5);
2263        unchecked_pack_unpack_u8(6);
2264        unchecked_pack_unpack_u8(7);
2265        unchecked_pack_unpack_u8(8);
2266
2267        unchecked_pack_unpack_u16(1);
2268        unchecked_pack_unpack_u16(2);
2269        unchecked_pack_unpack_u16(3);
2270        unchecked_pack_unpack_u16(4);
2271        unchecked_pack_unpack_u16(5);
2272        unchecked_pack_unpack_u16(6);
2273        unchecked_pack_unpack_u16(7);
2274        unchecked_pack_unpack_u16(8);
2275        unchecked_pack_unpack_u16(9);
2276        unchecked_pack_unpack_u16(10);
2277        unchecked_pack_unpack_u16(11);
2278        unchecked_pack_unpack_u16(12);
2279        unchecked_pack_unpack_u16(13);
2280        unchecked_pack_unpack_u16(14);
2281        unchecked_pack_unpack_u16(15);
2282        unchecked_pack_unpack_u16(16);
2283
2284        unchecked_pack_unpack_u32(1);
2285        unchecked_pack_unpack_u32(2);
2286        unchecked_pack_unpack_u32(3);
2287        unchecked_pack_unpack_u32(4);
2288        unchecked_pack_unpack_u32(5);
2289        unchecked_pack_unpack_u32(6);
2290        unchecked_pack_unpack_u32(7);
2291        unchecked_pack_unpack_u32(8);
2292        unchecked_pack_unpack_u32(9);
2293        unchecked_pack_unpack_u32(10);
2294        unchecked_pack_unpack_u32(11);
2295        unchecked_pack_unpack_u32(12);
2296        unchecked_pack_unpack_u32(13);
2297        unchecked_pack_unpack_u32(14);
2298        unchecked_pack_unpack_u32(15);
2299        unchecked_pack_unpack_u32(16);
2300        unchecked_pack_unpack_u32(17);
2301        unchecked_pack_unpack_u32(18);
2302        unchecked_pack_unpack_u32(19);
2303        unchecked_pack_unpack_u32(20);
2304        unchecked_pack_unpack_u32(21);
2305        unchecked_pack_unpack_u32(22);
2306        unchecked_pack_unpack_u32(23);
2307        unchecked_pack_unpack_u32(24);
2308        unchecked_pack_unpack_u32(25);
2309        unchecked_pack_unpack_u32(26);
2310        unchecked_pack_unpack_u32(27);
2311        unchecked_pack_unpack_u32(28);
2312        unchecked_pack_unpack_u32(29);
2313        unchecked_pack_unpack_u32(30);
2314        unchecked_pack_unpack_u32(31);
2315        unchecked_pack_unpack_u32(32);
2316
2317        unchecked_pack_unpack_u64(1);
2318        unchecked_pack_unpack_u64(2);
2319        unchecked_pack_unpack_u64(3);
2320        unchecked_pack_unpack_u64(4);
2321        unchecked_pack_unpack_u64(5);
2322        unchecked_pack_unpack_u64(6);
2323        unchecked_pack_unpack_u64(7);
2324        unchecked_pack_unpack_u64(8);
2325        unchecked_pack_unpack_u64(9);
2326        unchecked_pack_unpack_u64(10);
2327        unchecked_pack_unpack_u64(11);
2328        unchecked_pack_unpack_u64(12);
2329        unchecked_pack_unpack_u64(13);
2330        unchecked_pack_unpack_u64(14);
2331        unchecked_pack_unpack_u64(15);
2332        unchecked_pack_unpack_u64(16);
2333        unchecked_pack_unpack_u64(17);
2334        unchecked_pack_unpack_u64(18);
2335        unchecked_pack_unpack_u64(19);
2336        unchecked_pack_unpack_u64(20);
2337        unchecked_pack_unpack_u64(21);
2338        unchecked_pack_unpack_u64(22);
2339        unchecked_pack_unpack_u64(23);
2340        unchecked_pack_unpack_u64(24);
2341        unchecked_pack_unpack_u64(25);
2342        unchecked_pack_unpack_u64(26);
2343        unchecked_pack_unpack_u64(27);
2344        unchecked_pack_unpack_u64(28);
2345        unchecked_pack_unpack_u64(29);
2346        unchecked_pack_unpack_u64(30);
2347        unchecked_pack_unpack_u64(31);
2348        unchecked_pack_unpack_u64(32);
2349        unchecked_pack_unpack_u64(33);
2350        unchecked_pack_unpack_u64(34);
2351        unchecked_pack_unpack_u64(35);
2352        unchecked_pack_unpack_u64(36);
2353        unchecked_pack_unpack_u64(37);
2354        unchecked_pack_unpack_u64(38);
2355        unchecked_pack_unpack_u64(39);
2356        unchecked_pack_unpack_u64(40);
2357        unchecked_pack_unpack_u64(41);
2358        unchecked_pack_unpack_u64(42);
2359        unchecked_pack_unpack_u64(43);
2360        unchecked_pack_unpack_u64(44);
2361        unchecked_pack_unpack_u64(45);
2362        unchecked_pack_unpack_u64(46);
2363        unchecked_pack_unpack_u64(47);
2364        unchecked_pack_unpack_u64(48);
2365        unchecked_pack_unpack_u64(49);
2366        unchecked_pack_unpack_u64(50);
2367        unchecked_pack_unpack_u64(51);
2368        unchecked_pack_unpack_u64(52);
2369        unchecked_pack_unpack_u64(53);
2370        unchecked_pack_unpack_u64(54);
2371        unchecked_pack_unpack_u64(55);
2372        unchecked_pack_unpack_u64(56);
2373        unchecked_pack_unpack_u64(57);
2374        unchecked_pack_unpack_u64(58);
2375        unchecked_pack_unpack_u64(59);
2376        unchecked_pack_unpack_u64(60);
2377        unchecked_pack_unpack_u64(61);
2378        unchecked_pack_unpack_u64(62);
2379        unchecked_pack_unpack_u64(63);
2380        unchecked_pack_unpack_u64(64);
2381    }
2382}