You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: avx2.rs
    path of file: ./repos/tantivy/bitpacker/src/filter_vec
    
    the code of the file until where you have to start completion: //! SIMD filtering of a vector as described in the following blog post.
//! <https://quickwit.io/blog/filtering%20a%20vector%20with%20simd%20instructions%20avx-2%20and%20avx-512>
use std::arch::x86_64::{
    __m256i as DataType, _mm256_add_epi32 as op_add, _mm256_cmpgt_epi32 as op_greater,
    _mm256_lddqu_si256 as load_unaligned, _mm256_or_si256 as op_or, _mm256_set1_epi32 as set1,
    _mm256_storeu_si256 as store_unaligned, _mm256_xor_si256 as op_xor, *,
};
use std::ops::RangeInclusive;

const NUM_LANES: usize = 8;

const HIGHEST_BIT: u32 = 1 << 31;

#[inline]
fn u32_to_i32(val: u32) -> i32 {
    (val ^ HIGHEST_BIT) as i32
}

#[inline
    
pub fn filter_vec_in_place(range: RangeInclusive<u32>, offset: u32, output: &mut Vec<u32>) {
    // We use a monotonic mapping from u32 to i32 to make the comparison possible in AVX2.
    let range_i32: RangeInclusive<i32> = u32_to_i32(*range.start())..=u32_to_i32(*range.end());
    let num_words = output.len() / NUM_LANES;
    let mut output_len = unsafe {
        filter_vec_avx2_aux(
            output.as_ptr() as *const __m256i,
            range_i32,
            output.as_mut_ptr(),
            offset,
            num_words,
        )
    };
    let reminder_start = num_words * NUM_LANES;
    for i in reminder_start..output.len() {
        let val = output[i];
        output[output_len] = offset + i as u32;
        output_len += if range.contains(&val) { 1 } else { 0 };
    }
    output.truncate(output_len);
}