NumPy-源码解析-五十五-

192 阅读1小时+

NumPy 源码解析(五十五)

.\numpy\numpy\_core\src\common\simd\avx2\operators.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX2_OPERATORS_H
#define _NPY_SIMD_AVX2_OPERATORS_H

/***************************
 * Shifting
 ***************************/

// 定义 AVX2 下的无符号 16 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_u16(A, C) _mm256_sll_epi16(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 16 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_s16(A, C) _mm256_sll_epi16(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的无符号 32 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_u32(A, C) _mm256_sll_epi32(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 32 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_s32(A, C) _mm256_sll_epi32(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的无符号 64 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_u64(A, C) _mm256_sll_epi64(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 64 位整数左移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shl_s64(A, C) _mm256_sll_epi64(A, _mm_cvtsi32_si128(C))

// 左移动作,移位常数为立即数
#define npyv_shli_u16 _mm256_slli_epi16
#define npyv_shli_s16 _mm256_slli_epi16
#define npyv_shli_u32 _mm256_slli_epi32
#define npyv_shli_s32 _mm256_slli_epi32
#define npyv_shli_u64 _mm256_slli_epi64
#define npyv_shli_s64 _mm256_slli_epi64

// 定义 AVX2 下的无符号 16 位整数右移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shr_u16(A, C) _mm256_srl_epi16(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 16 位整数右移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shr_s16(A, C) _mm256_sra_epi16(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的无符号 32 位整数右移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shr_u32(A, C) _mm256_srl_epi32(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 32 位整数右移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shr_s32(A, C) _mm256_sra_epi32(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的无符号 64 位整数右移操作,参数 A 为输入向量,C 为移位常数
#define npyv_shr_u64(A, C) _mm256_srl_epi64(A, _mm_cvtsi32_si128(C))

// 定义 AVX2 下的有符号 64 位整数右移操作,参数 A 为输入向量,C 为移位常数
NPY_FINLINE __m256i npyv_shr_s64(__m256i a, int c)
{
    // 定义常量 sbit 为 0x8000000000000000256 位整数向量
    const __m256i sbit = _mm256_set1_epi64x(0x8000000000000000);
    // 将整数常数 c 转换为 128 位整数向量
    const __m128i c64  = _mm_cvtsi32_si128(c);
    // 计算右移结果,包括符号位的扩展
    __m256i r = _mm256_srl_epi64(_mm256_add_epi64(a, sbit), c64);
    // 还原符号位
    return _mm256_sub_epi64(r, _mm256_srl_epi64(sbit, c64));
}

// 右移动作,移位常数为立即数
#define npyv_shri_u16 _mm256_srli_epi16
#define npyv_shri_s16 _mm256_srai_epi16
#define npyv_shri_u32 _mm256_srli_epi32
#define npyv_shri_s32 _mm256_srai_epi32
#define npyv_shri_u64 _mm256_srli_epi64
#define npyv_shri_s64  npyv_shr_s64

/***************************
 * Logical
 ***************************/

// 逻辑 AND 操作,参数类型为无符号 8 位整数
#define npyv_and_u8  _mm256_and_si256

// 逻辑 AND 操作,参数类型为有符号 8 位整数
#define npyv_and_s8  _mm256_and_si256

// 逻辑 AND 操作,参数类型为无符号 16 位整数
#define npyv_and_u16 _mm256_and_si256

// 逻辑 AND 操作,参数类型为有符号 16 位整数
#define npyv_and_s16 _mm256_and_si256

// 逻辑 AND 操作,参数类型为无符号 32 位整数
#define npyv_and_u32 _mm256_and_si256

// 逻辑 AND 操作,参数类型为有符号 32 位整数
#define npyv_and_s32 _mm256_and_si256

// 逻辑 AND 操作,参数类型为无符号 64 位整数
#define npyv_and_u64 _mm256_and_si256

// 逻辑 AND 操作,参数类型为有符号 64 位整数
#define npyv_and_s64 _mm256_and_si256

// 逻辑 AND 操作,参数类型为单精度浮点数
#define npyv_and_f32 _mm256_and_ps

// 逻辑 AND 操作,参数类型为双精度浮点数
#define npyv_and_f64 _mm256_and_pd

// 逻辑 AND 操作,参数类型为布尔值 8#define npyv_and_b8  _mm256_and_si256

// 逻辑 AND 操作,参数类型为布尔值 16#define npyv_and_b16 _mm256_and_si256

// 逻辑 AND 操作,参数类型为布尔值 32#define npyv_and_b32 _mm256_and_si256

// 逻辑 AND 操作,参数类型为布尔值 64#define npyv_and_b64 _mm256_and_si256

// 逻辑 OR 操作,参数类型为无符号 8 位整数
#define npyv_or_u8  _mm256_or_si256

// 逻辑 OR 操作,参数类型为有符号 8 位整数
#define npyv_or_s8  _mm256_or_si256

// 逻辑 OR 操作,参数类型为无符号 16 位整数
#define npyv_or_u16 _mm256_or_si256

// 逻辑 OR 操作,参数类型为有符号 16 位整数
#define npyv_or_s16 _mm256_or_si256

// 逻辑 OR 操作,参数类型为无符号 32 位整数
#define npyv_or_u32 _mm256_or_si256

// 逻辑 OR 操作,参数类型为有符号 32 位整数
#define npyv_or_s32 _mm256_or_si256

// 逻辑 OR 操作,参数类型为无符号 64 位整数
#define npyv_or_u64 _mm256_or_si256

// 逻辑 OR 操作
// 定义按位异或操作,用于不同数据类型的操作
#define npyv_xor_s8  _mm256_xor_si256
#define npyv_xor_u16 _mm256_xor_si256
#define npyv_xor_s16 _mm256_xor_si256
#define npyv_xor_u32 _mm256_xor_si256
#define npyv_xor_s32 _mm256_xor_si256
#define npyv_xor_u64 _mm256_xor_si256
#define npyv_xor_s64 _mm256_xor_si256
#define npyv_xor_f32 _mm256_xor_ps
#define npyv_xor_f64 _mm256_xor_pd
#define npyv_xor_b8  _mm256_xor_si256
#define npyv_xor_b16 _mm256_xor_si256
#define npyv_xor_b32 _mm256_xor_si256
#define npyv_xor_b64 _mm256_xor_si256

// NOT 操作的宏定义
#define npyv_not_u8(A) _mm256_xor_si256(A, _mm256_set1_epi32(-1))
#define npyv_not_s8  npyv_not_u8
#define npyv_not_u16 npyv_not_u8
#define npyv_not_s16 npyv_not_u8
#define npyv_not_u32 npyv_not_u8
#define npyv_not_s32 npyv_not_u8
#define npyv_not_u64 npyv_not_u8
#define npyv_not_s64 npyv_not_u8
#define npyv_not_f32(A) _mm256_xor_ps(A, _mm256_castsi256_ps(_mm256_set1_epi32(-1)))
#define npyv_not_f64(A) _mm256_xor_pd(A, _mm256_castsi256_pd(_mm256_set1_epi32(-1)))
#define npyv_not_b8  npyv_not_u8
#define npyv_not_b16 npyv_not_u8
#define npyv_not_b32 npyv_not_u8
#define npyv_not_b64 npyv_not_u8

// ANDC, ORC 和 XNOR 操作的宏定义
#define npyv_andc_u8(A, B) _mm256_andnot_si256(B, A)
#define npyv_andc_b8(A, B) _mm256_andnot_si256(B, A)
#define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A)
#define npyv_xnor_b8 _mm256_cmpeq_epi8

/***************************
 * Comparison
 ***************************/

// 整数相等比较操作的宏定义
#define npyv_cmpeq_u8  _mm256_cmpeq_epi8
#define npyv_cmpeq_s8  _mm256_cmpeq_epi8
#define npyv_cmpeq_u16 _mm256_cmpeq_epi16
#define npyv_cmpeq_s16 _mm256_cmpeq_epi16
#define npyv_cmpeq_u32 _mm256_cmpeq_epi32
#define npyv_cmpeq_s32 _mm256_cmpeq_epi32
#define npyv_cmpeq_u64 _mm256_cmpeq_epi64
#define npyv_cmpeq_s64 _mm256_cmpeq_epi64

// 整数不相等比较操作的宏定义
#define npyv_cmpneq_u8(A, B) npyv_not_u8(_mm256_cmpeq_epi8(A, B))
#define npyv_cmpneq_s8 npyv_cmpneq_u8
#define npyv_cmpneq_u16(A, B) npyv_not_u16(_mm256_cmpeq_epi16(A, B))
#define npyv_cmpneq_s16 npyv_cmpneq_u16
#define npyv_cmpneq_u32(A, B) npyv_not_u32(_mm256_cmpeq_epi32(A, B))
#define npyv_cmpneq_s32 npyv_cmpneq_u32
#define npyv_cmpneq_u64(A, B) npyv_not_u64(_mm256_cmpeq_epi64(A, B))
#define npyv_cmpneq_s64 npyv_cmpneq_u64

// 有符号大于比较操作的宏定义
#define npyv_cmpgt_s8  _mm256_cmpgt_epi8
#define npyv_cmpgt_s16 _mm256_cmpgt_epi16
#define npyv_cmpgt_s32 _mm256_cmpgt_epi32
#define npyv_cmpgt_s64 _mm256_cmpgt_epi64

// 有符号大于等于比较操作的宏定义
#define npyv_cmpge_s8(A, B)  npyv_not_s8(_mm256_cmpgt_epi8(B, A))
#define npyv_cmpge_s16(A, B) npyv_not_s16(_mm256_cmpgt_epi16(B, A))
#define npyv_cmpge_s32(A, B) npyv_not_s32(_mm256_cmpgt_epi32(B, A))
#define npyv_cmpge_s64(A, B) npyv_not_s64(_mm256_cmpgt_epi64(B, A))

// 以下是一个未完成的宏定义,用于无符号大于比较操作
#define NPYV_IMPL_AVX2_UNSIGNED_GT(LEN, SIGN)                    \
    NPY_FINLINE __m256i npyv_cmpgt_u##LEN(__m256i a, __m256i b)  \
    {                                                            \
        const __m256i sbit = _mm256_set1_epi32(SIGN);            \
        # 创建一个包含全部元素为常数SIGN的256位整数向量sbit
        return _mm256_cmpgt_epi##LEN(                            \
            _mm256_xor_si256(a, sbit), _mm256_xor_si256(b, sbit) \
        );                                                       \
        # 使用AVX2指令集中的_mm256_cmpgt_epi##LEN函数,比较经过位异或运算后的两个256位整数向量a和b,
        # 返回结果是一个256位整数向量,每个元素是比较的结果(1表示a对应元素大于b对应元素,0表示否)
    }
// 使用 AVX2 指令集实现无符号大于比较操作,对每个操作数为8位整数的向量进行比较
NPYV_IMPL_AVX2_UNSIGNED_GT(8,  0x80808080)
// 使用 AVX2 指令集实现无符号大于比较操作,对每个操作数为16位整数的向量进行比较
NPYV_IMPL_AVX2_UNSIGNED_GT(16, 0x80008000)
// 使用 AVX2 指令集实现无符号大于比较操作,对每个操作数为32位整数的向量进行比较
NPYV_IMPL_AVX2_UNSIGNED_GT(32, 0x80000000)

// 定义函数 npyv_cmpgt_u64,用于比较两个64位整数向量 a 和 b 的大于关系
NPY_FINLINE __m256i npyv_cmpgt_u64(__m256i a, __m256i b)
{
    // 定义掩码向量 sbit,用于对比特反转,用于处理符号位的比较
    const __m256i sbit = _mm256_set1_epi64x(0x8000000000000000);
    // 返回对 a 和 b 的符号反转后的比较结果
    return _mm256_cmpgt_epi64(_mm256_xor_si256(a, sbit), _mm256_xor_si256(b, sbit));
}

// 定义函数 npyv_cmpge_u8,用于比较两个8位无符号整数向量 a 和 b 的大于等于关系
NPY_FINLINE __m256i npyv_cmpge_u8(__m256i a, __m256i b)
{ return _mm256_cmpeq_epi8(a, _mm256_max_epu8(a, b)); }

// 定义函数 npyv_cmpge_u16,用于比较两个16位无符号整数向量 a 和 b 的大于等于关系
NPY_FINLINE __m256i npyv_cmpge_u16(__m256i a, __m256i b)
{ return _mm256_cmpeq_epi16(a, _mm256_max_epu16(a, b)); }

// 定义函数 npyv_cmpge_u32,用于比较两个32位无符号整数向量 a 和 b 的大于等于关系
NPY_FINLINE __m256i npyv_cmpge_u32(__m256i a, __m256i b)
{ return _mm256_cmpeq_epi32(a, _mm256_max_epu32(a, b)); }

// 定义宏 npyv_cmpge_u64,用于比较两个64位无符号整数向量 A 和 B 的大于等于关系
#define npyv_cmpge_u64(A, B) npyv_not_u64(npyv_cmpgt_u64(B, A))

// 定义一系列宏,用于实现不同类型的小于比较操作,分别对应不同的整数类型(有符号和无符号)

// 定义一系列宏,用于实现不同类型的小于等于比较操作,分别对应不同的整数类型(有符号和无符号)

// 定义一系列宏,用于实现浮点数的精确比较操作,包括等于、不等于、小于、小于等于、大于、大于等于

// 定义函数 npyv_notnan_f32,用于检查32位浮点数向量 a 中的元素是否都不是 NaN
NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
{ return _mm256_castps_si256(_mm256_cmp_ps(a, a, _CMP_ORD_Q)); }

// 定义函数 npyv_notnan_f64,用于检查64位浮点数向量 a 中的元素是否都不是 NaN
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
{ return _mm256_castpd_si256(_mm256_cmp_pd(a, a, _CMP_ORD_Q)); }

// 测试跨所有向量通道的情况
// any: 如果任意一个元素不等于零,则返回 true
// 定义宏 NPYV_IMPL_AVX2_ANYALL(SFX),用于生成 AVX2 指令集的任意/全部判断函数
#define NPYV_IMPL_AVX2_ANYALL(SFX)                     \
    // 内联函数,判断 AVX2 数据类型为 SFX 的向量是否存在非零元素
    NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a)      \
    {                                                  \
        // 使用 AVX2 指令 movemask 判断向量是否存在不等于零的元素
        return _mm256_movemask_epi8(                   \
            npyv_cmpeq_##SFX(a, npyv_zero_##SFX())     \
        ) != -1;                                       \
    }                                                  \
    // 内联函数,判断 AVX2 数据类型为 SFX 的向量是否所有元素都等于零
    NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a)      \
    {                                                  \
        // 使用 AVX2 指令 movemask 判断向量是否所有元素都等于零
        return _mm256_movemask_epi8(                   \
            npyv_cmpeq_##SFX(a, npyv_zero_##SFX())     \
        ) == 0;                                        \
    }

// 生成 AVX2 指令集的不同数据类型的任意/全部判断函数
NPYV_IMPL_AVX2_ANYALL(b8)
NPYV_IMPL_AVX2_ANYALL(b16)
NPYV_IMPL_AVX2_ANYALL(b32)
NPYV_IMPL_AVX2_ANYALL(b64)

// 取消定义宏 NPYV_IMPL_AVX2_ANYALL,避免宏定义冲突
#undef NPYV_IMPL_AVX2_ANYALL

// 重新定义宏 NPYV_IMPL_AVX2_ANYALL(SFX),用于生成 AVX2 指令集的任意/全部判断函数
#define NPYV_IMPL_AVX2_ANYALL(SFX)                                         \
    // 内联函数,判断 AVX2 数据类型为 SFX 的向量是否存在非零元素            \
    NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a)                          \
    {                                                                       \
        // 使用 AVX2 指令 movemask 判断向量是否存在不等于零的元素            \
        return _mm256_movemask_##XSFX(                                      \
            _mm256_cmp_##XSFX(a, npyv_zero_##SFX(), _CMP_EQ_OQ)             \
        ) != MASK;                                                          \
    }                                                                       \
    // 内联函数,判断 AVX2 数据类型为 SFX 的向量是否所有元素都等于零         \
    NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a)                          \
    {                                                                       \
        // 使用 AVX2 指令 movemask 判断向量是否所有元素都等于零               \
        return _mm256_movemask_##XSFX(                                      \
            _mm256_cmp_##XSFX(a, npyv_zero_##SFX(), _CMP_EQ_OQ)             \
        ) == 0;                                                             \
    }

// 生成 AVX2 指令集的不同数据类型的任意/全部判断函数,使用不同的比较器 XSFX 和 MASK
NPYV_IMPL_AVX2_ANYALL(u8,  ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(s8,  ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(u16, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(s16, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(u32, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(s32, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(u64, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(s64, ps, 0xff)
NPYV_IMPL_AVX2_ANYALL(f32, pd, 0xf)
NPYV_IMPL_AVX2_ANYALL(f64, pd, 0xf)

// 取消定义宏 NPYV_IMPL_AVX2_ANYALL,避免宏定义冲突
#undef NPYV_IMPL_AVX2_ANYALL

// 结束条件,关闭头文件 _NPY_SIMD_AVX2_OPERATORS_H 的声明
#endif // _NPY_SIMD_AVX2_OPERATORS_H

.\numpy\numpy\_core\src\common\simd\avx2\reorder.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX2_REORDER_H
#define _NPY_SIMD_AVX2_REORDER_H

// 定义宏:将两个向量的低部分组合起来
#define npyv_combinel_u8(A, B) _mm256_permute2x128_si256(A, B, 0x20)
#define npyv_combinel_s8  npyv_combinel_u8
#define npyv_combinel_u16 npyv_combinel_u8
#define npyv_combinel_s16 npyv_combinel_u8
#define npyv_combinel_u32 npyv_combinel_u8
#define npyv_combinel_s32 npyv_combinel_u8
#define npyv_combinel_u64 npyv_combinel_u8
#define npyv_combinel_s64 npyv_combinel_u8
#define npyv_combinel_f32(A, B) _mm256_permute2f128_ps(A, B, 0x20)
#define npyv_combinel_f64(A, B) _mm256_permute2f128_pd(A, B, 0x20)

// 定义宏:将两个向量的高部分组合起来
#define npyv_combineh_u8(A, B) _mm256_permute2x128_si256(A, B, 0x31)
#define npyv_combineh_s8  npyv_combineh_u8
#define npyv_combineh_u16 npyv_combineh_u8
#define npyv_combineh_s16 npyv_combineh_u8
#define npyv_combineh_u32 npyv_combineh_u8
#define npyv_combineh_s32 npyv_combineh_u8
#define npyv_combineh_u64 npyv_combineh_u8
#define npyv_combineh_s64 npyv_combineh_u8
#define npyv_combineh_f32(A, B) _mm256_permute2f128_ps(A, B, 0x31)
#define npyv_combineh_f64(A, B) _mm256_permute2f128_pd(A, B, 0x31)

// 定义函数:将两个__m256i类型的向量a和b的低高部分分别组合起来,返回一个npyv_m256ix2结构体
NPY_FINLINE npyv_m256ix2 npyv__combine(__m256i a, __m256i b)
{
    npyv_m256ix2 r;
    // 将a和b的低高部分组合成a1b0
    __m256i a1b0 = _mm256_permute2x128_si256(a, b, 0x21);
    // 使用_blend_epi32混合a和a1b0的高低部分,将结果存入r.val[0]
    r.val[0] = _mm256_blend_epi32(a, a1b0, 0xF0);
    // 使用_blend_epi32混合b和a1b0的高低部分,将结果存入r.val[1]
    r.val[1] = _mm256_blend_epi32(b, a1b0, 0xF);
    return r;
}

// 定义函数:将两个__m256类型的向量a和b的低高部分分别组合起来,返回一个npyv_f32x2结构体
NPY_FINLINE npyv_f32x2 npyv_combine_f32(__m256 a, __m256 b)
{
    npyv_f32x2 r;
    // 将a和b的低高部分组合成a1b0
    __m256 a1b0 = _mm256_permute2f128_ps(a, b, 0x21);
    // 使用_blend_ps混合a和a1b0的高低部分,将结果存入r.val[0]
    r.val[0] = _mm256_blend_ps(a, a1b0, 0xF0);
    // 使用_blend_ps混合b和a1b0的高低部分,将结果存入r.val[1]
    r.val[1] = _mm256_blend_ps(b, a1b0, 0xF);
    return r;
}

// 定义函数:将两个__m256d类型的向量a和b的低高部分分别组合起来,返回一个npyv_f64x2结构体
NPY_FINLINE npyv_f64x2 npyv_combine_f64(__m256d a, __m256d b)
{
    npyv_f64x2 r;
    // 将a和b的低高部分组合成a1b0
    __m256d a1b0 = _mm256_permute2f128_pd(a, b, 0x21);
    // 使用_blend_pd混合a和a1b0的高低部分,将结果存入r.val[0]
    r.val[0] = _mm256_blend_pd(a, a1b0, 0xC);
    // 使用_blend_pd混合b和a1b0的高低部分,将结果存入r.val[1]
    r.val[1] = _mm256_blend_pd(b, a1b0, 0x3);
    return r;
}

// 定义宏:实现AVX2下的ZIP操作,将向量a和b的低高部分交织在一起,返回一个T_VEC##x2结构体
#define NPYV_IMPL_AVX2_ZIP_U(T_VEC, LEN)                    \
    NPY_FINLINE T_VEC##x2 npyv_zip_u##LEN(T_VEC a, T_VEC b) \
    {                                                       \
        // 将向量a和b的低部分和高部分分别解包并交织在一起,得到ab0和ab1
        __m256i ab0 = _mm256_unpacklo_epi##LEN(a, b);       \
        __m256i ab1 = _mm256_unpackhi_epi##LEN(a, b);       \
        // 使用npyv__combine将ab0和ab1的低高部分组合在一起,返回结果
        return npyv__combine(ab0, ab1);                     \
    }

// 为不同长度的T_VEC类型定义具体的ZIP函数实现
NPYV_IMPL_AVX2_ZIP_U(npyv_u8,  8)
NPYV_IMPL_AVX2_ZIP_U(npyv_u16, 16)
NPYV_IMPL_AVX2_ZIP_U(npyv_u32, 32)
NPYV_IMPL_AVX2_ZIP_U(npyv_u64, 64)
#define npyv_zip_s8  npyv_zip_u8
#define npyv_zip_s16 npyv_zip_u16
#define npyv_zip_s32 npyv_zip_u32

#endif // _NPY_SIMD_AVX2_REORDER_H
// 定义一个宏,将有符号64位整数向无符号64位整数的转换别名为npv_zip_s64
#define npyv_zip_s64 npyv_zip_u64

// 定义一个内联函数,将两个256位单精度浮点数向量a和b解交错
NPY_FINLINE npyv_f32x2 npyv_zip_f32(__m256 a, __m256 b)
{
    // 解交错操作,取出a和b的低128位和高128位,分别放入ab0和ab1
    __m256 ab0 = _mm256_unpacklo_ps(a, b);
    __m256 ab1 = _mm256_unpackhi_ps(a, b);
    // 调用npv_combine_f32函数将ab0和ab1组合成一个新的256位单精度浮点数向量
    return npyv_combine_f32(ab0, ab1);
}

// 定义一个内联函数,将两个256位双精度浮点数向量a和b解交错
NPY_FINLINE npyv_f64x2 npyv_zip_f64(__m256d a, __m256d b)
{
    // 解交错操作,取出a和b的低128位和高128位,分别放入ab0和ab1
    __m256d ab0 = _mm256_unpacklo_pd(a, b);
    __m256d ab1 = _mm256_unpackhi_pd(a, b);
    // 调用npv_combine_f64函数将ab0和ab1组合成一个新的256位双精度浮点数向量
    return npyv_combine_f64(ab0, ab1);
}

// 定义一个内联函数,将两个8位无符号整数向量ab0和ab1进行解插值
NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1)
{
    // 创建一个常量256位整数向量idx,其排列顺序按照指定的索引
    const __m256i idx = _mm256_setr_epi8(
        0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
        0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15
    );
    // 对ab0和ab1按照idx的顺序进行字节级重排
    __m256i ab_03 = _mm256_shuffle_epi8(ab0, idx);
    __m256i ab_12 = _mm256_shuffle_epi8(ab1, idx);
    // 调用npyv_combine_u8将ab_03和ab_12组合成一个新的8位无符号整数向量对
    npyv_u8x2 ab_lh = npyv_combine_u8(ab_03, ab_12);
    npyv_u8x2 r;
    // 将ab_lh的val[0]和val[1]分别按64位整数进行解交错,存入r.val[0]和r.val[1]
    r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]);
    r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]);
    return r;
}
// 定义一个宏,将有符号8位整数向无符号8位整数的转换别名为npv_unzip_s8
#define npyv_unzip_s8 npyv_unzip_u8

// 定义一个内联函数,将两个16位无符号整数向量ab0和ab1进行解插值
NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1)
{
    // 创建一个常量256位整数向量idx,其排列顺序按照指定的索引
    const __m256i idx = _mm256_setr_epi8(
        0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15,
        0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15
    );
    // 对ab0和ab1按照idx的顺序进行字节级重排
    __m256i ab_03 = _mm256_shuffle_epi8(ab0, idx);
    __m256i ab_12 = _mm256_shuffle_epi8(ab1, idx);
    // 调用npyv_combine_u16将ab_03和ab_12组合成一个新的16位无符号整数向量对
    npyv_u16x2 ab_lh = npyv_combine_u16(ab_03, ab_12);
    npyv_u16x2 r;
    // 将ab_lh的val[0]和val[1]分别按64位整数进行解交错,存入r.val[0]和r.val[1]
    r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]);
    r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]);
    return r;
}
// 定义一个宏,将有符号16位整数向无符号16位整数的转换别名为npv_unzip_s16
#define npyv_unzip_s16 npyv_unzip_u16

// 定义一个内联函数,将两个32位无符号整数向量ab0和ab1进行解插值
NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1)
{
    // 创建一个常量256位整数向量idx,按照指定的索引对ab0和ab1进行32位整数级的重排
    const __m256i idx = npyv_set_u32(0, 2, 4, 6, 1, 3, 5, 7);
    __m256i abl = _mm256_permutevar8x32_epi32(ab0, idx);
    __m256i abh = _mm256_permutevar8x32_epi32(ab1, idx);
    // 调用npyv_combine_u32将abl和abh组合成一个新的32位无符号整数向量对
    return npyv_combine_u32(abl, abh);
}
// 定义一个宏,将有符号32位整数向无符号32位整数的转换别名为npv_unzip_s32
#define npyv_unzip_s32 npyv_unzip_u32

// 定义一个内联函数,将两个64位无符号整数向量ab0和ab1进行解插值
NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1)
{
    // 调用npyv_combine_u64将ab0和ab1组合成一个新的64位无符号整数向量对
    npyv_u64x2 ab_lh = npyv_combine_u64(ab0, ab1);
    npyv_u64x2 r;
    // 将ab_lh的val[0]和val[1]分别按64位整数进行解交错,存入r.val[0]和r.val[1]
    r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]);
    r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]);
    return r;
}
// 定义一个宏,将有符号64位整数向无符号64位整数的转换别名为npv_unzip_s64
#define npyv_unzip_s64 npyv_unzip_u64

// 定义一个内联函数,将两个32位单精度浮点数向量ab0和ab1进行解插值
NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab
    # 创建一个 256 位整数类型的常量 idx,使用 _mm256_setr_epi8 函数设置它的值
    # 这个常量用于定义一个特定的字节重排顺序,具体顺序如下:
    # 从左到右分两行设置,每行包含 16 个字节索引,第一行从 7 到 0,第二行从 15 到 8
    const __m256i idx = _mm256_setr_epi8(
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8,
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8
    );
    # 使用 AVX2 指令集中的 _mm256_shuffle_epi8 函数,按照 idx 的指定顺序对参数 a 进行字节重排
    return _mm256_shuffle_epi8(a, idx);
// 定义宏 npyv_rev64_s8,将其映射到 npyv_rev64_u8 宏
#define npyv_rev64_s8 npyv_rev64_u8

// 定义函数 npyv_rev64_u16,反转参数中的 16 位元素顺序
NPY_FINLINE npyv_u16 npyv_rev64_u16(npyv_u16 a)
{
    // 创建一个常量 __m256i 类型的索引,用于反转 16 位元素的顺序
    const __m256i idx = _mm256_setr_epi8(
        6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9,
        6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9
    );
    // 使用 AVX2 指令集中的 _mm256_shuffle_epi8 对 a 应用 idx 索引进行元素反转
    return _mm256_shuffle_epi8(a, idx);
}
// 定义宏 npyv_rev64_s16,将其映射到 npyv_rev64_u16 宏

// 定义函数 npyv_rev64_u32,反转参数中的 32 位元素顺序
NPY_FINLINE npyv_u32 npyv_rev64_u32(npyv_u32 a)
{
    // 使用 AVX2 指令集中的 _mm256_shuffle_epi32 对 a 进行元素反转,模式为 _MM_SHUFFLE(2, 3, 0, 1)
    return _mm256_shuffle_epi32(a, _MM_SHUFFLE(2, 3, 0, 1));
}
// 定义宏 npyv_rev64_s32,将其映射到 npyv_rev64_u32 宏

// 定义函数 npyv_rev64_f32,反转参数中的 32 位浮点元素顺序
NPY_FINLINE npyv_f32 npyv_rev64_f32(npyv_f32 a)
{
    // 使用 AVX 指令集中的 _mm256_shuffle_ps 对 a 进行浮点元素反转,模式为 _MM_SHUFFLE(2, 3, 0, 1)
    return _mm256_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1));
}

// Permuting the elements of each 128-bit lane by immediate index for
// each element.

// 定义宏 npyv_permi128_u32,根据指定的索引对 128 位数据进行元素排列
#define npyv_permi128_u32(A, E0, E1, E2, E3) \
    // 使用 AVX2 指令集中的 _mm256_shuffle_epi32 对 A 进行元素排列,模式由参数 E0, E1, E2, E3 确定

// 定义宏 npyv_permi128_s32,将其映射到 npyv_permi128_u32 宏

// 定义宏 npyv_permi128_u64,根据指定的索引对 128 位数据进行元素排列
#define npyv_permi128_u64(A, E0, E1) \
    // 使用 AVX2 指令集中的 _mm256_shuffle_epi32 对 A 进行元素排列,模式由参数 E0, E1 确定

// 定义宏 npyv_permi128_s64,将其映射到 npyv_permi128_u64 宏

// 定义宏 npyv_permi128_f32,根据指定的索引对 128 位数据进行浮点元素排列
#define npyv_permi128_f32(A, E0, E1, E2, E3) \
    // 使用 AVX 指令集中的 _mm256_permute_ps 对 A 进行浮点元素排列,模式由参数 E0, E1, E2, E3 确定

// 定义宏 npyv_permi128_f64,根据指定的索引对 128 位数据进行双精度浮点元素排列
#define npyv_permi128_f64(A, E0, E1) \
    // 使用 AVX 指令集中的 _mm256_permute_pd 对 A 进行双精度浮点元素排列,模式由参数 E0, E1 确定

// 结束条件,结束条件编译器的处理,确保头文件内容不会被重复包含
#endif // _NPY_SIMD_AVX2_REORDER_H

.\numpy\numpy\_core\src\common\simd\avx2\utils.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX2_UTILS_H
#define _NPY_SIMD_AVX2_UTILS_H

// 定义一个宏,用于对256位整数型寄存器进行奇数位元素的重新排列
#define npyv256_shuffle_odd(A)    _mm256_permute4x64_epi64(A, _MM_SHUFFLE(3, 1, 2, 0))
// 定义一个宏,将256位浮点型寄存器转换为按奇数位元素排列的浮点型寄存器
#define npyv256_shuffle_odd_ps(A) _mm256_castsi256_ps(npyv256_shuffle_odd(_mm256_castps_si256(A)))
// 定义一个宏,用于对256位双精度浮点型寄存器进行奇数位元素的重新排列
#define npyv256_shuffle_odd_pd(A) _mm256_permute4x64_pd(A, _MM_SHUFFLE(3, 1, 2, 0))

// 定义一个内联函数,实现无符号8位整数型寄存器的乘法操作
NPY_FINLINE __m256i npyv256_mul_u8(__m256i a, __m256i b)
{
    // 创建一个掩码,用于选择奇数位元素
    const __m256i mask = _mm256_set1_epi32(0xFF00FF00);
    // 计算偶数位元素乘积
    __m256i even = _mm256_mullo_epi16(a, b);
    // 计算奇数位元素乘积
    __m256i odd  = _mm256_mullo_epi16(_mm256_srai_epi16(a, 8), _mm256_srai_epi16(b, 8));
    // 将奇数位元素乘积左移8位
    odd  = _mm256_slli_epi16(odd, 8);
    // 使用掩码选择奇数位元素乘积或偶数位元素乘积
    return _mm256_blendv_epi8(even, odd, mask);
}

#endif // _NPY_SIMD_AVX2_UTILS_H

.\numpy\numpy\_core\src\common\simd\avx512\arithmetic.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_ARITHMETIC_H
#define _NPY_SIMD_AVX512_ARITHMETIC_H

#include "../avx2/utils.h"
#include "../sse/utils.h"

/***************************
 * Addition
 ***************************/

// 定义 AVX512BW 指令集下的非饱和加法操作宏
#ifdef NPY_HAVE_AVX512BW
    #define npyv_add_u8  _mm512_add_epi8
    #define npyv_add_u16 _mm512_add_epi16
// 如果不支持 AVX512BW,则从 AVX2 中实现 AVX512 指令集的非饱和加法操作宏
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_add_u8,  _mm256_add_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_add_u16, _mm256_add_epi16)
#endif

// 定义有符号整数类型的非饱和加法宏
#define npyv_add_s8  npyv_add_u8
#define npyv_add_s16 npyv_add_u16
#define npyv_add_u32 _mm512_add_epi32
#define npyv_add_s32 _mm512_add_epi32
#define npyv_add_u64 _mm512_add_epi64
#define npyv_add_s64 _mm512_add_epi64
#define npyv_add_f32 _mm512_add_ps
#define npyv_add_f64 _mm512_add_pd

// 定义 AVX512BW 指令集下的饱和加法操作宏
#ifdef NPY_HAVE_AVX512BW
    #define npyv_adds_u8  _mm512_adds_epu8
    #define npyv_adds_s8  _mm512_adds_epi8
    #define npyv_adds_u16 _mm512_adds_epu16
    #define npyv_adds_s16 _mm512_adds_epi16
// 如果不支持 AVX512BW,则从 AVX2 中实现 AVX512 指令集的饱和加法操作宏
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_u8,  _mm256_adds_epu8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_s8,  _mm256_adds_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_u16, _mm256_adds_epu16)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_s16, _mm256_adds_epi16)
#endif

// TODO: rest, after implement Packs intrins

/***************************
 * Subtraction
 ***************************/

// 定义 AVX512BW 指令集下的非饱和减法操作宏
#ifdef NPY_HAVE_AVX512BW
    #define npyv_sub_u8  _mm512_sub_epi8
    #define npyv_sub_u16 _mm512_sub_epi16
// 如果不支持 AVX512BW,则从 AVX2 中实现 AVX512 指令集的非饱和减法操作宏
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_sub_u8,  _mm256_sub_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_sub_u16, _mm256_sub_epi16)
#endif

// 定义有符号整数类型的非饱和减法宏
#define npyv_sub_s8  npyv_sub_u8
#define npyv_sub_s16 npyv_sub_u16
#define npyv_sub_u32 _mm512_sub_epi32
#define npyv_sub_s32 _mm512_sub_epi32
#define npyv_sub_u64 _mm512_sub_epi64
#define npyv_sub_s64 _mm512_sub_epi64
#define npyv_sub_f32 _mm512_sub_ps
#define npyv_sub_f64 _mm512_sub_pd

// 定义 AVX512BW 指令集下的饱和减法操作宏
#ifdef NPY_HAVE_AVX512BW
    #define npyv_subs_u8  _mm512_subs_epu8
    #define npyv_subs_s8  _mm512_subs_epi8
    #define npyv_subs_u16 _mm512_subs_epu16
    #define npyv_subs_s16 _mm512_subs_epi16
// 如果不支持 AVX512BW,则从 AVX2 中实现 AVX512 指令集的饱和减法操作宏
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_u8,  _mm256_subs_epu8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_s8,  _mm256_subs_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_u16, _mm256_subs_epu16)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_s16, _mm256_subs_epi16)
#endif

// TODO: rest, after implement Packs intrins

/***************************
 * Multiplication
 ***************************/

// 定义 AVX512BW 指令集下的非饱和乘法函数实现
#ifdef NPY_HAVE_AVX512BW
NPY_FINLINE __m512i npyv_mul_u8(__m512i a, __m512i b)
{
    // 计算偶数位置的乘积
    __m512i even = _mm512_mullo_epi16(a, b);
    // 计算奇数位置的乘积
    __m512i odd  = _mm512_mullo_epi16(_mm512_srai_epi16(a, 8), _mm512_srai_epi16(b, 8));
            odd  = _mm512_slli_epi16(odd, 8);
    // 合并偶数和奇数位置的结果,构成完整的乘积结果
    return _mm512_mask_blend_epi8(0xAAAAAAAAAAAAAAAA, even, odd);
}
#else
    # 使用 AVX2 实现的无符号8位整数乘法函数 npyv256_mul_u8,转换为 AVX512 实现
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_mul_u8, npyv256_mul_u8)
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX-512 BW 指令集,使用 AVX-512 指令进行无符号 16 位整数乘法
    #define npyv_mul_u16 _mm512_mullo_epi16
#else
    // 如果不支持 AVX-512 BW 指令集,将 AVX2 的 256 位整数乘法扩展为 AVX-512
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_mul_u16, _mm256_mullo_epi16)
#endif

// 将有符号 8 位整数乘法定义为无符号 8 位整数乘法
#define npyv_mul_s8  npyv_mul_u8
// 将有符号 16 位整数乘法定义为无符号 16 位整数乘法
#define npyv_mul_s16 npyv_mul_u16
// 使用 AVX-512 指令进行无符号 32 位整数乘法
#define npyv_mul_u32 _mm512_mullo_epi32
// 使用 AVX-512 指令进行有符号 32 位整数乘法
#define npyv_mul_s32 _mm512_mullo_epi32
// 使用 AVX-512 指令进行单精度浮点数乘法
#define npyv_mul_f32 _mm512_mul_ps
// 使用 AVX-512 指令进行双精度浮点数乘法
#define npyv_mul_f64 _mm512_mul_pd

// saturated
// 饱和运算
// TODO: 实现 Packs 指令之后完成此部分

/***************************
 * Integer Division
 ***************************/
// 整数除法
// 详细内容请参见 simd/intdiv.h
// divide each unsigned 8-bit element by divisor
// 将每个无符号 8 位元素除以除数
NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor)
{
    // 从 divisor 中提取需要的位移量
    const __m128i shf1  = _mm512_castsi512_si128(divisor.val[1]);
    const __m128i shf2  = _mm512_castsi512_si128(divisor.val[2]);

#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX-512 BW 指令集
    const __m512i bmask = _mm512_set1_epi32(0x00FF00FF);
    // 计算位移的掩码
    const __m512i shf1b = _mm512_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf1));
    const __m512i shf2b = _mm512_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf2));

    // 对偶数位置进行乘法
    __m512i mulhi_even  = _mm512_mullo_epi16(_mm512_and_si512(a, bmask), divisor.val[0]);
    mulhi_even          = _mm512_srli_epi16(mulhi_even, 8);
    // 对奇数位置进行乘法
    __m512i mulhi_odd   = _mm512_mullo_epi16(_mm512_srli_epi16(a, 8), divisor.val[0]);
    // 将奇偶结果合并
    __m512i mulhi       = _mm512_mask_mov_epi8(mulhi_even, 0xAAAAAAAAAAAAAAAA, mulhi_odd);
    // 计算商 q = floor(a/d)
    __m512i q           = _mm512_sub_epi8(a, mulhi);
    q                   = _mm512_and_si512(_mm512_srl_epi16(q, shf1), shf1b);
    q                   = _mm512_add_epi8(mulhi, q);
    q                   = _mm512_and_si512(_mm512_srl_epi16(q, shf2), shf2b);

    return  q;
#else
    // 如果不支持 AVX-512 BW 指令集
    const __m256i bmask = _mm256_set1_epi32(0x00FF00FF);
    const __m256i shf1b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf1));
    const __m256i shf2b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf2));
    const __m512i shf2bw= npyv512_combine_si256(shf2b, shf2b);
    const __m256i mulc  = npyv512_lower_si256(divisor.val[0]);

    // 从 a 中获取低 256 位
    __m256i lo_a        = npyv512_lower_si256(a);
    // 对偶数位置进行乘法
    __m256i mulhi_even  = _mm256_mullo_epi16(_mm256_and_si256(lo_a, bmask), mulc);
    mulhi_even          = _mm256_srli_epi16(mulhi_even, 8);
    // 对奇数位置进行乘法
    __m256i mulhi_odd   = _mm256_mullo_epi16(_mm256_srli_epi16(lo_a, 8), mulc);
    // 将奇偶结果合并
    __m256i mulhi       = _mm256_blendv_epi8(mulhi_odd, mulhi_even, bmask);
    // 计算低位结果
    __m256i lo_q        = _mm256_sub_epi8(lo_a, mulhi);
    lo_q                = _mm256_and_si256(_mm256_srl_epi16(lo_q, shf1), shf1b);
    lo_q                = _mm256_add_epi8(mulhi, lo_q);
    lo_q                = _mm256_srl_epi16(lo_q, shf2);

    // 继续处理高 256 位
    __m256i hi_a        = npyv512_higher_si256(a);
    // ...
    // 计算无符号乘法的高位部分
    __m256i mulhi_even  = _mm256_mullo_epi16(_mm256_and_si256(hi_a, bmask), mulc);
    mulhi_even  = _mm256_srli_epi16(mulhi_even, 8);
    __m256i mulhi_odd   = _mm256_mullo_epi16(_mm256_srli_epi16(hi_a, 8), mulc);
    // 选择偶数位和奇数位的乘积结果
    __m256i mulhi       = _mm256_blendv_epi8(mulhi_odd, mulhi_even, bmask);

    // 计算 floor(a/d) = (mulhi + ((a - mulhi) >> sh1)) >> sh2
    __m256i hi_q        = _mm256_sub_epi8(hi_a, mulhi);
    hi_q        = _mm256_and_si256(_mm256_srl_epi16(hi_q, shf1), shf1b);
    hi_q        = _mm256_add_epi8(mulhi, hi_q);
    hi_q        = _mm256_srl_epi16(hi_q, shf2); // 不进行符号扩展

    // 将结果组合为一个 512 位向量,并与掩码进行与操作,扩展符号
    return _mm512_and_si512(npyv512_combine_si256(lo_q, hi_q), shf2bw);
#endif
}
// divide each signed 8-bit element by divisor (round towards zero)
NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor);
// 定义函数:将每个有符号8位元素除以除数(向零舍入)
NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor)
{
    // 计算偶数索引位置的结果
    __m512i divc_even = npyv_divc_s16(npyv_shri_s16(npyv_shli_s16(a, 8), 8), divisor);
    // 计算奇数索引位置的结果
    __m512i divc_odd  = npyv_divc_s16(npyv_shri_s16(a, 8), divisor);
    // 对奇数索引位置的结果进行左移8位
    divc_odd = npyv_shli_s16(divc_odd, 8);
#ifdef NPY_HAVE_AVX512BW
    // 使用掩码操作选择偶数索引位置的结果或者奇数索引位置的结果
    return _mm512_mask_mov_epi8(divc_even, 0xAAAAAAAAAAAAAAAA, divc_odd);
#else
    // 定义位掩码以选择合适的结果
    const __m512i bmask = _mm512_set1_epi32(0x00FF00FF);
    // 使用位掩码选择偶数索引位置的结果或者奇数索引位置的结果
    return npyv_select_u8(bmask, divc_even, divc_odd);
#endif
}
// divide each unsigned 16-bit element by divisor
// 定义函数:将每个无符号16位元素除以除数
NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor)
{
    // 将除数的第1和第2个元素转换为128位整数
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]);
    // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2
    #define NPYV__DIVC_U16(RLEN, A, MULC, R)      \
        mulhi = _mm##RLEN##_mulhi_epu16(A, MULC); \
        R     = _mm##RLEN##_sub_epi16(A, mulhi);  \
        R     = _mm##RLEN##_srl_epi16(R, shf1);   \
        R     = _mm##RLEN##_add_epi16(mulhi, R);  \
        R     = _mm##RLEN##_srl_epi16(R, shf2);

#ifdef NPY_HAVE_AVX512BW
    // 使用AVX-512指令集进行无符号16位除法运算
    __m512i mulhi, q;
    NPYV__DIVC_U16(512, a, divisor.val[0], q)
    return q;
#else
    // 获取除数的低256位部分
    const __m256i m = npyv512_lower_si256(divisor.val[0]);
    // 将输入向量的低256位和高256位分离
    __m256i lo_a    = npyv512_lower_si256(a);
    __m256i hi_a    = npyv512_higher_si256(a);

    // 定义变量:乘积高位、低位结果向量
    __m256i mulhi, lo_q, hi_q;
    // 对低256位和高256位分别进行除法运算
    NPYV__DIVC_U16(256, lo_a, m, lo_q)
    NPYV__DIVC_U16(256, hi_a, m, hi_q)
    // 将低位和高位的结果合并为一个512位向量并返回
    return npyv512_combine_si256(lo_q, hi_q);
#endif
    #undef NPYV__DIVC_U16
}
// divide each signed 16-bit element by divisor (round towards zero)
// 定义函数:将每个有符号16位元素除以除数(向零舍入)
NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor)
{
    // 将除数的第1个元素转换为128位整数
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    // q = ((a + mulhi) >> sh1) - XSIGN(a)
    // trunc(a/d) = (q ^ dsign) - dsign
    #define NPYV__DIVC_S16(RLEN, A, MULC, DSIGN, R)                       \
        mulhi  = _mm##RLEN##_mulhi_epi16(A, MULC);                        \
        R = _mm##RLEN##_sra_epi16(_mm##RLEN##_add_epi16(A, mulhi), shf1); \
        R = _mm##RLEN##_sub_epi16(R, _mm##RLEN##_srai_epi16(A, 15));      \
        R = _mm##RLEN##_sub_epi16(_mm##RLEN##_xor_si##RLEN(R, DSIGN), DSIGN);

#ifdef NPY_HAVE_AVX512BW
    // 使用AVX-512指令集进行有符号16位除法运算
    __m512i mulhi, q;
    NPYV__DIVC_S16(512, a, divisor.val[0], divisor.val[2], q)
    return q;
#else
    // 获取除数的低256位部分和符号掩码
    const __m256i m     = npyv512_lower_si256(divisor.val[0]);
    const __m256i dsign = npyv512_lower_si256(divisor.val[2]);
    // 将输入向量的低256位和高256位分离
    __m256i lo_a        = npyv512_lower_si256(a);
    __m256i hi_a        = npyv512_higher_si256(a);

    // 定义变量:乘积高位、低位结果向量
    __m256i mulhi, lo_q, hi_q;
    // 对低256位和高256位分别进行除法运算
    NPYV__DIVC_S16(256, lo_a, m, dsign, lo_q)
    NPYV__DIVC_S16(256, hi_a, m, dsign, hi_q)
    // 将低位和高位的结果合并为一个512位向量并返回
    return npyv512_combine_si256(lo_q, hi_q);
#endif
    #undef NPYV__DIVC_S16
}
// divide each unsigned 32-bit element by divisor
NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor)
{
    // 将除数的第一个部分加载为右移位数,用于高位无符号乘法
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    // 将除数的第二个部分加载为右移位数,用于计算 floor(a/d) 的结果
    const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]);
    // 计算 a 和除数的第一个部分的无符号乘积的高位
    __m512i mulhi_even = _mm512_srli_epi64(_mm512_mul_epu32(a, divisor.val[0]), 32);
    // 计算 a 右移32位后与除数的第一个部分的无符号乘积的高位
    __m512i mulhi_odd  = _mm512_mul_epu32(_mm512_srli_epi64(a, 32), divisor.val[0]);
    // 合并偶数和奇数位的高位乘积,使用掩码0xAAAA选择奇数位的结果
    __m512i mulhi      = _mm512_mask_mov_epi32(mulhi_even, 0xAAAA, mulhi_odd);
    // 计算 floor(a/d) = (mulhi + ((a-mulhi) >> shf1)) >> shf2
    __m512i q          = _mm512_sub_epi32(a, mulhi);
            q          = _mm512_srl_epi32(q, shf1);
            q          = _mm512_add_epi32(mulhi, q);
            q          = _mm512_srl_epi32(q, shf2);
    return q;
}

// divide each signed 32-bit element by divisor (round towards zero)
NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor)
{
    // 将除数的第一个部分加载为右移位数,用于有符号乘法的高位计算
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    // 计算 a 和除数的第一个部分的有符号乘积的高位
    __m512i mulhi_even = _mm512_srli_epi64(_mm512_mul_epi32(a, divisor.val[0]), 32);
    // 计算 a 右移32位后与除数的第一个部分的有符号乘积的高位
    __m512i mulhi_odd  = _mm512_mul_epi32(_mm512_srli_epi64(a, 32), divisor.val[0]);
    // 合并偶数和奇数位的高位乘积,使用掩码0xAAAA选择奇数位的结果
    __m512i mulhi      = _mm512_mask_mov_epi32(mulhi_even, 0xAAAA, mulhi_odd);
    // 计算 trunc(a/d) = (q ^ dsign) - dsign,其中 q = ((a + mulhi) >> shf1) - XSIGN(a)
    __m512i q          = _mm512_sra_epi32(_mm512_add_epi32(a, mulhi), shf1);
            q          = _mm512_sub_epi32(q, _mm512_srai_epi32(a, 31));
            q          = _mm512_sub_epi32(_mm512_xor_si512(q, divisor.val[2]), divisor.val[2]);
    return q;
}

// returns the high 64 bits of unsigned 64-bit multiplication
// xref https://stackoverflow.com/a/28827013
NPY_FINLINE npyv_u64 npyv__mullhi_u64(npyv_u64 a, npyv_u64 b)
{
    // 创建用于低位掩码的常量向量
    __m512i lomask = npyv_setall_s64(0xffffffff);
    // 计算 a 和 b 的高32位部分
    __m512i a_hi   = _mm512_srli_epi64(a, 32);        // a0l, a0h, a1l, a1h
    __m512i b_hi   = _mm512_srli_epi64(b, 32);        // b0l, b0h, b1l, b1h
    // 计算部分乘积
    __m512i w0     = _mm512_mul_epu32(a, b);          // a0l*b0l, a1l*b1l
    __m512i w1     = _mm512_mul_epu32(a, b_hi);       // a0l*b0h, a1l*b1h
    __m512i w2     = _mm512_mul_epu32(a_hi, b);       // a0h*b0l, a1h*b0l
    __m512i w3     = _mm512_mul_epu32(a_hi, b_hi);    // a0h*b0h, a1h*b1h
    // 合并部分乘积
    __m512i w0h    = _mm512_srli_epi64(w0, 32);
    __m512i s1     = _mm512_add_epi64(w1, w0h);
    __m512i s1l    = _mm512_and_si512(s1, lomask);
    __m512i s1h    = _mm512_srli_epi64(s1, 32);

    __m512i s2     = _mm512_add_epi64(w2, s1l);
    __m512i s2h    = _mm512_srli_epi64(s2, 32);

    __m512i hi     = _mm512_add_epi64(w3, s1h);
            hi     = _mm512_add_epi64(hi, s2h);
    return hi;
}

// divide each unsigned 64-bit element by a divisor
NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor)
{
    // 使用 SIMD 指令集将 divisor.val[1] 转换为 __m128i 类型
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    // 使用 SIMD 指令集将 divisor.val[2] 转换为 __m128i 类型
    const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]);

    // 计算 a 和 divisor.val[0] 的无符号整数高位乘积
    __m512i mulhi      = npyv__mullhi_u64(a, divisor.val[0]);

    // 计算 floor(a/d) 的近似值,其中 d = divisor.val[0]
    // 使用 SIMD 指令集执行以下操作:
    // 1. 计算 a - mulhi
    // 2. 对结果右移 shf1 位
    // 3. 将 mulhi 加到上述结果
    // 4. 对结果右移 shf2 位
    __m512i q          = _mm512_sub_epi64(a, mulhi);
            q          = _mm512_srl_epi64(q, shf1);
            q          = _mm512_add_epi64(mulhi, q);
            q          = _mm512_srl_epi64(q, shf2);

    // 返回计算得到的 floor(a/d) 的近似值
    return q;
// divide each unsigned 64-bit element by a divisor (round towards zero)
NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor)
{
    // 将第二个128位部分作为移位掩码
    const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]);
    // 高位部分的无符号乘法结果
    __m512i mulhi      = npyv__mullhi_u64(a, divisor.val[0]);
    // 将乘法结果转换为有符号高位乘法结果
    // mulhi - ((a < 0) ? m : 0) - ((m < 0) ? a : 0);
    __m512i asign      = _mm512_srai_epi64(a, 63);
    __m512i msign      = _mm512_srai_epi64(divisor.val[0], 63);
    __m512i m_asign    = _mm512_and_si512(divisor.val[0], asign);
    __m512i a_msign    = _mm512_and_si512(a, msign);
            mulhi      = _mm512_sub_epi64(mulhi, m_asign);
            mulhi      = _mm512_sub_epi64(mulhi, a_msign);
    // q               = ((a + mulhi) >> sh1) - XSIGN(a)
    // 截断(a/d)       = (q ^ dsign) - dsign
    __m512i q          = _mm512_sra_epi64(_mm512_add_epi64(a, mulhi), shf1);
            q          = _mm512_sub_epi64(q, asign);
            q          = _mm512_sub_epi64(_mm512_xor_si512(q, divisor.val[2]), divisor.val[2]);
    return  q;
}
/***************************
 * Division
 ***************************/
// TODO: emulate integer division
#define npyv_div_f32 _mm512_div_ps
#define npyv_div_f64 _mm512_div_pd

/***************************
 * FUSED
 ***************************/
// multiply and add, a*b + c
#define npyv_muladd_f32 _mm512_fmadd_ps
#define npyv_muladd_f64 _mm512_fmadd_pd
// multiply and subtract, a*b - c
#define npyv_mulsub_f32 _mm512_fmsub_ps
#define npyv_mulsub_f64 _mm512_fmsub_pd
// negate multiply and add, -(a*b) + c
#define npyv_nmuladd_f32 _mm512_fnmadd_ps
#define npyv_nmuladd_f64 _mm512_fnmadd_pd
// negate multiply and subtract, -(a*b) - c
#define npyv_nmulsub_f32 _mm512_fnmsub_ps
#define npyv_nmulsub_f64 _mm512_fnmsub_pd
// multiply, add for odd elements and subtract even elements.
// (a * b) -+ c
#define npyv_muladdsub_f32 _mm512_fmaddsub_ps
#define npyv_muladdsub_f64 _mm512_fmaddsub_pd

/***************************
 * Summation: Calculates the sum of all vector elements.
 * there are three ways to implement reduce sum for AVX512:
 * 1- split(256) /add /split(128) /add /hadd /hadd /extract
 * 2- shuff(cross) /add /shuff(cross) /add /shuff /add /shuff /add /extract
 * 3- _mm512_reduce_add_ps/pd
 * The first one is been widely used by many projects
 *
 * the second one is used by Intel Compiler, maybe because the
 * latency of hadd increased by (2-3) starting from Skylake-X which makes two
 * extra shuffles(non-cross) cheaper. check https://godbolt.org/z/s3G9Er for more info.
 *
 * The third one is almost the same as the second one but only works for
 * intel compiler/GCC 7.1/Clang 4, we still need to support older GCC.
 ***************************/
// reduce sum across vector
#ifdef NPY_HAVE_AVX512F_REDUCE
    #define npyv_sum_u32 _mm512_reduce_add_epi32
    #define npyv_sum_u64 _mm512_reduce_add_epi64
    #define npyv_sum_f32 _mm512_reduce_add_ps
    // 定义宏 npyv_sum_f64,用于计算 AVX-512 寄存器中双精度浮点数的累加和
    #define npyv_sum_f64 _mm512_reduce_add_pd
// 定义一个内联函数,用于求解未定义情况下的无符号32位整数向量a的总和
NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a)
{
    // 将256位向量a分为低128位和高128位,并将它们相加
    __m256i half = _mm256_add_epi32(npyv512_lower_si256(a), npyv512_higher_si256(a));
    // 将得到的结果128位向量再进行一次加法操作,得到四个32位整数的和
    __m128i quarter = _mm_add_epi32(_mm256_castsi256_si128(half), _mm256_extracti128_si256(half, 1));
    // 将得到的128位向量进行水平加法操作,得到最终的32位整数和,并返回结果
    quarter = _mm_hadd_epi32(quarter, quarter);
    return _mm_cvtsi128_si32(_mm_hadd_epi32(quarter, quarter));
}

// 定义一个内联函数,用于求解未定义情况下的无符号64位整数向量a的总和
NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a)
{
    // 将256位向量a分为低128位和高128位,并将它们相加
    __m256i four = _mm256_add_epi64(npyv512_lower_si256(a), npyv512_higher_si256(a));
    // 对得到的256位向量进行一系列加法和位混洗操作,得到64位整数的总和
    __m256i two = _mm256_add_epi64(four, _mm256_shuffle_epi32(four, _MM_SHUFFLE(1, 0, 3, 2)));
    // 将得到的256位向量转换为128位,并进行一次128位的加法操作
    __m128i one = _mm_add_epi64(_mm256_castsi256_si128(two), _mm256_extracti128_si256(two, 1));
    // 返回结果向量中的64位整数总和
    return (npy_uint64)npyv128_cvtsi128_si64(one);
}

// 定义一个内联函数,用于求解未定义情况下的单精度浮点数向量a的总和
NPY_FINLINE float npyv_sum_f32(npyv_f32 a)
{
    // 对512位向量a进行一系列的加法和位混洗操作,得到最终的单精度浮点数总和
    __m512 h64   = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(3, 2, 3, 2));
    __m512 sum32 = _mm512_add_ps(a, h64);
    __m512 h32   = _mm512_shuffle_f32x4(sum32, sum32, _MM_SHUFFLE(1, 0, 3, 2));
    __m512 sum16 = _mm512_add_ps(sum32, h32);
    __m512 h16   = _mm512_permute_ps(sum16, _MM_SHUFFLE(1, 0, 3, 2));
    __m512 sum8  = _mm512_add_ps(sum16, h16);
    __m512 h4    = _mm512_permute_ps(sum8, _MM_SHUFFLE(2, 3, 0, 1));
    __m512 sum4  = _mm512_add_ps(sum8, h4);
    // 将最终的512位向量转换为128位向量,并返回其中的单精度浮点数总和
    return _mm_cvtss_f32(_mm512_castps512_ps128(sum4));
}

// 定义一个内联函数,用于求解未定义情况下的双精度浮点数向量a的总和
NPY_FINLINE double npyv_sum_f64(npyv_f64 a)
{
    // 对512位向量a进行一系列的加法和位混洗操作,得到最终的双精度浮点数总和
    __m512d h64   = _mm512_shuffle_f64x2(a, a, _MM_SHUFFLE(3, 2, 3, 2));
    __m512d sum32 = _mm512_add_pd(a, h64);
    __m512d h32   = _mm512_permutex_pd(sum32, _MM_SHUFFLE(1, 0, 3, 2));
    __m512d sum16 = _mm512_add_pd(sum32, h32);
    __m512d h16   = _mm512_permute_pd(sum16, _MM_SHUFFLE(2, 3, 0, 1));
    __m512d sum8  = _mm512_add_pd(sum16, h16);
    // 将最终的512位向量转换为128位向量,并返回其中的双精度浮点数总和
    return _mm_cvtsd_f64(_mm512_castpd512_pd128(sum8));
}

// 定义一个内联函数,用于对无符号8位整数向量a进行扩展并执行求和操作
// 当系统支持AVX512BW指令集时,使用512位向量进行求和
NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a)
{
#ifdef NPY_HAVE_AVX512BW
    // 对512位向量a执行无符号8位整数求和累计操作
    __m512i eight = _mm512_sad_epu8(a, _mm512_setzero_si512());
    // 将512位向量拆分为256位向量,并将其相加
    __m256i four  = _mm256_add_epi16(npyv512_lower_si256(eight), npyv512_higher_si256(eight));
#else
    // 当系统不支持AVX512BW指令集时,对低256位和高256位向量分别执行无符号8位整数求和累计操作,然后将其相加
    __m256i lo_four = _mm256_sad_epu8(npyv512_lower_si256(a), _mm256_setzero_si256());
    __m256i hi_four = _mm256_sad_epu8(npyv512_higher_si256(a), _mm256_setzero_si256());
    __m256i four    = _mm256_add_epi16(lo_four, hi_four);
#endif
    // 将得到的256位向量再次拆分为128位向量,并进行一系列的加法操作,最终得到16位无符号整数的总和
    __m128i two     = _mm_add_epi16(_mm256_castsi256_si128(four), _mm256_extracti128_si256(four, 1));
    __m128i one     = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two));
    // 将最终的128位向量中的整数转换为16位无符号整数,并返回结果
    return (npy_uint16)_mm_cvtsi128_si32(one);
}

// 定义一个内联函数,用于对无符号16位整数向量a执行扩展并执行求和操作
NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a)
{
    // 创建一个掩码,用于提取偶数位的16位整数
    const npyv_u16 even_mask = _mm512_set1_epi32(0x0000FFFF);
    __m512i even = _mm512_and_si512(a, even_mask);
    // 对原始向量右移16位,得到奇数位的16位整数,并将其相加
    __m512i odd  = _mm512_srli_epi32(a, 16);
    __m512i ff   = _mm512_add_epi32(even, odd);
    // 调用npv_sum_u32函数,对上一步得到的32位整数向量求和,并返回结果
    return npyv_sum_u32(ff);
}
#endif // _NPY_SIMD_AVX512_ARITHMETIC_H

.\numpy\numpy\_core\src\common\simd\avx512\avx512.h

#ifndef _NPY_SIMD_H_
    #error "Not a standalone header"
#endif
// 如果未定义 _NPY_SIMD_H_,则输出错误信息,不是独立头文件
#define NPY_SIMD 512
// 定义 NPY_SIMD 为 512,表示 SIMD 宽度为 512 比特
#define NPY_SIMD_WIDTH 64
// 定义 NPY_SIMD_WIDTH 为 64,表示每个 SIMD 寄存器的宽度为 64 比特
#define NPY_SIMD_F32 1
// 定义 NPY_SIMD_F32 为 1,表示支持单精度浮点数的 SIMD 操作
#define NPY_SIMD_F64 1
// 定义 NPY_SIMD_F64 为 1,表示支持双精度浮点数的 SIMD 操作
#define NPY_SIMD_FMA3 1 // native support
// 定义 NPY_SIMD_FMA3 为 1,表示本机支持 Fused Multiply-Add (FMA3) 指令
#define NPY_SIMD_BIGENDIAN 0
// 定义 NPY_SIMD_BIGENDIAN 为 0,表示 SIMD 环境不是大端序
#define NPY_SIMD_CMPSIGNAL 0
// 定义 NPY_SIMD_CMPSIGNAL 为 0,表示 SIMD 比较信号不支持

// 以下两个宏定义允许使用 _mm512_i32gather_* 和 _mm512_i32scatter_*,限制为内存加载和存储的最大步长
#define NPY_SIMD_MAXLOAD_STRIDE32  (0x7fffffff / 16)
#define NPY_SIMD_MAXSTORE_STRIDE32 (0x7fffffff / 16)

typedef __m512i npyv_u8;
typedef __m512i npyv_s8;
typedef __m512i npyv_u16;
typedef __m512i npyv_s16;
typedef __m512i npyv_u32;
typedef __m512i npyv_s32;
typedef __m512i npyv_u64;
typedef __m512i npyv_s64;
typedef __m512  npyv_f32;
typedef __m512d npyv_f64;

#ifdef NPY_HAVE_AVX512BW
// 如果定义了 NPY_HAVE_AVX512BW,使用 AVX-512BW 指令集
typedef __mmask64 npyv_b8;
typedef __mmask32 npyv_b16;
#else
// 如果未定义 NPY_HAVE_AVX512BW,使用普通的 AVX-512 整型寄存器
typedef __m512i npyv_b8;
typedef __m512i npyv_b16;
#endif
// 定义 AVX-512 下的掩码类型,根据 NPY_HAVE_AVX512BW 的定义选择 __mmask* 或 __m512i

typedef __mmask16 npyv_b32;
typedef __mmask8  npyv_b64;

typedef struct { __m512i val[2]; } npyv_m512ix2;
typedef npyv_m512ix2 npyv_u8x2;
typedef npyv_m512ix2 npyv_s8x2;
typedef npyv_m512ix2 npyv_u16x2;
typedef npyv_m512ix2 npyv_s16x2;
typedef npyv_m512ix2 npyv_u32x2;
typedef npyv_m512ix2 npyv_s32x2;
typedef npyv_m512ix2 npyv_u64x2;
typedef npyv_m512ix2 npyv_s64x2;

typedef struct { __m512i val[3]; } npyv_m512ix3;
typedef npyv_m512ix3 npyv_u8x3;
typedef npyv_m512ix3 npyv_s8x3;
typedef npyv_m512ix3 npyv_u16x3;
typedef npyv_m512ix3 npyv_s16x3;
typedef npyv_m512ix3 npyv_u32x3;
typedef npyv_m512ix3 npyv_s32x3;
typedef npyv_m512ix3 npyv_u64x3;
typedef npyv_m512ix3 npyv_s64x3;

typedef struct { __m512  val[2]; } npyv_f32x2;
typedef struct { __m512d val[2]; } npyv_f64x2;
typedef struct { __m512  val[3]; } npyv_f32x3;
typedef struct { __m512d val[3]; } npyv_f64x3;

#define npyv_nlanes_u8  64
#define npyv_nlanes_s8  64
#define npyv_nlanes_u16 32
#define npyv_nlanes_s16 32
#define npyv_nlanes_u32 16
#define npyv_nlanes_s32 16
#define npyv_nlanes_u64 8
#define npyv_nlanes_s64 8
#define npyv_nlanes_f32 16
#define npyv_nlanes_f64 8

#include "utils.h"
#include "memory.h"
#include "misc.h"
#include "reorder.h"
#include "operators.h"
#include "conversion.h"
#include "arithmetic.h"
#include "math.h"
#include "maskop.h"

.\numpy\numpy\_core\src\common\simd\avx512\conversion.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_CVT_H
#define _NPY_SIMD_AVX512_CVT_H

// 如果未定义NPY_SIMD,抛出错误信息,要求不要单独使用此头文件
#ifdef NPY_HAVE_AVX512BW
    // 如果支持AVX512BW,则使用AVX512指令集中的_mm512_movm_epi8函数进行无符号8位整数向量到掩码的转换
    #define npyv_cvt_u8_b8  _mm512_movm_epi8
    // 如果支持AVX512BW,则使用AVX512指令集中的_mm512_movm_epi16函数进行无符号16位整数向量到掩码的转换
    #define npyv_cvt_u16_b16 _mm512_movm_epi16
#else
    // 否则,定义宏npv_cvt_u8_b8和npyv_cvt_u16_b16分别为输入和输出相等
    #define npyv_cvt_u8_b8(BL) BL
    #define npyv_cvt_u16_b16(BL) BL
#endif
// npyv_cvt_s8_b8和npyv_cvt_s16_b16分别为npv_cvt_u8_b8和npyv_cvt_u16_b16的别名
#define npyv_cvt_s8_b8  npyv_cvt_u8_b8
#define npyv_cvt_s16_b16 npyv_cvt_u16_b16

#ifdef NPY_HAVE_AVX512DQ
    // 如果支持AVX512DQ,则使用AVX512指令集中的_mm512_movm_epi32函数进行无符号32位整数向量到掩码的转换
    #define npyv_cvt_u32_b32 _mm512_movm_epi32
    // 如果支持AVX512DQ,则使用AVX512指令集中的_mm512_movm_epi64函数进行无符号64位整数向量到掩码的转换
    #define npyv_cvt_u64_b64 _mm512_movm_epi64
#else
    // 否则,定义宏npyv_cvt_u32_b32和npyv_cvt_u64_b64为使用BL和指定值-1作为输入
    #define npyv_cvt_u32_b32(BL) _mm512_maskz_set1_epi32(BL, (int)-1)
    #define npyv_cvt_u64_b64(BL) _mm512_maskz_set1_epi64(BL, (npy_int64)-1)
#endif
// npyv_cvt_s32_b32和npyv_cvt_s64_b64分别为npyv_cvt_u32_b32和npyv_cvt_u64_b64的别名
#define npyv_cvt_s32_b32 npyv_cvt_u32_b32
#define npyv_cvt_s64_b64 npyv_cvt_u64_b64
// 定义npv_cvt_f32_b32和npv_cvt_f64_b64分别为_mm512_castsi512_ps和npyv_cvt_u32_b32和npyv_cvt_u64_b64的别名
#define npyv_cvt_f32_b32(BL) _mm512_castsi512_ps(npyv_cvt_u32_b32(BL))
#define npyv_cvt_f64_b64(BL) _mm512_castsi512_pd(npyv_cvt_u64_b64(BL))

// 将整数向量转换为掩码
#ifdef NPY_HAVE_AVX512BW
    // 如果支持AVX512BW,则使用AVX512指令集中的_mm512_movepi8_mask和_mm512_movepi16_mask分别进行8位和16位整数向量到掩码的转换
    #define npyv_cvt_b8_u8 _mm512_movepi8_mask
    #define npyv_cvt_b16_u16 _mm512_movepi16_mask
#else
    // 否则,定义宏npyv_cvt_b8_u8和npyv_cvt_b16_u16为输入
    #define npyv_cvt_b8_u8(A)  A
    #define npyv_cvt_b16_u16(A) A
#endif
// npyv_cvt_b8_s8和npyv_cvt_b16_s16分别为npyv_cvt_b8_u8和npyv_cvt_b16_u16的别名
#define npyv_cvt_b8_s8  npyv_cvt_b8_u8
#define npyv_cvt_b16_s16 npyv_cvt_b16_u16

#ifdef NPY_HAVE_AVX512DQ
    // 如果支持AVX512DQ,则使用AVX512指令集中的_mm512_movepi32_mask和_mm512_movepi64_mask分别进行32位和64位整数向量到掩码的转换
    #define npyv_cvt_b32_u32 _mm512_movepi32_mask
    #define npyv_cvt_b64_u64 _mm512_movepi64_mask
#else
    // 否则,定义宏npyv_cvt_b32_u32和npyv_cvt_b64_u64为使用A和_mm512_setzero_si512作为输入
    #define npyv_cvt_b32_u32(A) _mm512_cmpneq_epu32_mask(A, _mm512_setzero_si512())
    #define npyv_cvt_b64_u64(A) _mm512_cmpneq_epu64_mask(A, _mm512_setzero_si512())
#endif
// npyv_cvt_b32_s32和npyv_cvt_b64_s64分别为npyv_cvt_b32_u32和npyv_cvt_b64_u64的别名
#define npyv_cvt_b32_s32 npyv_cvt_b32_u32
#define npyv_cvt_b64_s64 npyv_cvt_b64_u64
// 定义npv_cvt_b32_f32和npv_cvt_b64_f64分别为npyv_cvt_b32_u32和npyv_cvt_b64_u64的别名
#define npyv_cvt_b32_f32(A) npyv_cvt_b32_u32(_mm512_castps_si512(A))
#define npyv_cvt_b64_f64(A) npyv_cvt_b64_u64(_mm512_castpd_si512(A))

// 扩展函数
NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data)
{
    npyv_u16x2 r;
    // 获取数据的低256位和高256位
    __m256i lo = npyv512_lower_si256(data);
    __m256i hi = npyv512_higher_si256(data);
#ifdef NPY_HAVE_AVX512BW
    // 如果支持AVX512BW,则将低256位和高256位的无符号8位整数转换为无符号16位整数,分别存入r的第一个和第二个元素
    r.val[0] = _mm512_cvtepu8_epi16(lo);
    r.val[1] = _mm512_cvtepu8_epi16(hi);
#else
    // 否则,将低256位和高256位的无符号8位整数先分别转换为无符号16位整数,然后组合成256位,分别存入r的第一个和第二个元素
    __m256i loelo = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(lo));
    __m256i loehi = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(lo, 1));
    __m256i hielo = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(hi));
    __m256i hiehi = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(hi, 1));
    r.val[0] = npyv512_combine_si256(loelo, loehi);
    r.val[1] = npyv512_combine_si256(hielo, hiehi);
#endif
    return r;
}

NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data)
{
    npyv_u32x2 r;
    // 获取数据的低256位和高256位
    __m256i lo = npyv512_lower_si256(data);
    __m256i hi = npyv512_higher_si256(data);
#ifdef NPY_HAVE_AVX512BW
    // 如果支持AVX512BW,则将低256位和高256位的
    # 将 AVX2 寄存器中的低位 128 位转换为整数型寄存器 __m256i
    __m256i hielo = _mm256_cvtepu16_epi32(_mm256_castsi256_si128(hi));
    # 将 AVX2 寄存器中的高位 128 位转换为整数型寄存器 __m256i
    __m256i hiehi = _mm256_cvtepu16_epi32(_mm256_extracti128_si256(hi, 1));
    # 将两个 256 位 AVX2 寄存器的低位和高位合并为一个 512 位 AVX-512 寄存器
    r.val[0] = npyv512_combine_si256(loelo, loehi);
    # 将两个 256 位 AVX2 寄存器的低位和高位合并为一个 512 位 AVX-512 寄存器
    r.val[1] = npyv512_combine_si256(hielo, hiehi);
#endif
    return r;
}

// 将两个16位布尔值打包成一个8位布尔向量
NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) {
#ifdef NPY_HAVE_AVX512BW
    // 使用AVX-512指令集进行位解压缩和打包
    return _mm512_kunpackd((__mmask64)b, (__mmask64)a);
#else
    // 创建索引以重新排列16位整数元素
    const __m512i idx = _mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7);
    // 使用AVX-512指令集将两个16位整数向量打包成8位整数向量
    return _mm512_permutexvar_epi64(idx, npyv512_packs_epi16(a, b));
#endif
}

// 将四个32位布尔向量打包成一个8位布尔向量
NPY_FINLINE npyv_b8
npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) {
#ifdef NPY_HAVE_AVX512BW
    // 使用AVX-512指令集进行位解压缩和打包
    __mmask32 ab = _mm512_kunpackw((__mmask32)b, (__mmask32)a);
    __mmask32 cd = _mm512_kunpackw((__mmask32)d, (__mmask32)c);
    // 调用上一函数,将两个32位布尔向量打包成一个8位布尔向量
    return npyv_pack_b8_b16(ab, cd);
#else
    // 创建索引以重新排列32位整数元素
    const __m512i idx = _mm512_setr_epi32(
        0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15);
    // 将四个32位整数向量打包成两个16位整数向量
    __m256i ta = npyv512_pack_lo_hi(npyv_cvt_u32_b32(a));
    __m256i tb = npyv512_pack_lo_hi(npyv_cvt_u32_b32(b));
    __m256i tc = npyv512_pack_lo_hi(npyv_cvt_u32_b32(c));
    __m256i td = npyv512_pack_lo_hi(npyv_cvt_u32_b32(d));
    // 将两个16位整数向量打包成8位整数向量
    __m256i ab = _mm256_packs_epi16(ta, tb);
    __m256i cd = _mm256_packs_epi16(tc, td);
    // 将两个8位整数向量打包成一个8位整数向量
    __m512i abcd = npyv512_combine_si256(ab, cd);
    // 使用AVX-512指令集根据索引重新排列元素
    return _mm512_permutexvar_epi32(idx, abcd);
#endif
}

// 将八个64位布尔向量打包成一个8位布尔向量
NPY_FINLINE npyv_b8
npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d,
                 npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) {
    // 使用AVX-512指令集进行位解压缩和打包
    __mmask16 ab = _mm512_kunpackb((__mmask16)b, (__mmask16)a);
    __mmask16 cd = _mm512_kunpackb((__mmask16)d, (__mmask16)c);
    __mmask16 ef = _mm512_kunpackb((__mmask16)f, (__mmask16)e);
    __mmask16 gh = _mm512_kunpackb((__mmask16)h, (__mmask16)g);
    // 调用上一函数,将四个16位布尔向量打包成一个8位布尔向量
    return npyv_pack_b8_b32(ab, cd, ef, gh);
}
/*
 * A compiler bug workaround on Intel Compiler Classic.
 * The bug manifests specifically when the
 * scalar result of _cvtmask64_u64 is compared against the constant -1. This
 * comparison uniquely triggers a bug under conditions of equality (==) or
 * inequality (!=) checks, which are typically used in reduction operations like
 * np.logical_or.
 *
 * The underlying issue arises from the compiler's optimizer. When the last
 * vector comparison instruction operates on zmm, the optimizer erroneously
 * emits a duplicate of this instruction but on the lower half register ymm. It
 * then performs a bitwise XOR operation between the mask produced by this
 * duplicated instruction and the mask from the original comparison instruction.
 * This erroneous behavior leads to incorrect results.
 *
 * See https://github.com/numpy/numpy/issues/26197#issuecomment-2056750975
 */
#ifdef __INTEL_COMPILER
// 使用volatile修饰符以解决Intel编译器经典版本上的编译器错误
#define NPYV__VOLATILE_CVTMASK64 volatile
#else
// 在非Intel编译器上不使用volatile修饰符
#define NPYV__VOLATILE_CVTMASK64
#endif
// 将布尔向量转换为整数位域
NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) {
#ifdef NPY_HAVE_AVX512BW_MASK
    // 将布尔向量转换为64位整数
    npy_uint64 NPYV__VOLATILE_CVTMASK64 t = (npy_uint64)_cvtmask64_u64(a);
    return t;
#elif defined(NPY_HAVE_AVX512BW)
    # 如果定义了 NPY_HAVE_AVX512BW,则执行以下代码段
    npy_uint64 NPYV__VOLATILE_CVTMASK64 t = (npy_uint64)a;
    return t;
#else
    # 否则执行以下代码段
    int mask_lo = _mm256_movemask_epi8(npyv512_lower_si256(a));
    int mask_hi = _mm256_movemask_epi8(npyv512_higher_si256(a));
    return (unsigned)mask_lo | ((npy_uint64)(unsigned)mask_hi << 32);
#endif
}
#undef NPYV__VOLATILE_CVTMASK64

NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a)
{
#ifdef NPY_HAVE_AVX512BW_MASK
    # 如果定义了 NPY_HAVE_AVX512BW_MASK,则执行以下代码段
    return (npy_uint32)_cvtmask32_u32(a);
#elif defined(NPY_HAVE_AVX512BW)
    # 如果定义了 NPY_HAVE_AVX512BW,则执行以下代码段
    return (npy_uint32)a;
#else
    # 否则执行以下代码段
    __m256i pack = _mm256_packs_epi16(
        npyv512_lower_si256(a), npyv512_higher_si256(a)
    );
    return (npy_uint32)_mm256_movemask_epi8(_mm256_permute4x64_epi64(pack, _MM_SHUFFLE(3, 1, 2, 0)));
#endif
}
NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a)
{ return (npy_uint16)a; }
NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a)
{
#ifdef NPY_HAVE_AVX512DQ_MASK
    # 如果定义了 NPY_HAVE_AVX512DQ_MASK,则执行以下代码段
    return _cvtmask8_u32(a);
#else
    # 否则执行以下代码段
    return (npy_uint8)a;
#endif
}

// round to nearest integer (assuming even)
#define npyv_round_s32_f32 _mm512_cvtps_epi32
NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b)
{
    // 将 a 和 b 转换为整数(向最近的偶数舍入)
    __m256i lo = _mm512_cvtpd_epi32(a), hi = _mm512_cvtpd_epi32(b);
    // 将两个 __m256i 类型的变量合并成一个 npyv_s32 类型的变量并返回
    return npyv512_combine_si256(lo, hi);
}

#endif // _NPY_SIMD_AVX512_CVT_H

.\numpy\numpy\_core\src\common\simd\avx512\maskop.h

#ifndef NPY_SIMD
    #error "Not a standalone header, use simd/simd.h instead"
#endif

#ifndef _NPY_SIMD_AVX512_MASKOP_H
#define _NPY_SIMD_AVX512_MASKOP_H

/**
 * Implements conditional addition and subtraction.
 * e.g. npyv_ifadd_f32(m, a, b, c) -> m ? a + b : c
 * e.g. npyv_ifsub_f32(m, a, b, c) -> m ? a - b : c
 */

// 定义 AVX512 下的条件加法和减法操作
#define NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(SFX, BSFX)       \
    NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX                   \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \
    {                                                         \
        // 执行向量加法 a + b
        npyv_##SFX add = npyv_add_##SFX(a, b);                \
        // 根据掩码 m 选择返回加法结果 add 或者 c
        return npyv_select_##SFX(m, add, c);                  \
    }                                                         \
    NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX                   \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \
    {                                                         \
        // 执行向量减法 a - b
        npyv_##SFX sub = npyv_sub_##SFX(a, b);                \
        // 根据掩码 m 选择返回减法结果 sub 或者 c
        return npyv_select_##SFX(m, sub, c);                  \
    }

// 定义 AVX512 下的条件加法和减法操作,使用 AVX512 指令
#define NPYV_IMPL_AVX512_MASK_ADDSUB(SFX, BSFX, ZSFX)          \
    NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX                    \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c)  \
    { return _mm512_mask_add_##ZSFX(c, m, a, b); }             \
    NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX                    \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c)  \
    { return _mm512_mask_sub_##ZSFX(c, m, a, b); }

#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX512BW,则使用 AVX512 指令实现 u8, s8, u16, s16 类型的条件加减法
    NPYV_IMPL_AVX512_MASK_ADDSUB(u8,  b8,  epi8)
    NPYV_IMPL_AVX512_MASK_ADDSUB(s8,  b8,  epi8)
    NPYV_IMPL_AVX512_MASK_ADDSUB(u16, b16, epi16)
    NPYV_IMPL_AVX512_MASK_ADDSUB(s16, b16, epi16)
#else
    // 如果不支持 AVX512BW,则使用仿真方式实现 u8, s8, u16, s16 类型的条件加减法
    NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(u8,  b8)
    NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(s8,  b8)
    NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(u16, b16)
    NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(s16, b16)
#endif

// 使用 AVX512 指令实现 u32, s32, u64, s64, f32, f64 类型的条件加减法
NPYV_IMPL_AVX512_MASK_ADDSUB(u32, b32, epi32)
NPYV_IMPL_AVX512_MASK_ADDSUB(s32, b32, epi32)
NPYV_IMPL_AVX512_MASK_ADDSUB(u64, b64, epi64)
NPYV_IMPL_AVX512_MASK_ADDSUB(s64, b64, epi64)
NPYV_IMPL_AVX512_MASK_ADDSUB(f32, b32, ps)
NPYV_IMPL_AVX512_MASK_ADDSUB(f64, b64, pd)

// 使用 AVX512 指令实现条件除法,m ? a / b : c
NPY_FINLINE npyv_f32 npyv_ifdiv_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b, npyv_f32 c)
{ return _mm512_mask_div_ps(c, m, a, b); }
// 使用 AVX512 指令实现条件除法,m ? a / b : 0
NPY_FINLINE npyv_f32 npyv_ifdivz_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b)
{ return _mm512_maskz_div_ps(m, a, b); }
// 使用 AVX512 指令实现条件除法,m ? a / b : c
NPY_FINLINE npyv_f64 npyv_ifdiv_f64(npyv_b32 m, npyv_f64 a, npyv_f64 b, npyv_f64 c)
{ return _mm512_mask_div_pd(c, m, a, b); }
// 使用 AVX512 指令实现条件除法,m ? a / b : 0
NPY_FINLINE npyv_f64 npyv_ifdivz_f64(npyv_b32 m, npyv_f64 a, npyv_f64 b)
{ return _mm512_maskz_div_pd(m, a, b); }

#endif // _NPY_SIMD_AVX512_MASKOP_H

.\numpy\numpy\_core\src\common\simd\avx512\math.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_MATH_H
#define _NPY_SIMD_AVX512_MATH_H

/***************************
 * Elementary
 ***************************/

// Square root functions for AVX512, operating on vectors of single and double precision floating point numbers
#define npyv_sqrt_f32 _mm512_sqrt_ps
#define npyv_sqrt_f64 _mm512_sqrt_pd

// Reciprocal functions for AVX512, computing the reciprocal of each element in a vector
NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a)
{ return _mm512_div_ps(_mm512_set1_ps(1.0f), a); }
NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a)
{ return _mm512_div_pd(_mm512_set1_pd(1.0), a); }

// Absolute value functions for AVX512, computing absolute values of vectors of single and double precision floating point numbers
NPY_FINLINE npyv_f32 npyv_abs_f32(npyv_f32 a)
{
#if 0 // def NPY_HAVE_AVX512DQ
    return _mm512_range_ps(a, a, 8);
#else
    return npyv_and_f32(
        a, _mm512_castsi512_ps(_mm512_set1_epi32(0x7fffffff))
    );
#endif
}
NPY_FINLINE npyv_f64 npyv_abs_f64(npyv_f64 a)
{
#if 0 // def NPY_HAVE_AVX512DQ
    return _mm512_range_pd(a, a, 8);
#else
    return npyv_and_f64(
        a, _mm512_castsi512_pd(npyv_setall_s64(0x7fffffffffffffffLL))
    );
#endif
}

// Square functions for AVX512, computing element-wise squares of vectors of single and double precision floating point numbers
NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a)
{ return _mm512_mul_ps(a, a); }
NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a)
{ return _mm512_mul_pd(a, a); }

// Maximum functions for AVX512, computing element-wise maximums of vectors of single and double precision floating point numbers
#define npyv_max_f32 _mm512_max_ps
#define npyv_max_f64 _mm512_max_pd

// Maximum with propagation of NaNs for single precision floating point numbers in AVX512
NPY_FINLINE npyv_f32 npyv_maxp_f32(npyv_f32 a, npyv_f32 b)
{
    __mmask16 nn = _mm512_cmp_ps_mask(b, b, _CMP_ORD_Q);
    return _mm512_mask_max_ps(a, nn, a, b);
}
// Maximum with propagation of NaNs for double precision floating point numbers in AVX512
NPY_FINLINE npyv_f64 npyv_maxp_f64(npyv_f64 a, npyv_f64 b)
{
    __mmask8 nn = _mm512_cmp_pd_mask(b, b, _CMP_ORD_Q);
    return _mm512_mask_max_pd(a, nn, a, b);
}

// Maximum with NaN handling for single precision floating point numbers in AVX512
NPY_FINLINE npyv_f32 npyv_maxn_f32(npyv_f32 a, npyv_f32 b)
{
    __mmask16 nn = _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q);
    return _mm512_mask_max_ps(a, nn, a, b);
}
// Maximum with NaN handling for double precision floating point numbers in AVX512
NPY_FINLINE npyv_f64 npyv_maxn_f64(npyv_f64 a, npyv_f64 b)
{
    __mmask8 nn = _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q);
    return _mm512_mask_max_pd(a, nn, a, b);
}

// Maximum functions for integer types in AVX512, using unsigned and signed 8, 16, 32, and 64-bit integers
#ifdef NPY_HAVE_AVX512BW
    #define npyv_max_u8 _mm512_max_epu8
    #define npyv_max_s8 _mm512_max_epi8
    #define npyv_max_u16 _mm512_max_epu16
    #define npyv_max_s16 _mm512_max_epi16
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_u8, _mm256_max_epu8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_s8, _mm256_max_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_u16, _mm256_max_epu16)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_s16, _mm256_max_epi16)
#endif
#define npyv_max_u32 _mm512_max_epu32
#define npyv_max_s32 _mm512_max_epi32
#define npyv_max_u64 _mm512_max_epu64
#define npyv_max_s64 _mm512_max_epi64

// Minimum functions for AVX512, computing element-wise minimums of vectors of single precision floating point numbers
#define npyv_min_f32 _mm512_min_ps

#endif // _NPY_SIMD_AVX512_MATH_H
#define npyv_min_f64 _mm512_min_pd
// 定义宏,将 _mm512_min_pd 重命名为 npyv_min_f64,用于执行双精度浮点数的最小值操作

// 返回 a 和 b 中每个对应元素的最小值,支持 IEEE 浮点算术(IEC 60559)
// - 如果其中一个向量包含 NaN,则设置另一个向量对应元素的值
// - 只有当两个对应元素都为 NaN 时,才设置 NaN
NPY_FINLINE npyv_f32 npyv_minp_f32(npyv_f32 a, npyv_f32 b)
{
    __mmask16 nn = _mm512_cmp_ps_mask(b, b, _CMP_ORD_Q);
    // 使用掩码 nn,将 a 和 b 中不是 NaN 的元素对应位置的最小值组成新向量返回
    return _mm512_mask_min_ps(a, nn, a, b);
}

// 返回 a 和 b 中每个对应元素的最小值,支持 IEEE 双精度浮点数算术(IEC 60559)
// - 如果其中一个向量包含 NaN,则设置另一个向量对应元素的值
// - 只有当两个对应元素都为 NaN 时,才设置 NaN
NPY_FINLINE npyv_f64 npyv_minp_f64(npyv_f64 a, npyv_f64 b)
{
    __mmask8 nn = _mm512_cmp_pd_mask(b, b, _CMP_ORD_Q);
    // 使用掩码 nn,将 a 和 b 中不是 NaN 的元素对应位置的最小值组成新向量返回
    return _mm512_mask_min_pd(a, nn, a, b);
}

// 返回 a 和 b 中每个对应元素的最小值,支持 IEEE 浮点算术(IEC 60559),传播 NaN
// - 如果任何对应元素为 NaN,则将该位置设置为 NaN
NPY_FINLINE npyv_f32 npyv_minn_f32(npyv_f32 a, npyv_f32 b)
{
    __mmask16 nn = _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q);
    // 使用掩码 nn,将 a 和 b 中 a 不是 NaN 的元素对应位置的最小值组成新向量返回
    return _mm512_mask_min_ps(a, nn, a, b);
}

// 返回 a 和 b 中每个对应元素的最小值,支持 IEEE 双精度浮点数算术(IEC 60559),传播 NaN
// - 如果任何对应元素为 NaN,则将该位置设置为 NaN
NPY_FINLINE npyv_f64 npyv_minn_f64(npyv_f64 a, npyv_f64 b)
{
    __mmask8 nn = _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q);
    // 使用掩码 nn,将 a 和 b 中 a 不是 NaN 的元素对应位置的最小值组成新向量返回
    return _mm512_mask_min_pd(a, nn, a, b);
}

// 返回 a 和 b 中每个对应元素的最小值,支持整数操作
#ifdef NPY_HAVE_AVX512BW
    #define npyv_min_u8 _mm512_min_epu8
    #define npyv_min_s8 _mm512_min_epi8
    #define npyv_min_u16 _mm512_min_epu16
    #define npyv_min_s16 _mm512_min_epi16
#else
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_u8, _mm256_min_epu8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_s8, _mm256_min_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_u16, _mm256_min_epu16)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_s16, _mm256_min_epi16)
#endif

#define npyv_min_u32 _mm512_min_epu32
#define npyv_min_s32 _mm512_min_epi32
#define npyv_min_u64 _mm512_min_epu64
#define npyv_min_s64 _mm512_min_epi64

#ifdef NPY_HAVE_AVX512F_REDUCE
    #define npyv_reduce_min_u32 _mm512_reduce_min_epu32
    #define npyv_reduce_min_s32 _mm512_reduce_min_epi32
    #define npyv_reduce_min_u64 _mm512_reduce_min_epu64
    #define npyv_reduce_min_s64 _mm512_reduce_min_epi64
    #define npyv_reduce_min_f32 _mm512_reduce_min_ps
    #define npyv_reduce_min_f64 _mm512_reduce_min_pd
    #define npyv_reduce_max_u32 _mm512_reduce_max_epu32
    #define npyv_reduce_max_s32 _mm512_reduce_max_epi32
    #define npyv_reduce_max_u64 _mm512_reduce_max_epu64
    #define npyv_reduce_max_s64 _mm512_reduce_max_epi64
    #define npyv_reduce_max_f32 _mm512_reduce_max_ps
    #define npyv_reduce_max_f64 _mm512_reduce_max_pd
#else
    // 32位和64位的减少最小和最大值的实现
    #define NPY_IMPL_AVX512_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN)                              \
        // 定义 AVX-512 下的最小值和最大值归约函数,参数分别为数据类型、指令类型、向量指令类型
        NPY_FINLINE STYPE##32 npyv_reduce_##INTRIN##32(__m512i a)                              \
        {                                                                                      \
            // 将512位整型寄存器拆分为两个256位整型寄存器
            __m256i v256 = _mm256_##VINTRIN##32(npyv512_lower_si256(a),                        \
                    npyv512_higher_si256(a));                                                  \
            // 从256位整型寄存器中抽取低128位整型寄存器
            __m128i v128 = _mm_##VINTRIN##32(_mm256_castsi256_si128(v256),                     \
                    _mm256_extracti128_si256(v256, 1));                                        \
            // 使用 Shuffle 指令对128位整型寄存器进行重排,得到64位整型寄存器
            __m128i v64 =  _mm_##VINTRIN##32(v128, _mm_shuffle_epi32(v128,                     \
                        (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));                              \
            // 再次使用 Shuffle 指令对64位整型寄存器进行重排,得到32位整型寄存器
            __m128i v32 = _mm_##VINTRIN##32(v64, _mm_shuffle_epi32(v64,                        \
                        (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));                              \
            // 将最终结果转换为32位整数并返回
            return (STYPE##32)_mm_cvtsi128_si32(v32);                                          \
        }                                                                                      \
        // 定义 AVX-512 下的最小值和最大值归约函数,参数分别为数据类型、指令类型、向量指令类型
        NPY_FINLINE STYPE##64 npyv_reduce_##INTRIN##64(__m512i a)                              \
        {                                                                                      \
            // 使用 Shuffle 指令对512位整型寄存器进行重排,得到256位整型寄存器
            __m512i v256 = _mm512_##VINTRIN##64(a,                                             \
                    _mm512_shuffle_i64x2(a, a, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));       \
            // 再次使用 Shuffle 指令对256位整型寄存器进行重排,得到128位整型寄存器
            __m512i v128 = _mm512_##VINTRIN##64(v256,                                          \
                    _mm512_shuffle_i64x2(v256, v256, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \
            // 使用 Shuffle 指令对128位整型寄存器进行重排,得到64位整型寄存器
            __m512i v64  = _mm512_##VINTRIN##64(v128,                                          \
                    _mm512_shuffle_epi32(v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));       \
            // 提取64位整型寄存器中的第一个元素,并将结果转换为64位整数返回
            return (STYPE##64)npyv_extract0_u64(v64);                                          \
        }
    
    // 定义 AVX-512 下的最小值和最大值归约函数的具体实现
    NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, min_u, min_epu)
    NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int,  min_s, min_epi)
    NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, max_u, max_epu)
    NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int,  max_s, max_epi)
    #undef NPY_IMPL_AVX512_REDUCE_MINMAX
    // 取消宏定义 NPY_IMPL_AVX512_REDUCE_MINMAX,并注释说明为 ps & pd 的最小值和最大值归约
    #define NPY_IMPL_AVX512_REDUCE_MINMAX(INTRIN)                                         \
        // 定义 AVX512 下的最小值和最大值归约函数,使用指定的 INTRIN 操作
        NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a)                          \
        {                                                                                 \
            // 使用 AVX2 指令集下的 _mm256_##INTRIN##_ps 函数,对 a 进行归约操作
            __m256 v256 = _mm256_##INTRIN##_ps(                                           \
                    npyv512_lower_ps256(a), npyv512_higher_ps256(a));                     \
            // 将结果从 AVX256 转换为 AVX128,继续使用 AVX 指令进行归约
            __m128 v128 = _mm_##INTRIN##_ps(                                              \
                    _mm256_castps256_ps128(v256), _mm256_extractf128_ps(v256, 1));        \
            // 在 AVX128 中进行进一步的归约操作
            __m128 v64 =  _mm_##INTRIN##_ps(v128,                                         \
                    _mm_shuffle_ps(v128, v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));  \
            // 继续使用 AVX 指令在更低精度下进行最后的归约操作
            __m128 v32 = _mm_##INTRIN##_ps(v64,                                           \
                    _mm_shuffle_ps(v64, v64, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));    \
            // 返回最终结果,将 AVX32 结果转换为 float 类型
            return _mm_cvtss_f32(v32);                                                    \
        }                                                                                 \
        // 定义 AVX512 下的双精度最小值和最大值归约函数,使用指定的 INTRIN 操作
        NPY_FINLINE double npyv_reduce_##INTRIN##_f64(npyv_f64 a)                         \
        {                                                                                 \
            // 使用 AVX2 指令集下的 _mm256_##INTRIN##_pd 函数,对 a 进行归约操作
            __m256d v256 = _mm256_##INTRIN##_pd(                                          \
                    npyv512_lower_pd256(a), npyv512_higher_pd256(a));                     \
            // 将结果从 AVX256 转换为 AVX128,继续使用 AVX 指令进行归约
            __m128d v128 = _mm_##INTRIN##_pd(                                             \
                    _mm256_castpd256_pd128(v256), _mm256_extractf128_pd(v256, 1));        \
            // 在 AVX128 中进行进一步的归约操作
            __m128d v64 =  _mm_##INTRIN##_pd(v128,                                        \
                    _mm_shuffle_pd(v128, v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));  \
            // 返回最终结果,将 AVX64 结果转换为 double 类型
            return _mm_cvtsd_f64(v64);                                                    \
        }
    // 取消定义 NPY_IMPL_AVX512_REDUCE_MINMAX 宏
    #undef NPY_IMPL_AVX512_REDUCE_MINMAX
#ifndef

#if 指令,用于条件编译,检查是否已经定义了指定的宏,如果没有则编译后续代码。


#define NPY_IMPL_AVX512_REDUCE_MINMAX(INTRIN, INF, INF64)           \

定义宏 NPY_IMPL_AVX512_REDUCE_MINMAX,带有三个参数:INTRIN、INF、INF64。


NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a)       \

定义内联函数 npyv_reduce_##INTRIN##p_f32,接受一个参数 npyv_f32 类型的 a,返回 float 类型的值。


{

函数体开始。


npyv_b32 notnan = npyv_notnan_f32(a);                       

声明并初始化变量 notnan,用于存储对 a 应用 npyv_notnan_f32 函数的结果。


if (NPY_UNLIKELY(!npyv_any_b32(notnan))) {                  

如果 notnan 中不存在任何 true 值(即没有非 NaN 的元素),执行以下代码块。


return _mm_cvtss_f32(_mm512_castps512_ps128(a));        

将 a 强制转换为 128 位宽度的单精度浮点数,并返回其值。


}

条件语句结束。


a = npyv_select_f32(notnan, a,                              
        npyv_reinterpret_f32_u32(npyv_setall_u32(INF)));    

通过 npyv_select_f32 函数,根据 notnan 的条件选择将 a 中的元素保留或替换为 INF 的值。


return npyv_reduce_##INTRIN##_f32(a);                       

调用 npyv_reduce_##INTRIN##_f32 函数,返回处理后的 a 的值。


}

函数体结束。

依此类推,对于每一个函数,需要按照类似的方式注释解释每一行代码的作用,确保完整理解每个函数的实现和功能。
// 定义 AVX512 指令的宏,用于实现最小值和最大值的归约操作
#define NPY_IMPL_AVX512_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN)                                               \
    // 定义内联函数,对 __m512i 类型的数据进行最小值或最大值的归约操作,返回 STYPE##16 类型的结果
    NPY_FINLINE STYPE##16 npyv_reduce_##INTRIN##16(__m512i a)                                               \
    {                                                                                                       \
        // 将 __m512i 类型数据的低 256 位和高 256 位分别提取为 __m256i 类型
        __m256i v256 = _mm256_##VINTRIN##16(npyv512_lower_si256(a), npyv512_higher_si256(a));               \
        // 从 __m256i 中提取低 128 位和高 128 位,执行相同的指令操作
        __m128i v128 = _mm_##VINTRIN##16(_mm256_castsi256_si128(v256), _mm256_extracti128_si256(v256, 1));  \
        // 将低 128 位的数据向高位扩展
        __m128i v64 =  _mm_##VINTRIN##16(v128, _mm_shuffle_epi32(v128,                                      \
                   (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));                                                \
        // 继续向高位扩展为 32 位
        __m128i v32 = _mm_##VINTRIN##16(v64, _mm_shuffle_epi32(v64,                                         \
                   (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));                                                \
        // 再次向高位扩展为 16 位
        __m128i v16 = _mm_##VINTRIN##16(v32, _mm_shufflelo_epi16(v32,                                       \
                   (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));                                                \
        // 将 16 位转换为 32 位,并返回最终结果
        return (STYPE##16)_mm_cvtsi128_si32(v16);                                                           \
    }                                                                                                       \
    // 定义内联函数,对 __m512i 类型的数据进行最小值或最大值的归约操作,返回 STYPE##8 类型的结果
    NPY_FINLINE STYPE##8 npyv_reduce_##INTRIN##8(__m512i a)                                                 \
    {                                                                                                       \
        // 将 __m512i 类型数据的低 256 位和高 256 位分别提取为 __m256i 类型
        __m256i v256 = _mm256_##VINTRIN##8(npyv512_lower_si256(a), npyv512_higher_si256(a));                \
        // 从 __m256i 中提取低 128 位和高 128 位,执行相同的指令操作
        __m128i v128 = _mm_##VINTRIN##8(_mm256_castsi256_si128(v256), _mm256_extracti128_si256(v256, 1));   \
        // 将低 128 位的数据向高位扩展
        __m128i v64 =  _mm_##VINTRIN##8(v128, _mm_shuffle_epi32(v128,                                       \
                    (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2)));                                               \
        // 继续向高位扩展为 32 位
        __m128i v32 = _mm_##VINTRIN##8(v64, _mm_shuffle_epi32(v64,                                          \
                    (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));                                               \
        // 再次向高位扩展为 16 位
        __m128i v16 = _mm_##VINTRIN##8(v32, _mm_shufflelo_epi16(v32,                                        \
                    (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1)));                                               \
        // 将 16 位向高位扩展为 8 位,并返回最终结果
        __m128i v8 = _mm_##VINTRIN##8(v16, _mm_srli_epi16(v16, 8));                                         \
        return (STYPE##16)_mm_cvtsi128_si32(v8);                                                            \
    }
// 定义 AVX512 指令集下的最小最大值归约操作,针对无符号整数,使用最小值操作宏
NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, min_u, min_epu)
// 定义 AVX512 指令集下的最小最大值归约操作,针对有符号整数,使用最小值操作宏
NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int,  min_s, min_epi)
// 定义 AVX512 指令集下的最小最大值归约操作,针对无符号整数,使用最大值操作宏
NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, max_u, max_epu)
// 定义 AVX512 指令集下的最小最大值归约操作,针对有符号整数,使用最大值操作宏
NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int,  max_s, max_epi)
// 取消前面定义的 AVX512 最小最大值归约操作宏
#undef NPY_IMPL_AVX512_REDUCE_MINMAX

// 定义向最近偶数整数舍入的 AVX512 单精度浮点数运算宏
#define npyv_rint_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_NEAREST_INT)
// 定义向最近偶数整数舍入的 AVX512 双精度浮点数运算宏
#define npyv_rint_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_NEAREST_INT)

// 定义向正无穷大舍入的 AVX512 单精度浮点数运算宏
#define npyv_ceil_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_POS_INF)
// 定义向正无穷大舍入的 AVX512 双精度浮点数运算宏
#define npyv_ceil_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_POS_INF)

// 定义向零舍入的 AVX512 单精度浮点数运算宏
#define npyv_trunc_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_ZERO)
// 定义向零舍入的 AVX512 双精度浮点数运算宏
#define npyv_trunc_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_ZERO)

// 定义向负无穷大舍入的 AVX512 单精度浮点数运算宏
#define npyv_floor_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_NEG_INF)
// 定义向负无穷大舍入的 AVX512 双精度浮点数运算宏
#define npyv_floor_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_NEG_INF)

// 结束 _NPY_SIMD_AVX512_MATH_H 文件的条件编译
#endif // _NPY_SIMD_AVX512_MATH_H

.\numpy\numpy\_core\src\common\simd\avx512\memory.h

#ifndef NPY_SIMD
    // 如果没有定义 NPY_SIMD 宏,则输出错误信息 "Not a standalone header"
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_MEMORY_H
#define _NPY_SIMD_AVX512_MEMORY_H

#include "misc.h"

/***************************
 * load/store
 ***************************/

#if defined(__GNUC__)
    // 如果使用 GCC 编译器,因为 GCC 期望指针参数类型为 `void*` 而不是 `const void*`,会引发大量警告,
    // 所以使用 `_mm512_stream_load_si512` 进行加载操作
    #define npyv__loads(PTR) _mm512_stream_load_si512((__m512i*)(PTR))
#else
    // 对于其他编译器,正常使用 `_mm512_stream_load_si512` 加载操作
    #define npyv__loads(PTR) _mm512_stream_load_si512((const __m512i*)(PTR))
#endif

#if defined(_MSC_VER) && defined(_M_IX86)
    // 解决 MSVC(32位) 的溢出 bug,详见 https://developercommunity.visualstudio.com/content/problem/911872/u.html
    NPY_FINLINE __m512i npyv__loadl(const __m256i *ptr)
    {
        // 使用 `_mm256_loadu_si256` 加载 `ptr` 所指向的内存,并将结果插入到 `_mm512_castsi256_si512` 的结果中返回
        __m256i a = _mm256_loadu_si256(ptr);
        return _mm512_inserti64x4(_mm512_castsi256_si512(a), a, 0);
    }
#else
    // 对于其他情况,使用 `_mm256_loadu_si256` 加载 `PTR` 所指向的内存,然后使用 `_mm512_castsi256_si512` 转换返回结果
    #define npyv__loadl(PTR) \
        _mm512_castsi256_si512(_mm256_loadu_si256(PTR))
#endif

// 定义 AVX-512 内存操作的宏实现,包括不同类型的加载和存储操作
#define NPYV_IMPL_AVX512_MEM_INT(CTYPE, SFX)                                 \
    NPY_FINLINE npyv_##SFX npyv_load_##SFX(const CTYPE *ptr)                 \
    { return _mm512_loadu_si512((const __m512i*)ptr); }                      \
    NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const CTYPE *ptr)                \
    { return _mm512_load_si512((const __m512i*)ptr); }                       \
    NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const CTYPE *ptr)                \
    { return npyv__loads(ptr); }                                             \
    NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const CTYPE *ptr)                \
    { return npyv__loadl((const __m256i *)ptr); }                            \
    NPY_FINLINE void npyv_store_##SFX(CTYPE *ptr, npyv_##SFX vec)            \
    { _mm512_storeu_si512((__m512i*)ptr, vec); }                             \
    NPY_FINLINE void npyv_storea_##SFX(CTYPE *ptr, npyv_##SFX vec)           \
    { _mm512_store_si512((__m512i*)ptr, vec); }                              \
    NPY_FINLINE void npyv_stores_##SFX(CTYPE *ptr, npyv_##SFX vec)           \
    { _mm512_stream_si512((__m512i*)ptr, vec); }                             \
    NPY_FINLINE void npyv_storel_##SFX(CTYPE *ptr, npyv_##SFX vec)           \
    { _mm256_storeu_si256((__m256i*)ptr, npyv512_lower_si256(vec)); }        \
    NPY_FINLINE void npyv_storeh_##SFX(CTYPE *ptr, npyv_##SFX vec)           \
    { _mm256_storeu_si256((__m256i*)(ptr), npyv512_higher_si256(vec)); }

// 定义不同整数类型的 AVX-512 内存操作实现
NPYV_IMPL_AVX512_MEM_INT(npy_uint8,  u8)
NPYV_IMPL_AVX512_MEM_INT(npy_int8,   s8)
NPYV_IMPL_AVX512_MEM_INT(npy_uint16, u16)
NPYV_IMPL_AVX512_MEM_INT(npy_int16,  s16)
NPYV_IMPL_AVX512_MEM_INT(npy_uint32, u32)
NPYV_IMPL_AVX512_MEM_INT(npy_int32,  s32)
NPYV_IMPL_AVX512_MEM_INT(npy_uint64, u64)
NPYV_IMPL_AVX512_MEM_INT(npy_int64,  s64)

// 不对齐加载操作宏定义
#define npyv_load_f32(PTR) _mm512_loadu_ps((const __m512*)(PTR))
#define npyv_load_f64(PTR) _mm512_loadu_pd((const __m512d*)(PTR))
// 对齐加载操作

#endif // _NPY_SIMD_AVX512_MEMORY_H
// 定义宏:以 32 位浮点数精度加载数据到 AVX-512 向量,使用非对齐方式
#define npyv_loada_f32(PTR) _mm512_load_ps((const __m512*)(PTR))
// 定义宏:以 64 位浮点数精度加载数据到 AVX-512 向量,使用非对齐方式
#define npyv_loada_f64(PTR) _mm512_load_pd((const __m512d*)(PTR))

// 宏条件编译:加载低位部分的数据,根据编译器和架构的不同使用不同的实现
#if defined(_MSC_VER) && defined(_M_IX86)
    #define npyv_loadl_f32(PTR) _mm512_castsi512_ps(npyv__loadl((const __m256i *)(PTR)))
    #define npyv_loadl_f64(PTR) _mm512_castsi512_pd(npyv__loadl((const __m256i *)(PTR)))
#else
    #define npyv_loadl_f32(PTR) _mm512_castps256_ps512(_mm256_loadu_ps(PTR))
    #define npyv_loadl_f64(PTR) _mm512_castpd256_pd512(_mm256_loadu_pd(PTR))
#endif

// 定义宏:使用流加载方式加载数据到 AVX-512 向量,适合连续加载操作
#define npyv_loads_f32(PTR) _mm512_castsi512_ps(npyv__loads(PTR))
#define npyv_loads_f64(PTR) _mm512_castsi512_pd(npyv__loads(PTR))

// 定义宏:以非对齐方式将 AVX-512 向量中的数据存储到内存
#define npyv_store_f32 _mm512_storeu_ps
#define npyv_store_f64 _mm512_storeu_pd

// 定义宏:以对齐方式将 AVX-512 向量中的数据存储到内存
#define npyv_storea_f32 _mm512_store_ps
#define npyv_storea_f64 _mm512_store_pd

// 定义宏:使用流存储方式将 AVX-512 向量中的数据存储到内存
#define npyv_stores_f32 _mm512_stream_ps
#define npyv_stores_f64 _mm512_stream_pd

// 定义宏:存储 AVX-512 向量的低位部分到内存
#define npyv_storel_f32(PTR, VEC) _mm256_storeu_ps(PTR, npyv512_lower_ps256(VEC))
#define npyv_storel_f64(PTR, VEC) _mm256_storeu_pd(PTR, npyv512_lower_pd256(VEC))

// 定义宏:存储 AVX-512 向量的高位部分到内存
#define npyv_storeh_f32(PTR, VEC) _mm256_storeu_ps(PTR, npyv512_higher_ps256(VEC))
#define npyv_storeh_f64(PTR, VEC) _mm256_storeu_pd(PTR, npyv512_higher_pd256(VEC))

/***************************
 * 非连续加载操作
 ***************************/

//// 32 位整数加载
// 加载非连续的 32 位无符号整数到 AVX-512 向量
NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride)
{
    // 断言:步长的绝对值不超过 NPY_SIMD_MAXLOAD_STRIDE32
    assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32);
    // 设置步长向量
    const __m512i steps = npyv_set_s32(
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    );
    // 计算索引
    const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride));
    // 使用步长向量从内存中加载数据到 AVX-512 向量
    return _mm512_i32gather_epi32(idx, (const __m512i*)ptr, 4);
}

// 加载非连续的 32 位有符号整数到 AVX-512 向量
NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride)
{ return npyv_loadn_u32((const npy_uint32*)ptr, stride); }

// 加载非连续的 32 位浮点数到 AVX-512 向量
NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride)
{ return _mm512_castsi512_ps(npyv_loadn_u32((const npy_uint32*)ptr, stride)); }

//// 64 位整数加载
// 加载非连续的 64 位无符号整数到 AVX-512 向量
NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride)
{
    // 设置索引向量
    const __m512i idx = npyv_set_s64(
        0*stride, 1*stride, 2*stride, 3*stride,
        4*stride, 5*stride, 6*stride, 7*stride
    );
    // 使用索引向量从内存中加载数据到 AVX-512 向量
    return _mm512_i64gather_epi64(idx, (const __m512i*)ptr, 8);
}

// 加载非连续的 64 位有符号整数到 AVX-512 向量
NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride)
{ return npyv_loadn_u64((const npy_uint64*)ptr, stride); }

// 加载非连续的 64 位双精度浮点数到 AVX-512 向量
NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride)
{ return _mm512_castsi512_pd(npyv_loadn_u64((const npy_uint64*)ptr, stride)); }

//// 64 位整数加载(通过 32 位步长)
// 加载非连续的 32 位无符号整数到 AVX-512 向量的高位
NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride)
{
    // 使用 AVX 指令集加载第二部分数据到 AVX-512 向量的低位
    __m128d a = _mm_loadh_pd(
        _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)ptr)),
        (const double*)(ptr + stride)
    );
    //
    # 加载两个 double 值到寄存器 __m128d 中,其中高位值来自 ptr + stride*2 处的数据,低位值来自 ptr + stride*3 处的数据
    __m128d b = _mm_loadh_pd(
        _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*2))),
        (const double*)(ptr + stride*3)
    );
    
    # 加载两个 double 值到寄存器 __m128d 中,其中高位值来自 ptr + stride*4 处的数据,低位值来自 ptr + stride*5 处的数据
    __m128d c = _mm_loadh_pd(
        _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*4))),
        (const double*)(ptr + stride*5)
    );
    
    # 加载两个 double 值到寄存器 __m128d 中,其中高位值来自 ptr + stride*6 处的数据,低位值来自 ptr + stride*7 处的数据
    __m128d d = _mm_loadh_pd(
        _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*6))),
        (const double*)(ptr + stride*7)
    );
    
    # 组合四个 __m128d 寄存器成一个 __m512i 寄存器,通过调用 npyv512_combine_pd256 函数并转换为 __m512i 类型返回
    return _mm512_castpd_si512(npyv512_combine_pd256(
        # 将两个 __m128d 寄存器 a 和 b 合并为一个 __m256d 寄存器,并在高位插入 b 寄存器的值
        _mm256_insertf128_pd(_mm256_castpd128_pd256(a), b, 1),
        # 将两个 __m128d 寄存器 c 和 d 合并为一个 __m256d 寄存器,并在高位插入 d 寄存器的值
        _mm256_insertf128_pd(_mm256_castpd128_pd256(c), d, 1)
    ));
//// 64-bit store over 32-bit stride
NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a)
{
    // 将输入的512位整数向量转换为两个256位双精度浮点向量
    __m256d lo = _mm512_castpd512_pd256(_mm512_castsi512_pd(a));
    // 提取512位整数向量的高128位并转换为256位双精度浮点向量
    __m256d hi = _mm512_extractf64x4_pd(_mm512_castsi512_pd(a), 1);
    // 从lo中提取低128位双精度浮点数并存储到ptr的0号元素位置
    __m128d e0 = _mm256_castpd256_pd128(lo);
    // 从lo中提取高128位双精度浮点数并存储到ptr的1号元素位置
    __m128d e1 = _mm256_extractf128_pd(lo, 1);
    // 从hi中提取低128位双精度浮点数并存储到ptr的2号元素位置
    __m128d e2 = _mm256_castpd256_pd128(hi);
    // 从hi中提取高128位双精度浮点数并存储到ptr的3号元素位置
    __m128d e3 = _mm256_extractf128_pd(hi, 1);
    // 使用单精度浮点数存储ptr的0号位置
    _mm_storel_pd((double*)(ptr + stride * 0), e0);
    // 使用单精度浮点数存储ptr的1号位置
    _mm_storeh_pd((double*)(ptr + stride * 1), e0);
    // 使用单精度浮点数存储ptr的2号位置
    _mm_storel_pd((double*)(ptr + stride * 2), e1);
}
    // 使用 SSE2 指令集中的 _mm_storeh_pd 函数,将双精度浮点数 e1 的高64位存储到 ptr + stride * 3 处
    _mm_storeh_pd((double*)(ptr + stride * 3), e1);
    // 使用 SSE2 指令集中的 _mm_storel_pd 函数,将双精度浮点数 e2 的低64位存储到 ptr + stride * 4 处
    _mm_storel_pd((double*)(ptr + stride * 4), e2);
    // 使用 SSE2 指令集中的 _mm_storeh_pd 函数,将双精度浮点数 e2 的高64位存储到 ptr + stride * 5 处
    _mm_storeh_pd((double*)(ptr + stride * 5), e2);
    // 使用 SSE2 指令集中的 _mm_storel_pd 函数,将双精度浮点数 e3 的低64位存储到 ptr + stride * 6 处
    _mm_storel_pd((double*)(ptr + stride * 6), e3);
    // 使用 SSE2 指令集中的 _mm_storeh_pd 函数,将双精度浮点数 e3 的高64位存储到 ptr + stride * 7 处
    _mm_storeh_pd((double*)(ptr + stride * 7), e3);
//// 128-bit store over 64-bit stride
NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a)
{
    // 将512位无符号整数向量a分成低256位和高256位
    __m256i lo = npyv512_lower_si256(a);
    __m256i hi = npyv512_higher_si256(a);

    // 从lo中提取128位元素e0和e1,从hi中提取128位元素e2和e3
    __m128i e0 = _mm256_castsi256_si128(lo);
    __m128i e1 = _mm256_extracti128_si256(lo, 1);
    __m128i e2 = _mm256_castsi256_si128(hi);
    __m128i e3 = _mm256_extracti128_si256(hi, 1);

    // 将128位元素e0、e1、e2、e3分别存储到ptr的不同偏移位置
    _mm_storeu_si128((__m128i*)(ptr + stride * 0), e0);
    _mm_storeu_si128((__m128i*)(ptr + stride * 1), e1);
    _mm_storeu_si128((__m128i*)(ptr + stride * 2), e2);
    _mm_storeu_si128((__m128i*)(ptr + stride * 3), e3);
}

/*********************************
 * Partial Load
 *********************************/
//// 32
NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill)
{
    // 断言nlane大于0,即加载的元素数量大于0
    assert(nlane > 0);

    // 设置填充值为vfill
    const __m512i vfill = _mm512_set1_epi32(fill);

    // 计算掩码,mask为-1或者(1 << nlane) - 1,取决于nlane是否大于15
    const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1;

    // 使用掩码加载元素到ret中,ptr强制转换为__m512i类型
    __m512i ret = _mm512_mask_loadu_epi32(vfill, mask, (const __m512i*)ptr);

    // 如果定义了NPY_SIMD_GUARD_PARTIAL_LOAD,执行下面的工作区绕过
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif

    return ret;
}

// fill zero to rest lanes
//// 32
NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane)
{
    // 断言nlane大于0,即加载的元素数量大于0
    assert(nlane > 0);

    // 计算掩码,mask为-1或者(1 << nlane) - 1,取决于nlane是否大于15
    const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1;

    // 使用掩码加载元素到ret中,ptr强制转换为__m512i类型,加载时填充零
    __m512i ret = _mm512_maskz_loadu_epi32(mask, (const __m512i*)ptr);

    // 如果定义了NPY_SIMD_GUARD_PARTIAL_LOAD,执行下面的工作区绕过
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif

    return ret;
}

//// 64
NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill)
{
    // 断言nlane大于0,即加载的元素数量大于0
    assert(nlane > 0);

    // 设置填充值为vfill
    const __m512i vfill = npyv_setall_s64(fill);

    // 计算掩码,mask为-1或者(1 << nlane) - 1,取决于nlane是否大于7
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;

    // 使用掩码加载元素到ret中,ptr强制转换为__m512i类型
    __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr);

    // 如果定义了NPY_SIMD_GUARD_PARTIAL_LOAD,执行下面的工作区绕过
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif

    return ret;
}

// fill zero to rest lanes
//// 64
NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane)
{
    // 断言nlane大于0,即加载的元素数量大于0
    assert(nlane > 0);

    // 计算掩码,mask为-1或者(1 << nlane) - 1,取决于nlane是否大于7
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;

    // 使用掩码加载元素到ret中,ptr强制转换为__m512i类型,加载时填充零
    __m512i ret = _mm512_maskz_loadu_epi64(mask, (const __m512i*)ptr);

    // 如果定义了NPY_SIMD_GUARD_PARTIAL_LOAD,执行下面的工作区绕过
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif

    return ret;
}
//// 64-bit nlane
// 定义一个函数,加载指定数量的 32 位有符号整数到 SIMD 向量中,同时使用指定的值填充未加载的部分
NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane,
                                          npy_int32 fill_lo, npy_int32 fill_hi)
{
    // 断言确保加载的 lane 数大于 0
    assert(nlane > 0);
    // 创建一个包含填充值的 512 位整数向量,顺序为 fill_hi, fill_lo, fill_hi, fill_lo
    const __m512i vfill = _mm512_set4_epi32(fill_hi, fill_lo, fill_hi, fill_lo);
    // 根据 nlane 的大小设置掩码,如果 nlane 大于 7,则掩码为全 1,否则为低 nlane 位为 1
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;
    // 使用掩码从指针处加载 64 位整数数据到 512 位整数向量 ret 中
    __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD,执行偏移量加载后的补救措施
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载后的向量 ret
    return ret;
}
// 使用零值填充未加载的 lane
NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane)
{ return npyv_load_tillz_s64((const npy_int64*)ptr, nlane); }

//// 128-bit nlane
// 定义一个函数,加载指定数量的 64 位有符号整数到 SIMD 向量中,同时使用指定的值填充未加载的部分
NPY_FINLINE npyv_u64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane,
                                           npy_int64 fill_lo, npy_int64 fill_hi)
{
    // 断言确保加载的 lane 数大于 0
    assert(nlane > 0);
    // 创建一个包含填充值的 512 位整数向量,顺序为 fill_hi, fill_lo, fill_hi, fill_lo
    const __m512i vfill = _mm512_set4_epi64(fill_hi, fill_lo, fill_hi, fill_lo);
    // 根据 nlane 的大小设置掩码,如果 nlane 大于 3,则掩码为全 1,否则为低 nlane*2 位为 1
    const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1;
    // 使用掩码从指针处加载 64 位整数数据到 512 位整数向量 ret 中
    __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD,执行偏移量加载后的补救措施
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载后的向量 ret
    return ret;
}
// 使用零值填充未加载的 lane
NPY_FINLINE npyv_s64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane)
{
    // 断言确保加载的 lane 数大于 0
    assert(nlane > 0);
    // 根据 nlane 的大小设置掩码,如果 nlane 大于 3,则掩码为全 1,否则为低 nlane*2 位为 1
    const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1;
    // 使用掩码从指针处加载零填充的 64 位整数数据到 512 位整数向量 ret 中
    __m512i ret = _mm512_maskz_loadu_epi64(mask, (const __m512i*)ptr);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD,执行偏移量加载后的补救措施
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载后的向量 ret
    return ret;
}
/*********************************
 * Non-contiguous partial load
 *********************************/
//// 32
// 定义一个函数,以非连续的方式加载指定数量的 32 位有符号整数到 SIMD 向量中,同时使用指定的值填充未加载的部分
NPY_FINLINE npyv_s32
npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill)
{
    // 断言确保加载的 lane 数大于 0
    assert(nlane > 0);
    // 断言确保步长的绝对值不超过 NPY_SIMD_MAXLOAD_STRIDE32
    assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32);
    // 创建一个顺序为 015512 位整数向量 steps
    const __m512i steps = npyv_set_s32(
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    );
    // 使用步长和给定的步长值计算索引
    const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride));
    // 创建一个包含填充值的 512 位整数向量 vfill
    const __m512i vfill = _mm512_set1_epi32(fill);
    // 根据 nlane 的大小设置掩码,如果 nlane 大于 15,则掩码为全 1,否则为低 nlane 位为 1
    const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1;
    // 使用掩码从 ptr 指针处按照 4 字节步长加载 32 位整数数据到 512 位整数向量 ret 中
    __m512i ret = _mm512_mask_i32gather_epi32(vfill, mask, idx, (const __m512i*)ptr, 4);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD,执行偏移量加载后的补救措施
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载后的向量 ret
    return ret;
}
// 使用零值填充未加载的 lane
NPY_FINLINE npyv_s32
npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane)
{ return npyv_loadn_till_s32(ptr, stride, nlane, 0); }

//// 64
// 定义一个函数,以非连续的方式加载指定数量的 64 位有符号整数到 SIMD 向量中,同时使用指定的值填充未加载的部分
NPY_FINLINE npyv_s64
npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill)
{
    // 断言确保加载的 lane 数大于 0
    assert(nlane > 0);
    // 断言确保步长的绝对值不超过 NPY_SIMD_MAXLOAD_STRIDE64
    assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE64);
    //cpp
    // 创建一个包含给定索引值的 __m512i 向量,这些索引是以步长 stride 递增的
    const __m512i idx = npyv_set_s64(
        0*stride, 1*stride, 2*stride, 3*stride,
        4*stride, 5*stride, 6*stride, 7*stride
    );
    
    // 创建一个所有元素均为 fill 的 __m512i 向量
    const __m512i vfill = npyv_setall_s64(fill);
    
    // 根据 nlane 的值创建一个掩码,如果 nlane 大于 15,则掩码设置为全1;否则设置为 (1 << nlane) - 1
    const __mmask8 mask = nlane > 15 ? -1 : (1 << nlane) - 1;
    
    // 使用 _mm512_mask_i64gather_epi64 函数从 ptr 指向的内存中根据 idx 向量的索引收集数据到 ret 向量中,每次收集 8 个元素
    __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 8);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD 宏,则使用 workaround 来处理 ret
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回 ret 变量的值
    return ret;
}
// 使用零值填充其余的通道

//// 64-bit load over 32-bit stride
// 以 64 位加载数据,步长为 32 位
NPY_FINLINE npyv_s64 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane,
                                                 npy_int32 fill_lo, npy_int32 fill_hi)
{
    assert(nlane > 0);
    // 创建包含索引的 __m512i 对象,每个索引乘以步长用于加载数据
    const __m512i idx = npyv_set_s64(
        0*stride, 1*stride, 2*stride, 3*stride,
        4*stride, 5*stride, 6*stride, 7*stride
    );
    // 创建包含填充值的 __m512i 对象
    const __m512i vfill = _mm512_set4_epi32(fill_hi, fill_lo, fill_hi, fill_lo);
    // 根据 nlane 的大小设置掩码,以便决定加载多少数据
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;
    // 使用 gather 操作加载数据到 ret 变量中
    __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 4);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD 宏,则使用 workaround 处理 ret
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载的结果
    return ret;
}
// 使用零值填充其余的通道

//// 128-bit load over 64-bit stride
// 以 128 位加载数据,步长为 64 位
NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane,
                                                  npy_int64 fill_lo, npy_int64 fill_hi)
{
    assert(nlane > 0);
    // 创建包含索引的 __m512i 对象,每个索引乘以步长用于加载数据
    const __m512i idx = npyv_set_s64(
       0,        1,          stride,   stride+1,
       stride*2, stride*2+1, stride*3, stride*3+1
    );
    // 根据 nlane 的大小设置掩码,以便决定加载多少数据
    const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1;
    // 创建包含填充值的 __m512i 对象
    const __m512i vfill = _mm512_set4_epi64(fill_hi, fill_lo, fill_hi, fill_lo);
    // 使用 gather 操作加载数据到 ret 变量中
    __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 8);
#if NPY_SIMD_GUARD_PARTIAL_LOAD
    // 如果定义了 NPY_SIMD_GUARD_PARTIAL_LOAD 宏,则使用 workaround 处理 ret
    volatile __m512i workaround = ret;
    ret = _mm512_or_si512(workaround, ret);
#endif
    // 返回加载的结果
    return ret;
}
// 使用零值填充其余的通道

/*********************************
 * Partial store
 *********************************/
//// 32
// 存储至少 32 位数据
NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a)
{
    assert(nlane > 0);
    // 根据 nlane 的大小设置掩码,以便决定存储多少数据
    const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1;
    // 使用掩码进行存储操作
    _mm512_mask_storeu_epi32((__m512i*)ptr, mask, a);
}
//// 64
// 存储至少 64 位数据
NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a)
{
    assert(nlane > 0);
    // 根据 nlane 的大小设置掩码,以便决定存储多少数据
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;
    // 使用掩码进行存储操作
    _mm512_mask_storeu_epi64((__m512i*)ptr, mask, a);
}

//// 64-bit nlane
// 存储至少 64 位数据
NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a)
{
    assert(nlane > 0);
    // 根据 nlane 的大小设置掩码,以便决定存储多少数据
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;
    # 使用512位无符号整数向内存位置ptr按mask掩码存储a的值
    _mm512_mask_storeu_epi64((__m512i*)ptr, mask, a);
/*********************************
 * Non-contiguous partial store
 *********************************/
//// 32
NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a)
{
    // 确保要存储的元素数量大于0
    assert(nlane > 0);
    // 确保步长的绝对值不超过最大存储步长限制
    assert(llabs(stride) <= NPY_SIMD_MAXSTORE_STRIDE32);

    // 创建一个步长数组
    const __m512i steps = _mm512_setr_epi32(
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    );

    // 计算实际存储时的索引,使用给定的步长
    const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride));

    // 根据要存储的元素数量,创建一个掩码
    const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1;

    // 使用掩码进行非连续的整数存储
    _mm512_mask_i32scatter_epi32((__m512i*)ptr, mask, idx, a, 4);
}

//// 64
NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a)
{
    // 确保要存储的元素数量大于0
    assert(nlane > 0);

    // 创建一个步长数组
    const __m512i idx = npyv_set_s64(
        0*stride, 1*stride, 2*stride, 3*stride,
        4*stride, 5*stride, 6*stride, 7*stride
    );

    // 根据要存储的元素数量,创建一个掩码
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;

    // 使用掩码进行非连续的64位整数存储
    _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 8);
}

//// 64-bit store over 32-bit stride
NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a)
{
    // 确保要存储的元素数量大于0
    assert(nlane > 0);

    // 创建一个步长数组
    const __m512i idx = npyv_set_s64(
        0*stride, 1*stride, 2*stride, 3*stride,
        4*stride, 5*stride, 6*stride, 7*stride
    );

    // 根据要存储的元素数量,创建一个掩码
    const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1;

    // 使用掩码进行64位整数存储,但每个元素占4字节步长
    _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 4);
}

//// 128-bit store over 64-bit stride
NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a)
{
    // 确保要存储的元素数量大于0
    assert(nlane > 0);

    // 创建一个步长数组
    const __m512i idx = npyv_set_s64(
        0,        1,            stride,   stride+1,
        2*stride, 2*stride+1, 3*stride, 3*stride+1
    );

    // 根据要存储的元素数量,创建一个掩码
    const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1;

    // 使用掩码进行64位整数存储,每个元素占8字节步长
    _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 8);
}
    {                                                                                       \
        union {                                                                             \
            npyv_lanetype_##F_SFX from_##F_SFX;                                             \  // 声明一个联合体 pun,其中包含类型为 npyv_lanetype_##F_SFX 的 from_##F_SFX 成员
            npyv_lanetype_##T_SFX to_##T_SFX;                                               \  // 联合体中还包含类型为 npyv_lanetype_##T_SFX 的 to_##T_SFX 成员
        } pun;                                                                              \  // 声明 pun 作为联合体变量
        pun.from_##F_SFX = fill;                                                            \  // 将 fill 赋值给联合体 pun 中的 from_##F_SFX 成员
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX(                   \
            (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX                       \  // 调用 npyv_load_till_##T_SFX 函数,传递指针 ptr、nlane 和联合体 pun 中的 to_##T_SFX 成员
        ));                                                                                 \  // 返回 npyv_reinterpret_##F_SFX##_##T_SFX 的结果
    }                                                                                       \  // 结束函数定义
    NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX                                        \  // 定义一个内联函数 npyv_loadn_till_##F_SFX,返回类型为 npyv_##F_SFX
    (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane,                    \  // 函数参数:指向 npyv_lanetype_##F_SFX 类型的指针 ptr,步长 stride,数量 nlane,以及填充值 fill
     npyv_lanetype_##F_SFX fill)                                                            \  // 填充值 fill 的类型为 npyv_lanetype_##F_SFX
    {                                                                                       \
        union {                                                                             \
            npyv_lanetype_##F_SFX from_##F_SFX;                                             \  // 声明一个联合体 pun,包含类型为 npyv_lanetype_##F_SFX 的 from_##F_SFX 成员
            npyv_lanetype_##T_SFX to_##T_SFX;                                               \  // 联合体中还包含类型为 npyv_lanetype_##T_SFX 的 to_##T_SFX 成员
        } pun;                                                                              \  // 声明 pun 作为联合体变量
        pun.from_##F_SFX = fill;                                                            \  // 将 fill 赋值给联合体 pun 中的 from_##F_SFX 成员
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX(                  \
            (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX               \  // 调用 npyv_loadn_till_##T_SFX 函数,传递指针 ptr、stride、nlane 和联合体 pun 中的 to_##T_SFX 成员
        ));                                                                                 \  // 返回 npyv_reinterpret_##F_SFX##_##T_SFX 的结果
    }                                                                                       \  // 结束函数定义
    NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX                                        \  // 定义一个内联函数 npyv_load_tillz_##F_SFX,返回类型为 npyv_##F_SFX
    (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane)                                     \  // 函数参数:指向 npyv_lanetype_##F_SFX 类型的指针 ptr,数量 nlane
    {                                                                                       \
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX(                  \
            (const npyv_lanetype_##T_SFX *)ptr, nlane                                       \  // 调用 npyv_load_tillz_##T_SFX 函数,传递指针 ptr 和 nlane
        ));                                                                                 \  // 返回 npyv_reinterpret_##F_SFX##_##T_SFX 的结果
    }                                                                                       \  // 结束函数定义
    NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX                                       \
    # 定义一个宏,用于将类型为 F_SFX 的向量数据指针重新解释为类型为 T_SFX 的向量数据,并加载直到遇到零
    (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane)
    {
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX(
            (const npyv_lanetype_##T_SFX *)ptr, stride, nlane
        ));
    }
    
    # 定义一个内联函数,用于将类型为 F_SFX 的向量数据 a 存储到类型为 F_SFX 的指针数组 ptr 的前 nlane 个位置
    NPY_FINLINE void npyv_store_till_##F_SFX
    (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a)
    {
        # 将类型为 F_SFX 的向量数据 a 重新解释为类型为 T_SFX 的向量数据,并存储到 ptr 数组中前 nlane 个位置
        npyv_store_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
    
    # 定义一个内联函数,用于将类型为 F_SFX 的向量数据 a 存储到类型为 F_SFX 的指针数组 ptr 中,带有步长 stride,并存储到前 nlane 个位置
    NPY_FINLINE void npyv_storen_till_##F_SFX
    (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a)
    {
        # 将类型为 F_SFX 的向量数据 a 重新解释为类型为 T_SFX 的向量数据,并存储到 ptr 数组中,带有步长 stride,并存储到前 nlane 个位置
        npyv_storen_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, stride, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
// 定义AVX-512加速部分类型的宏,用于u32和s32类型
NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(u32, s32)
// 定义AVX-512加速部分类型的宏,用于f32和s32类型
NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(f32, s32)
// 定义AVX-512加速部分类型的宏,用于u64和s64类型
NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(u64, s64)
// 定义AVX-512加速部分类型的宏,用于f64和s64类型

// 128位/64位步长(双元素加载/存储)的宏定义
#define NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX)                              \
    // 内部联合结构用于类型转换
    NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX                                        \
    (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane,                                     \
     npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi)                          \
    {                                                                                       \
        // 联合结构定义
        union pun {                                                                         \
            npyv_lanetype_##F_SFX from_##F_SFX;                                             \
            npyv_lanetype_##T_SFX to_##T_SFX;                                               \
        };                                                                                  \
        // 低位和高位数据的联合结构变量
        union pun pun_lo;                                                                   \
        union pun pun_hi;                                                                   \
        // 将填充的低位和高位数据存入联合结构中
        pun_lo.from_##F_SFX = fill_lo;                                                      \
        pun_hi.from_##F_SFX = fill_hi;                                                      \
        // 调用加载函数,将转换后的数据作为参数传递
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX(                  \
            (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \
        ));                                                                                 \
    }                                                                                       \
    // 内部联合结构用于类型转换
    NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX                                       \
    (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane,                    \
     npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi)                          \
    {                                                                                       \
        union pun {                                                                         \
            npyv_lanetype_##F_SFX from_##F_SFX;                                             \
            npyv_lanetype_##T_SFX to_##T_SFX;                                               \
        };                                                                                  \
        union pun pun_lo;                                                                   \
        union pun pun_hi;                                                                   \
        pun_lo.from_##F_SFX = fill_lo;                                                      \
        pun_hi.from_##F_SFX = fill_hi;                                                      \
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX(                 \
            (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX,           \
            pun_hi.to_##T_SFX                                                               \
        ));                                                                                 \
    }                                                                                       \

    // 定义一个内联函数 npyv_load2_tillz_##F_SFX,加载并转换数据为目标类型,填充未使用的部分为零
    NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX                                       \
    (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane)                                     \
    {                                                                                       \
        // 调用相应的加载函数,将输入指针的数据加载并转换为目标类型
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX(                 \
            (const npyv_lanetype_##T_SFX *)ptr, nlane                                       \
        ));                                                                                 \
    }                                                                                       \

    // 定义一个内联函数 npyv_loadn2_tillz_##F_SFX,加载并转换数据为目标类型,带步长和指定数量
    NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX                                      \
    (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane)                    \
    {                                                                                       \
        // 调用相应的加载函数,将输入指针的数据加载并转换为目标类型,带有指定步长和数量
        return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX(                \
            (const npyv_lanetype_##T_SFX *)ptr, stride, nlane                               \
        ));                                                                                 \
    }                                                                                       \

    // 定义一个内联函数 npyv_store2_till_##F_SFX,存储数据到目标指针,填充未使用的部分
    NPY_FINLINE void npyv_store2_till_##F_SFX                                               \
    (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a)                           \
    {
        npyv_store2_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
    NPY_FINLINE void npyv_storen2_till_##F_SFX
    (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a)
    {
        npyv_storen2_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, stride, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
    
    
    
    {
        // 使用 `npyv_store2_till_##T_SFX` 宏将数据 `a` 解释为 `T_SFX` 类型后存储到 `ptr` 指向的地址,存储 `nlane` 个元素
        npyv_store2_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
    
    // 使用 `npyv_storen2_till_##F_SFX` 函数将数据 `a` 解释为 `T_SFX` 类型后存储到 `ptr` 指向的地址,每隔 `stride` 存储一个元素,存储 `nlane` 个元素
    NPY_FINLINE void npyv_storen2_till_##F_SFX
    (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a)
    {
        npyv_storen2_till_##T_SFX(
            (npyv_lanetype_##T_SFX *)ptr, stride, nlane,
            npyv_reinterpret_##T_SFX##_##F_SFX(a)
        );
    }
// 宏定义,用于生成 AVX-512 指令集下的加载和存储操作的代码片段,支持两种数据类型的成对操作
#define NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(TYPE1, TYPE2) \
    // 在 AVX-512 指令集下实现 TYPE1 和 TYPE2 数据类型的特定操作

// 宏定义,实现 AVX-512 指令集下的内存交织加载和存储操作
#define NPYV_IMPL_AVX512_MEM_INTERLEAVE(SFX, ZSFX)                            \
    // 定义函数 npyv_zip_##ZSFX 和 npyv_unzip_##ZSFX,用于两通道的交织操作
    NPY_FINLINE npyv_##ZSFX##x2 npyv_zip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX);    \
    NPY_FINLINE npyv_##ZSFX##x2 npyv_unzip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX);  \
    // 定义函数 npyv_load_##SFX##x2,从内存中加载两个连续通道的数据
    NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2(                           \
        const npyv_lanetype_##SFX *ptr                                        \
    ) {                                                                       \
        return npyv_unzip_##ZSFX(                                             \
            npyv_load_##SFX(ptr), npyv_load_##SFX(ptr+npyv_nlanes_##SFX)      \
        );                                                                    \
    }                                                                         \
    // 定义函数 npyv_store_##SFX##x2,将两个通道的数据连续存储到内存中
    NPY_FINLINE void npyv_store_##SFX##x2(                                    \
        npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v                            \
    ) {                                                                       \
        npyv_##SFX##x2 zip = npyv_zip_##ZSFX(v.val[0], v.val[1]);             \
        npyv_store_##SFX(ptr, zip.val[0]);                                    \
        npyv_store_##SFX(ptr + npyv_nlanes_##SFX, zip.val[1]);                \
    }

// 使用宏定义生成 AVX-512 指令集下的内存交织加载和存储操作的具体实现
NPYV_IMPL_AVX512_MEM_INTERLEAVE(u8, u8)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(s8, u8)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(u16, u16)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(s16, u16)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(u32, u32)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(s32, u32)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(u64, u64)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(s64, u64)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(f32, f32)
NPYV_IMPL_AVX512_MEM_INTERLEAVE(f64, f64)

/**************************************************
 * Lookup table
 *************************************************/

// 使用向量作为索引来访问包含 32 个 float32 元素的查找表
NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx)
{
    // 加载表中的前 16 个元素到向量 table0
    const npyv_f32 table0 = npyv_load_f32(table);
    // 加载表中的后 16 个元素到向量 table1
    const npyv_f32 table1 = npyv_load_f32(table + 16);
    // 使用 _mm512_permutex2var_ps 函数按照 idx 的指定顺序对 table0 和 table1 进行混洗操作
    return _mm512_permutex2var_ps(table0, idx, table1);
}

// 使用向量作为索引来访问包含 32 个元素的 uint32 查找表,并将结果转换为 float32 向量返回
NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx)
{ return npyv_reinterpret_u32_f32(npyv_lut32_f32((const float*)table, idx)); }

// 使用向量作为索引来访问包含 32 个元素的 int32 查找表,并将结果转换为 float32 向量返回
NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx)
{ return npyv_reinterpret_s32_f32(npyv_lut32_f32((const float*)table, idx)); }

// 使用向量作为索引来访问包含 16 个元素的 float64 查找表
// (此处代码截断,未完成)
    # 加载一个包含双精度浮点数的表格到向量table0中
    const npyv_f64 table0 = npyv_load_f64(table);
    # 从表格中的第8个位置开始加载双精度浮点数到向量table1中
    const npyv_f64 table1 = npyv_load_f64(table + 8);
    # 使用掩码向量idx对table0和table1中的数据进行混洗,并返回结果
    return _mm512_permutex2var_pd(table0, idx, table1);
// 返回一个npyv_u64类型的向量,其中根据给定的索引从64位整数表中查找值
NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx)
{ return npyv_reinterpret_u64_f64(npyv_lut16_f64((const double*)table, idx)); }

// 返回一个npyv_s64类型的向量,其中根据给定的索引从64位有符号整数表中查找值
NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx)
{ return npyv_reinterpret_s64_f64(npyv_lut16_f64((const double*)table, idx)); }

#endif // _NPY_SIMD_AVX512_MEMORY_H

.\numpy\numpy\_core\src\common\simd\avx512\misc.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_MISC_H
#define _NPY_SIMD_AVX512_MISC_H

// 定义了一系列宏用于将 AVX-512 向量的所有元素设置为零
#define npyv_zero_u8  _mm512_setzero_si512
#define npyv_zero_s8  _mm512_setzero_si512
#define npyv_zero_u16 _mm512_setzero_si512
#define npyv_zero_s16 _mm512_setzero_si512
#define npyv_zero_u32 _mm512_setzero_si512
#define npyv_zero_s32 _mm512_setzero_si512
#define npyv_zero_u64 _mm512_setzero_si512
#define npyv_zero_s64 _mm512_setzero_si512
#define npyv_zero_f32 _mm512_setzero_ps
#define npyv_zero_f64 _mm512_setzero_pd

// 定义了一系列宏用于将 AVX-512 向量的所有元素设置为相同的值
#define npyv_setall_u8(VAL)  _mm512_set1_epi8((char)VAL)
#define npyv_setall_s8(VAL)  _mm512_set1_epi8((char)VAL)
#define npyv_setall_u16(VAL) _mm512_set1_epi16((short)VAL)
#define npyv_setall_s16(VAL) _mm512_set1_epi16((short)VAL)
#define npyv_setall_u32(VAL) _mm512_set1_epi32((int)VAL)
#define npyv_setall_s32(VAL) _mm512_set1_epi32(VAL)
#define npyv_setall_f32(VAL) _mm512_set1_ps(VAL)
#define npyv_setall_f64(VAL) _mm512_set1_pd(VAL)

// 在一些编译器中缺少了 _mm512_set_epi8 和 _mm512_set_epi16 函数,这里定义了一个特定值的向量函数
NPY_FINLINE __m512i npyv__setr_epi64(
    npy_int64, npy_int64, npy_int64, npy_int64,
    npy_int64, npy_int64, npy_int64, npy_int64
);
// 设置所有 AVX-512 64 位无符号整数向量的元素为同一个值
NPY_FINLINE npyv_u64 npyv_setall_u64(npy_uint64 a)
{
    npy_int64 ai = (npy_int64)a;
#if defined(_MSC_VER) && defined(_M_IX86)
    return npyv__setr_epi64(ai, ai, ai, ai, ai, ai, ai, ai);
#else
    return _mm512_set1_epi64(ai);
#endif
}
// 设置所有 AVX-512 64 位有符号整数向量的元素为同一个值
NPY_FINLINE npyv_s64 npyv_setall_s64(npy_int64 a)
{
#if defined(_MSC_VER) && defined(_M_IX86)
    return npyv__setr_epi64(a, a, a, a, a, a, a, a);
#else
    return _mm512_set1_epi64(a);
#endif
}
/**
 * 设置 AVX-512 8 位整数向量的每个通道为特定值,并将其余通道设置为特定值
 *
 * 在许多编译器中缺少了 _mm512_set_epi8 和 _mm512_set_epi16 函数
 */
NPY_FINLINE __m512i npyv__setr_epi8(
    char i0,  char i1,  char i2,  char i3,  char i4,  char i5,  char i6,  char i7,
    char i8,  char i9,  char i10, char i11, char i12, char i13, char i14, char i15,
    char i16, char i17, char i18, char i19, char i20, char i21, char i22, char i23,
    char i24, char i25, char i26, char i27, char i28, char i29, char i30, char i31,
    char i32, char i33, char i34, char i35, char i36, char i37, char i38, char i39,
    char i40, char i41, char i42, char i43, char i44, char i45, char i46, char i47,
    char i48, char i49, char i50, char i51, char i52, char i53, char i54, char i55,
    char i56, char i57, char i58, char i59, char i60, char i61, char i62, char i63)
{
    // 将输入的字符数组按照 AVX-512 要求对齐后加载为向量
    const char NPY_DECL_ALIGNED(64) data[64] = {
        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,  i8,  i9,  i10, i11, i12, i13, i14, i15,
        i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31,
        i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47,
        i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, i61, i62, i63
    };
    // 加载数据到 AVX-512 整数向量
    return _mm512_load_si512((const void*)data);
}

#endif // _NPY_SIMD_AVX512_MISC_H
NPY_FINLINE __m512i npyv__setr_epi16(
    short i0,  short i1,  short i2,  short i3,  short i4,  short i5,  short i6,  short i7,
    short i8,  short i9,  short i10, short i11, short i12, short i13, short i14, short i15,
    short i16, short i17, short i18, short i19, short i20, short i21, short i22, short i23,
    short i24, short i25, short i26, short i27, short i28, short i29, short i30, short i31)
{
    // 创建包含32个元素的数组,每个元素是输入的短整型参数
    const short NPY_DECL_ALIGNED(64) data[32] = {
        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,  i8,  i9,  i10, i11, i12, i13, i14, i15,
        i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31
    };
    // 使用 AVX-512 指令集加载包含在数组中的数据到 __m512i 类型的寄存器
    return _mm512_load_si512((const void*)data);
}

// 如果 _mm512_setr_* 被定义为宏,则由于宏不会展开生成的参数。
NPY_FINLINE __m512i npyv__setr_epi32(
    int i0, int i1, int i2,  int i3,  int i4,  int i5,  int i6,  int i7,
    int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15)
{
    // 使用输入的整型参数创建一个 __m512i 类型的寄存器
    return _mm512_setr_epi32(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15);
}

// 使用输入的 64 位整型参数创建一个 __m512i 类型的寄存器
NPY_FINLINE __m512i npyv__setr_epi64(npy_int64 i0, npy_int64 i1, npy_int64 i2, npy_int64 i3,
                                     npy_int64 i4, npy_int64 i5, npy_int64 i6, npy_int64 i7)
{
    // 如果编译器为 MSVC 且目标平台为 x86,则使用 _mm512_setr_epi32 创建 __m512i 类型的寄存器
    // 否则,使用 _mm512_setr_epi64 创建 __m512i 类型的寄存器
#if defined(_MSC_VER) && defined(_M_IX86)
    return _mm512_setr_epi32(
        (int)i0, (int)(i0 >> 32), (int)i1, (int)(i1 >> 32),
        (int)i2, (int)(i2 >> 32), (int)i3, (int)(i3 >> 32),
        (int)i4, (int)(i4 >> 32), (int)i5, (int)(i5 >> 32),
        (int)i6, (int)(i6 >> 32), (int)i7, (int)(i7 >> 32)
    );
#else
    return _mm512_setr_epi64(i0, i1, i2, i3, i4, i5, i6, i7);
#endif
}

// 使用输入的单精度浮点参数创建一个 __m512 类型的寄存器
NPY_FINLINE __m512 npyv__setr_ps(
    float i0, float i1, float i2,  float i3,  float i4,  float i5,  float i6,  float i7,
    float i8, float i9, float i10, float i11, float i12, float i13, float i14, float i15)
{
    // 使用 _mm512_setr_ps 创建一个 __m512 类型的寄存器,包含输入的单精度浮点参数
    return _mm512_setr_ps(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15);
}

// 使用输入的双精度浮点参数创建一个 __m512d 类型的寄存器
NPY_FINLINE __m512d npyv__setr_pd(double i0, double i1, double i2, double i3,
                                  double i4, double i5, double i6, double i7)
{
    // 使用 _mm512_setr_pd 创建一个 __m512d 类型的寄存器,包含输入的双精度浮点参数
    return _mm512_setr_pd(i0, i1, i2, i3, i4, i5, i6, i7);
}

// 宏定义,用于将填充值 FILL 和可变参数展开为对应的 npyv__setr_epi8 函数调用
#define npyv_setf_u8(FILL, ...)  npyv__setr_epi8(NPYV__SET_FILL_64(char, FILL, __VA_ARGS__))
#define npyv_setf_s8(FILL, ...)  npyv__setr_epi8(NPYV__SET_FILL_64(char, FILL, __VA_ARGS__))
#define npyv_setf_u16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_32(short, FILL, __VA_ARGS__))
#define npyv_setf_s16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_32(short, FILL, __VA_ARGS__))
#define npyv_setf_u32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_16(int, FILL, __VA_ARGS__))
#define npyv_setf_s32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_16(int, FILL, __VA_ARGS__))
#define npyv_setf_u64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_8(npy_int64, FILL, __VA_ARGS__))
#define npyv_setf_s64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_8(npy_int64, FILL, __VA_ARGS__))
// 定义宏 npyv_setf_f32,用于设置单精度浮点数向量中的值,调用 npyv__setr_ps 宏来实现
#define npyv_setf_f32(FILL, ...) npyv__setr_ps(NPYV__SET_FILL_16(float, FILL, __VA_ARGS__))
// 定义宏 npyv_setf_f64,用于设置双精度浮点数向量中的值,调用 npyv__setr_pd 宏来实现
#define npyv_setf_f64(FILL, ...) npyv__setr_pd(NPYV__SET_FILL_8(double, FILL, __VA_ARGS__))

// 定义宏 npyv_set_u8,将 npyv_setf_u8 宏调用为设置无符号8位整数向量中的值,0表示其余所有通道为0
#define npyv_set_u8(...)  npyv_setf_u8(0,  __VA_ARGS__)
// 定义宏 npyv_set_s8,将 npyv_setf_s8 宏调用为设置有符号8位整数向量中的值,0表示其余所有通道为0
#define npyv_set_s8(...)  npyv_setf_s8(0,  __VA_ARGS__)
// 定义宏 npyv_set_u16,将 npyv_setf_u16 宏调用为设置无符号16位整数向量中的值,0表示其余所有通道为0
#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__)
// 定义宏 npyv_set_s16,将 npyv_setf_s16 宏调用为设置有符号16位整数向量中的值,0表示其余所有通道为0
#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__)
// 定义宏 npyv_set_u32,将 npyv_setf_u32 宏调用为设置无符号32位整数向量中的值,0表示其余所有通道为0
#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__)
// 定义宏 npyv_set_s32,将 npyv_setf_s32 宏调用为设置有符号32位整数向量中的值,0表示其余所有通道为0
#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__)
// 定义宏 npyv_set_u64,将 npyv_setf_u64 宏调用为设置无符号64位整数向量中的值,0表示其余所有通道为0
#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__)
// 定义宏 npyv_set_s64,将 npyv_setf_s64 宏调用为设置有符号64位整数向量中的值,0表示其余所有通道为0
#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__)
// 定义宏 npyv_set_f32,将 npyv_setf_f32 宏调用为设置单精度浮点数向量中的值,0表示其余所有通道为0
#define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__)
// 定义宏 npyv_set_f64,将 npyv_setf_f64 宏调用为设置双精度浮点数向量中的值,0表示其余所有通道为0
#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__)

// 根据是否支持 AVX512BW 指令集选择不同的宏实现
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX512BW,定义宏 npyv_select_u8,使用 _mm512_mask_blend_epi8 实现按位选择无符号8位整数向量
    #define npyv_select_u8(MASK, A, B)  _mm512_mask_blend_epi8(MASK,  B, A)
    // 定义宏 npyv_select_u16,使用 _mm512_mask_blend_epi16 实现按位选择无符号16位整数向量
    #define npyv_select_u16(MASK, A, B) _mm512_mask_blend_epi16(MASK, B, A)
#else
    // 如果不支持 AVX512BW,定义函数 npyv_select_u8,使用 _mm512_xor_si512 和 _mm512_and_si512 实现按位选择无符号8位整数向量
    NPY_FINLINE __m512i npyv_select_u8(__m512i mask, __m512i a, __m512i b)
    { return _mm512_xor_si512(b, _mm512_and_si512(_mm512_xor_si512(b, a), mask)); }
    // 定义宏 npyv_select_u16,与 npyv_select_u8 相同
    #define npyv_select_u16 npyv_select_u8
#endif
// 定义宏 npyv_select_s8,与 npyv_select_u8 相同
#define npyv_select_s8  npyv_select_u8
// 定义宏 npyv_select_s16,与 npyv_select_u16 相同
#define npyv_select_s16 npyv_select_u16
// 定义宏 npyv_select_u32,使用 _mm512_mask_blend_epi32 实现按位选择无符号32位整数向量
#define npyv_select_u32(MASK, A, B) _mm512_mask_blend_epi32(MASK, B, A)
// 定义宏 npyv_select_s32,与 npyv_select_u32 相同
#define npyv_select_s32 npyv_select_u32
// 定义宏 npyv_select_u64,使用 _mm512_mask_blend_epi64 实现按位选择无符号64位整数向量
#define npyv_select_u64(MASK, A, B) _mm512_mask_blend_epi64(MASK, B, A)
// 定义宏 npyv_select_s64,与 npyv_select_u64 相同
#define npyv_select_s64 npyv_select_u64
// 定义宏 npyv_select_f32,使用 _mm512_mask_blend_ps 实现按位选择单精度浮点数向量
#define npyv_select_f32(MASK, A, B) _mm512_mask_blend_ps(MASK, B, A)
// 定义宏 npyv_select_f64,使用 _mm512_mask_blend_pd 实现按位选择双精度浮点数向量
#define npyv_select_f64(MASK, A, B) _mm512_mask_blend_pd(MASK, B, A)

// 提取第一个向量的第一个通道值
#define npyv_extract0_u8(A) ((npy_uint8)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_s8(A) ((npy_int8)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_u16(A) ((npy_uint16)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_s16(A) ((npy_int16)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_u32(A) ((npy_uint32)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_s32(A) ((npy_int32)_mm_cvtsi128_si32(_mm512_castsi512_si128(A)))
#define npyv_extract0_u64(A) ((npy_uint64)npyv128_cvtsi128_si64(_mm512_castsi512_si128(A)))
#define npyv_extract0_s64(A) ((npy_int64)npyv128_cvtsi128_si64(_mm512_castsi512_si128(A)))
#define npyv_extract0_f32(A) _mm_cvtss_f32(_mm512_castps512_ps128(A))
#define npyv_extract0_f64(A) _mm_cvtsd_f64(_mm512_castpd512_pd128(A))

// 重新解释宏,将输入参数重新解释为无符号8位整数向量
#define npyv_reinterpret_u8_u8(X)  X
// 将输入参数重新解释为有符号8位整数向量
#define npyv_reinterpret_u8_s8(X)  X
# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_s8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_u16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_s16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_u32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_s32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s8_s64(X) X

# 宏定义,将输入参数按 512 位转换为单精度浮点数向量
#define npyv_reinterpret_s8_f32 _mm512_castps_si512

# 宏定义,将输入参数按 512 位转换为双精度浮点数向量
#define npyv_reinterpret_s8_f64 _mm512_castpd_si512

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_u16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_s8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_s16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_u32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_s32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u16_s64(X) X

# 宏定义,将输入参数按 512 位转换为单精度浮点数向量
#define npyv_reinterpret_u16_f32 _mm512_castps_si512

# 宏定义,将输入参数按 512 位转换为双精度浮点数向量
#define npyv_reinterpret_u16_f64 _mm512_castpd_si512

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_s16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_s8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_u16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_u32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_s32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s16_s64(X) X

# 宏定义,将输入参数按 512 位转换为单精度浮点数向量
#define npyv_reinterpret_s16_f32 _mm512_castps_si512

# 宏定义,将输入参数按 512 位转换为双精度浮点数向量
#define npyv_reinterpret_s16_f64 _mm512_castpd_si512

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_u32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_s8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_u16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_s16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_s32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u32_s64(X) X

# 宏定义,将输入参数按 512 位转换为单精度浮点数向量
#define npyv_reinterpret_u32_f32 _mm512_castps_si512

# 宏定义,将输入参数按 512 位转换为双精度浮点数向量
#define npyv_reinterpret_u32_f64 _mm512_castpd_si512

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_s32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_s8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_u16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_s16(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_u32(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_s32_s64(X) X

# 宏定义,将输入参数按 512 位转换为单精度浮点数向量
#define npyv_reinterpret_s32_f32 _mm512_castps_si512

# 宏定义,将输入参数按 512 位转换为双精度浮点数向量
#define npyv_reinterpret_s32_f64 _mm512_castpd_si512

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u64_u64(X) X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define npyv_reinterpret_u64_u8(X)  X

# 宏定义,将输入参数直接作为输出,不做任何类型转换
#define np
#define npyv_reinterpret_f32_s8  _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_u16 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_s16 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_u32 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_s32 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_u64 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_s64 _mm512_castsi512_ps
// 定义将 512 位整数转换为单精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f32_f64 _mm512_castpd_ps
// 定义将 512 位双精度浮点数转换为单精度浮点数的宏,使用 AVX-512 指令集

#define npyv_reinterpret_f64_f64(X) X
// 定义将双精度浮点数保持不变的宏
#define npyv_reinterpret_f64_u8  _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_s8  _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_u16 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_s16 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_u32 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_s32 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_u64 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_s64 _mm512_castsi512_pd
// 定义将 512 位整数转换为双精度浮点数的宏,使用 AVX-512 指令集
#define npyv_reinterpret_f64_f32 _mm512_castps_pd
// 定义将单精度浮点数转换为双精度浮点数的宏,使用 AVX-512 指令集

#ifdef NPY_HAVE_AVX512_KNL
    #define npyv_cleanup() ((void)0)
#else
    #define npyv_cleanup _mm256_zeroall
#endif
// 如果定义了 NPY_HAVE_AVX512_KNL,则定义 npyv_cleanup 为空操作;否则定义为 _mm256_zeroall,该函数清空 AVX 寄存器

#endif // _NPY_SIMD_AVX512_MISC_H
// 结束条件编译指令,用于保护头文件内容不被重复引入

.\numpy\numpy\_core\src\common\simd\avx512\operators.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_OPERATORS_H
#define _NPY_SIMD_AVX512_OPERATORS_H

#include "conversion.h" // tobits

/***************************
 * Shifting
 ***************************/

// left
#ifdef NPY_HAVE_AVX512BW
    #define npyv_shl_u16(A, C) _mm512_sll_epi16(A, _mm_cvtsi32_si128(C))
#else
    // 定义 AVX512BW 不可用时的位移操作函数,参数为 512 位整数向量和整数常量
    #define NPYV_IMPL_AVX512_SHIFT(FN, INTRIN)          \
        NPY_FINLINE __m512i npyv_##FN(__m512i a, int c) \
        {                                               \
            // 将 512 位向量拆分为两个 256 位向量
            __m256i l  = npyv512_lower_si256(a);        \
            __m256i h  = npyv512_higher_si256(a);       \
            // 将整数常量转换为 128 位的数据类型
            __m128i cv = _mm_cvtsi32_si128(c);          \
            // 对低位和高位向量分别进行指定的位移操作
            l = _mm256_##INTRIN(l, cv);                 \
            h = _mm256_##INTRIN(h, cv);                 \
            // 将结果重新组合成一个 512 位向量返回
            return npyv512_combine_si256(l, h);         \
        }

    // 定义具体的位移函数 npyv_shl_u16,使用 AVX2 指令集的 sll_epi16 函数
    NPYV_IMPL_AVX512_SHIFT(shl_u16, sll_epi16)
#endif
#define npyv_shl_s16 npyv_shl_u16
// 定义其他整数类型的左移操作宏,参数为向量和整数常量,使用对应的 AVX512 指令
#define npyv_shl_u32(A, C) _mm512_sll_epi32(A, _mm_cvtsi32_si128(C))
#define npyv_shl_s32(A, C) _mm512_sll_epi32(A, _mm_cvtsi32_si128(C))
#define npyv_shl_u64(A, C) _mm512_sll_epi64(A, _mm_cvtsi32_si128(C))
#define npyv_shl_s64(A, C) _mm512_sll_epi64(A, _mm_cvtsi32_si128(C))

// left by an immediate constant
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX512BW,则使用对应的 slli_epi16 函数进行左移操作
    #define npyv_shli_u16 _mm512_slli_epi16
#else
    // 否则使用之前定义的 npyv_shl_u16 宏进行左移操作
    #define npyv_shli_u16 npyv_shl_u16
#endif
// 定义其他整数类型的按常量左移操作宏,使用对应的 AVX512 指令
#define npyv_shli_s16  npyv_shl_u16
#define npyv_shli_u32 _mm512_slli_epi32
#define npyv_shli_s32 _mm512_slli_epi32
#define npyv_shli_u64 _mm512_slli_epi64
#define npyv_shli_s64 _mm512_slli_epi64

// right
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX512BW,则使用对应的 srl_epi16 和 sra_epi16 函数进行右移操作
    #define npyv_shr_u16(A, C) _mm512_srl_epi16(A, _mm_cvtsi32_si128(C))
    #define npyv_shr_s16(A, C) _mm512_sra_epi16(A, _mm_cvtsi32_si128(C))
#else
    // 否则使用自定义的宏 NPYV_IMPL_AVX512_SHIFT 定义的右移函数
    NPYV_IMPL_AVX512_SHIFT(shr_u16, srl_epi16)
    NPYV_IMPL_AVX512_SHIFT(shr_s16, sra_epi16)
#endif
// 定义其他整数类型的右移操作宏,使用对应的 AVX512 指令
#define npyv_shr_u32(A, C) _mm512_srl_epi32(A, _mm_cvtsi32_si128(C))
#define npyv_shr_s32(A, C) _mm512_sra_epi32(A, _mm_cvtsi32_si128(C))
#define npyv_shr_u64(A, C) _mm512_srl_epi64(A, _mm_cvtsi32_si128(C))
#define npyv_shr_s64(A, C) _mm512_sra_epi64(A, _mm_cvtsi32_si128(C))

// right by an immediate constant
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX512BW,则使用对应的 srli_epi16 和 srai_epi16 函数进行按常量右移操作
    #define npyv_shri_u16 _mm512_srli_epi16
    #define npyv_shri_s16 _mm512_srai_epi16
#else
    // 否则使用之前定义的 npyv_shr_u16 和 npyv_shr_s16 宏进行右移操作
    #define npyv_shri_u16 npyv_shr_u16
    #define npyv_shri_s16 npyv_shr_s16
#endif
// 定义其他整数类型的按常量右移操作宏,使用对应的 AVX512 指令
#define npyv_shri_u32 _mm512_srli_epi32
#define npyv_shri_s32 _mm512_srai_epi32
#define npyv_shri_u64 _mm512_srli_epi64
#define npyv_shri_s64 _mm512_srai_epi64

/***************************
 * Logical
 ***************************/

// AND
// 定义各种整数类型的按位与操作宏,使用对应的 AVX512 指令
#define npyv_and_u8  _mm512_and_si512
#define npyv_and_s8  _mm512_and_si512
#define npyv_and_u16 _mm512_and_si512
#define npyv_and_s16 _mm512_and_si512
#define npyv_and_u32 _mm512_and_si512
#define npyv_and_s32 _mm512_and_si512
#define npyv_and_u64 _mm512_and_si512
#define npyv_and_s64 _mm512_and_si512
#ifdef NPY_HAVE_AVX512DQ
    # 定义宏,用于执行 AVX-512 指令集的单精度浮点数按位与操作
    #define npyv_and_f32 _mm512_and_ps
    # 定义宏,用于执行 AVX-512 指令集的双精度浮点数按位与操作
    #define npyv_and_f64 _mm512_and_pd
#else
    NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_and_f32, _mm512_and_si512)
    // 定义 AVX512 浮点数按位与操作宏,使用 _mm512_and_si512 实现
    NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_and_f64, _mm512_and_si512)
    // 定义 AVX512 双精度浮点数按位与操作宏,使用 _mm512_and_si512 实现
#endif

// OR
#define npyv_or_u8  _mm512_or_si512
// 定义 AVX512 无符号 8 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_s8  _mm512_or_si512
// 定义 AVX512 有符号 8 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_u16 _mm512_or_si512
// 定义 AVX512 无符号 16 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_s16 _mm512_or_si512
// 定义 AVX512 有符号 16 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_u32 _mm512_or_si512
// 定义 AVX512 无符号 32 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_s32 _mm512_or_si512
// 定义 AVX512 有符号 32 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_u64 _mm512_or_si512
// 定义 AVX512 无符号 64 位整数按位或操作宏,使用 _mm512_or_si512
#define npyv_or_s64 _mm512_or_si512
// 定义 AVX512 有符号 64 位整数按位或操作宏,使用 _mm512_or_si512
#ifdef NPY_HAVE_AVX512DQ
    #define npyv_or_f32 _mm512_or_ps
    // 如果支持 AVX512DQ,定义 AVX512 单精度浮点数按位或操作宏,使用 _mm512_or_ps
    #define npyv_or_f64 _mm512_or_pd
    // 如果支持 AVX512DQ,定义 AVX512 双精度浮点数按位或操作宏,使用 _mm512_or_pd
#else
    NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_or_f32, _mm512_or_si512)
    // 否则,定义 AVX512 浮点数按位或操作宏,使用 _mm512_or_si512 实现
    NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_or_f64, _mm512_or_si512)
    // 否则,定义 AVX512 双精度浮点数按位或操作宏,使用 _mm512_or_si512 实现
#endif

// XOR
#define npyv_xor_u8  _mm512_xor_si512
// 定义 AVX512 无符号 8 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_s8  _mm512_xor_si512
// 定义 AVX512 有符号 8 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_u16 _mm512_xor_si512
// 定义 AVX512 无符号 16 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_s16 _mm512_xor_si512
// 定义 AVX512 有符号 16 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_u32 _mm512_xor_si512
// 定义 AVX512 无符号 32 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_s32 _mm512_xor_si512
// 定义 AVX512 有符号 32 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_u64 _mm512_xor_si512
// 定义 AVX512 无符号 64 位整数按位异或操作宏,使用 _mm512_xor_si512
#define npyv_xor_s64 _mm512_xor_si512
// 定义 AVX512 有符号 64 位整数按位异或操作宏,使用 _mm512_xor_si512
#ifdef NPY_HAVE_AVX512DQ
    #define npyv_xor_f32 _mm512_xor_ps
    // 如果支持 AVX512DQ,定义 AVX512 单精度浮点数按位异或操作宏,使用 _mm512_xor_ps
    #define npyv_xor_f64 _mm512_xor_pd
    // 如果支持 AVX512DQ,定义 AVX512 双精度浮点数按位异或操作宏,使用 _mm512_xor_pd
#else
    NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_xor_f32, _mm512_xor_si512)
    // 否则,定义 AVX512 浮点数按位异或操作宏,使用 _mm512_xor_si512 实现
    NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_xor_f64, _mm512_xor_si512)
    // 否则,定义 AVX512 双精度浮点数按位异或操作宏,使用 _mm512_xor_si512 实现
#endif

// NOT
#define npyv_not_u8(A) _mm512_xor_si512(A, _mm512_set1_epi32(-1))
// 定义 AVX512 无符号 8 位整数按位取反操作宏,使用 _mm512_xor_si512(A, _mm512_set1_epi32(-1))
#define npyv_not_s8  npyv_not_u8
// 定义 AVX512 有符号 8 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_u16 npyv_not_u8
// 定义 AVX512 无符号 16 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_s16 npyv_not_u8
// 定义 AVX512 有符号 16 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_u32 npyv_not_u8
// 定义 AVX512 无符号 32 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_s32 npyv_not_u8
// 定义 AVX512 有符号 32 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_u64 npyv_not_u8
// 定义 AVX512 无符号 64 位整数按位取反操作宏,与无符号 8 位整数取反相同
#define npyv_not_s64 npyv_not_u8
// 定义 AVX512 有符号 64 位整数按位取反操作宏,与无符号 8 位整数取反相同
#ifdef NPY_HAVE_AVX512DQ
    #define npyv_not_f32(A) _mm512_xor_ps(A, _mm512_castsi512_ps(_mm512_set1_epi32(-1)))
    // 如果支持 AVX512DQ,定义 AVX512 单精度浮点数按位取反操作宏,使用 _mm512_xor_ps 实现
    #define npyv_not_f64(A) _mm512_xor_pd(A, _mm512_castsi512_pd(_mm512_set1_epi32(-1)))
    // 如果支持 AVX512DQ,定义 AVX512 双精度浮点数按位取反操作宏,使用 _mm512_xor_pd 实现
#else
    #define npyv_not_f32(A) _mm512_castsi512_ps(npyv_not_u32(_mm512_castps_si512(A)))
    // 否则,定义 AVX512 单精度浮点数按位取
    # 定义一个内联函数,对两个8位向量进行按位异或操作,并返回结果
    NPY_FINLINE npyv_b8  npyv_xor_b8(npyv_b8 a, npyv_b8 b)
    { return a ^ b; }
    
    # 定义一个内联函数,对两个16位向量进行按位异或操作,并返回结果
    NPY_FINLINE npyv_b16 npyv_xor_b16(npyv_b16 a, npyv_b16 b)
    { return a ^ b; }
    
    # 定义一个内联函数,对一个8位向量进行按位取反操作,并返回结果
    NPY_FINLINE npyv_b8  npyv_not_b8(npyv_b8 a)
    { return ~a; }
    
    # 定义一个内联函数,对一个16位向量进行按位取反操作,并返回结果
    NPY_FINLINE npyv_b16 npyv_not_b16(npyv_b16 a)
    { return ~a; }
    
    # 定义一个内联函数,对一个8位向量与另一个8位向量按位取反的结果进行按位与操作,并返回结果
    NPY_FINLINE npyv_b8  npyv_andc_b8(npyv_b8 a, npyv_b8 b)
    { return a & (~b); }
    
    # 定义一个内联函数,对一个8位向量与另一个8位向量按位取反的结果进行按位或操作,并返回结果
    NPY_FINLINE npyv_b8  npyv_orc_b8(npyv_b8 a, npyv_b8 b)
    { return a | (~b); }
    
    # 定义一个内联函数,对两个8位向量进行按位异或操作后再按位取反,并返回结果
    NPY_FINLINE npyv_b8  npyv_xnor_b8(npyv_b8 a, npyv_b8 b)
    { return ~(a ^ b); }
#else
    // 定义 AVX512 下的位与操作宏
    #define npyv_and_b8  _mm512_and_si512
    // 定义 AVX512 下的位与操作宏
    #define npyv_and_b16 _mm512_and_si512
    // 定义 AVX512 下的位或操作宏
    #define npyv_or_b8   _mm512_or_si512
    // 定义 AVX512 下的位或操作宏
    #define npyv_or_b16  _mm512_or_si512
    // 定义 AVX512 下的位异或操作宏
    #define npyv_xor_b8  _mm512_xor_si512
    // 定义 AVX512 下的位异或操作宏
    #define npyv_xor_b16 _mm512_xor_si512
    // 定义 AVX512 下的位非操作宏
    #define npyv_not_b8  npyv_not_u8
    // 定义 AVX512 下的位非操作宏
    #define npyv_not_b16 npyv_not_u8
    // 定义 AVX512 下的位与非操作宏
    #define npyv_andc_b8(A, B) _mm512_andnot_si512(B, A)
    // 定义 AVX512 下的位或非操作宏
    #define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A)
    // 定义 AVX512 下的位异或非操作宏
    #define npyv_xnor_b8(A, B) npyv_not_b8(npyv_xor_b8(A, B))
#endif

#define npyv_and_b32 _mm512_kand
#define npyv_or_b32  _mm512_kor
#define npyv_xor_b32 _mm512_kxor
#define npyv_not_b32 _mm512_knot

#ifdef NPY_HAVE_AVX512DQ_MASK
    // 定义 AVX512 DQ 指令集下的位与操作宏
    #define npyv_and_b64 _kand_mask8
    // 定义 AVX512 DQ 指令集下的位或操作宏
    #define npyv_or_b64  _kor_mask8
    // 定义 AVX512 DQ 指令集下的位异或操作宏
    #define npyv_xor_b64 _kxor_mask8
    // 定义 AVX512 DQ 指令集下的位非操作宏
    #define npyv_not_b64 _knot_mask8
#else
    // 如果不支持 AVX512 DQ 指令集,定义 64 位位与操作函数
    NPY_FINLINE npyv_b64 npyv_and_b64(npyv_b64 a, npyv_b64 b)
    { return (npyv_b64)_mm512_kand((npyv_b32)a, (npyv_b32)b); }
    // 如果不支持 AVX512 DQ 指令集,定义 64 位位或操作函数
    NPY_FINLINE npyv_b64 npyv_or_b64(npyv_b64 a, npyv_b64 b)
    { return (npyv_b64)_mm512_kor((npyv_b32)a, (npyv_b32)b); }
    // 如果不支持 AVX512 DQ 指令集,定义 64 位位异或操作函数
    NPY_FINLINE npyv_b64 npyv_xor_b64(npyv_b64 a, npyv_b64 b)
    { return (npyv_b64)_mm512_kxor((npyv_b32)a, (npyv_b32)b); }
    // 如果不支持 AVX512 DQ 指令集,定义 64 位位非操作函数
    NPY_FINLINE npyv_b64 npyv_not_b64(npyv_b64 a)
    { return (npyv_b64)_mm512_knot((npyv_b32)a); }
#endif

/***************************
 * Comparison
 ***************************/

// int Equal
#ifdef NPY_HAVE_AVX512BW
    // 定义 AVX512 BW 指令集下的无符号 8 位相等比较操作宏
    #define npyv_cmpeq_u8  _mm512_cmpeq_epu8_mask
    // 定义 AVX512 BW 指令集下的有符号 8 位相等比较操作宏
    #define npyv_cmpeq_s8  _mm512_cmpeq_epi8_mask
    // 定义 AVX512 BW 指令集下的无符号 16 位相等比较操作宏
    #define npyv_cmpeq_u16 _mm512_cmpeq_epu16_mask
    // 定义 AVX512 BW 指令集下的有符号 16 位相等比较操作宏
    #define npyv_cmpeq_s16 _mm512_cmpeq_epi16_mask
#else
    // 如果不支持 AVX512 BW 指令集,从 AVX2 转换定义无符号 8 位相等比较操作函数
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpeq_u8,  _mm256_cmpeq_epi8)
    // 如果不支持 AVX512 BW 指令集,从 AVX2 转换定义无符号 16 位相等比较操作函数
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpeq_u16, _mm256_cmpeq_epi16)
    // 如果不支持 AVX512 BW 指令集,定义有符号 8 位相等比较操作宏
    #define npyv_cmpeq_s8  npyv_cmpeq_u8
    // 如果不支持 AVX512 BW 指令集,定义有符号 16 位相等比较操作宏
    #define npyv_cmpeq_s16 npyv_cmpeq_u16
#endif
// 定义 AVX512 下的无符号 32 位相等比较操作宏
#define npyv_cmpeq_u32 _mm512_cmpeq_epu32_mask
// 定义 AVX512 下的有符号 32 位相等比较操作宏
#define npyv_cmpeq_s32 _mm512_cmpeq_epi32_mask
// 定义 AVX512 下的无符号 64 位相等比较操作宏
#define npyv_cmpeq_u64 _mm512_cmpeq_epu64_mask
// 定义 AVX512 下的有符号 64 位相等比较操作宏
#define npyv_cmpeq_s64 _mm512_cmpeq_epi64_mask

// int not equal
#ifdef NPY_HAVE_AVX512BW
    // 定义 AVX512 BW 指令集下的无符号 8 位不相等比较操作宏
    #define npyv_cmpneq_u8  _mm512_cmpneq_epu8_mask
    // 定义 AVX512 BW 指令集下的有符号 8 位不相等比较操作宏
    #define npyv_cmpneq_s8  _mm512_cmpneq_epi8_mask
    // 定义 AVX512 BW 指令集下的无符号 16 位不相等比较操作宏
    #define npyv_cmpneq_u16 _mm512_cmpneq_epu16_mask
    // 定义 AVX512 BW 指令集下的有符号 16 位不相等比较操作宏
    #define npyv_cmpneq_s16 _mm512_cmpneq_epi16_mask
#else
    // 如果不支持 AVX512 BW 指令集,定义无符号 8 位不相等比较操作宏
    #define npyv_cmpneq_u8(A, B) npyv_not_u8(npyv_cmpeq_u8(A, B))
    // 如果不支持 AVX512 BW 指令集,定义无符号 16 位不相等比较操作宏
    #define npyv_cmpneq_u16(A, B) npyv_not_u16(npyv_cmpeq_u16(A, B))
    // 如果不支持 AVX512 BW 指令集,定义有符号 8 位不相等比较操作宏
    #define npyv_cmpne
    # 使用 AVX2 指令集中的 _mm256_cmpgt_epi8 函数实现 npyv_cmpgt_s8 函数
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpgt_s8,  _mm256_cmpgt_epi8)
    
    # 使用 AVX2 指令集中的 _mm256_cmpgt_epi16 函数实现 npyv_cmpgt_s16 函数
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpgt_s16, _mm256_cmpgt_epi16)
    
    # 定义一个内联函数 npyv_cmpgt_u8,用于比较两个 __m512i 类型的无符号整数向量 a 和 b
    NPY_FINLINE __m512i npyv_cmpgt_u8(__m512i a, __m512i b)
    {
        # 创建一个常量向量 sbit,其每个元素为 0x80808080,用于处理无符号整数的比较
        const __m512i sbit = _mm512_set1_epi32(0x80808080);
        # 返回对 a 和 b 分别按位异或后再传给 npyv_cmpgt_s8 处理的结果
        return npyv_cmpgt_s8(_mm512_xor_si512(a, sbit), _mm512_xor_si512(b, sbit));
    }
    
    # 定义一个内联函数 npyv_cmpgt_u16,用于比较两个 __m512i 类型的无符号整数向量 a 和 b
    NPY_FINLINE __m512i npyv_cmpgt_u16(__m512i a, __m512i b)
    {
        # 创建一个常量向量 sbit,其每个元素为 0x80008000,用于处理无符号整数的比较
        const __m512i sbit = _mm512_set1_epi32(0x80008000);
        # 返回对 a 和 b 分别按位异或后再传给 npyv_cmpgt_s16 处理的结果
        return npyv_cmpgt_s16(_mm512_xor_si512(a, sbit), _mm512_xor_si512(b, sbit));
    }
#endif
#define npyv_cmpgt_u32 _mm512_cmpgt_epu32_mask
#define npyv_cmpgt_s32 _mm512_cmpgt_epi32_mask
#define npyv_cmpgt_u64 _mm512_cmpgt_epu64_mask
#define npyv_cmpgt_s64 _mm512_cmpgt_epi64_mask

// 定义无符号和有符号整数的 AVX-512 指令,用于比较大于的掩码生成

#ifdef NPY_HAVE_AVX512BW
    #define npyv_cmpge_u8  _mm512_cmpge_epu8_mask
    #define npyv_cmpge_s8  _mm512_cmpge_epi8_mask
    #define npyv_cmpge_u16 _mm512_cmpge_epu16_mask
    #define npyv_cmpge_s16 _mm512_cmpge_epi16_mask
#else
    #define npyv_cmpge_u8(A, B)  npyv_not_u8(npyv_cmpgt_u8(B, A))
    #define npyv_cmpge_s8(A, B)  npyv_not_s8(npyv_cmpgt_s8(B, A))
    #define npyv_cmpge_u16(A, B) npyv_not_u16(npyv_cmpgt_u16(B, A))
    #define npyv_cmpge_s16(A, B) npyv_not_s16(npyv_cmpgt_s16(B, A))
#endif

// 如果支持 AVX-512BW 指令集,则定义无符号和有符号整数的大于等于掩码生成指令,否则用大于生成掩码并取反生成大于等于掩码

#define npyv_cmpge_u32 _mm512_cmpge_epu32_mask
#define npyv_cmpge_s32 _mm512_cmpge_epi32_mask
#define npyv_cmpge_u64 _mm512_cmpge_epu64_mask
#define npyv_cmpge_s64 _mm512_cmpge_epi64_mask

// 定义无符号和有符号整数的 AVX-512 指令,用于比较大于等于的掩码生成

#define npyv_cmplt_u8(A, B)  npyv_cmpgt_u8(B, A)
#define npyv_cmplt_s8(A, B)  npyv_cmpgt_s8(B, A)
#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A)
#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A)
#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A)
#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A)
#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A)
#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A)

// 定义无符号和有符号整数的 AVX-512 指令,用于比较小于的掩码生成

#define npyv_cmple_u8(A, B)  npyv_cmpge_u8(B, A)
#define npyv_cmple_s8(A, B)  npyv_cmpge_s8(B, A)
#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A)
#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A)
#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A)
#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A)
#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A)
#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A)

// 定义无符号和有符号整数的 AVX-512 指令,用于比较小于等于的掩码生成

// precision comparison
#define npyv_cmpeq_f32(A, B)  _mm512_cmp_ps_mask(A, B, _CMP_EQ_OQ)
#define npyv_cmpeq_f64(A, B)  _mm512_cmp_pd_mask(A, B, _CMP_EQ_OQ)
#define npyv_cmpneq_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_NEQ_UQ)
#define npyv_cmpneq_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_NEQ_UQ)
#define npyv_cmplt_f32(A, B)  _mm512_cmp_ps_mask(A, B, _CMP_LT_OQ)
#define npyv_cmplt_f64(A, B)  _mm512_cmp_pd_mask(A, B, _CMP_LT_OQ)
#define npyv_cmple_f32(A, B)  _mm512_cmp_ps_mask(A, B, _CMP_LE_OQ)
#define npyv_cmple_f64(A, B)  _mm512_cmp_pd_mask(A, B, _CMP_LE_OQ)
#define npyv_cmpgt_f32(A, B)  _mm512_cmp_ps_mask(A, B, _CMP_GT_OQ)
#define npyv_cmpgt_f64(A, B)  _mm512_cmp_pd_mask(A, B, _CMP_GT_OQ)
#define npyv_cmpge_f32(A, B)  _mm512_cmp_ps_mask(A, B, _CMP_GE_OQ)
#define npyv_cmpge_f64(A, B)  _mm512_cmp_pd_mask(A, B, _CMP_GE_OQ)

// 定义单精度和双精度浮点数的 AVX-512 指令,用于比较相等、不相等、小于、小于等于、大于、大于等于的掩码生成

// check special cases
NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
{ return _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q); }
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
{ return _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q); }

// 检查特殊情况,返回单精度和双精度浮点数向量中非 NaN 元素的掩码

// Test cross all vector lanes
// any: returns true if any of the elements is not equal to zero
// all: returns true if all elements are not equal to zero
# 定义 AVX512 SIMD 操作的任意和所有函数模板

#define NPYV_IMPL_AVX512_ANYALL(SFX, MASK)        \
    # 定义检查是否存在非零元素的函数,返回值为布尔类型
    NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \
    { return npyv_tobits_##SFX(a) != 0; }         \
    # 定义检查是否所有元素都等于给定掩码值的函数,返回值为布尔类型
    NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \
    { return npyv_tobits_##SFX(a) == MASK; }

# 使用模板定义具体的 AVX512 SIMD 操作函数

NPYV_IMPL_AVX512_ANYALL(b8,  0xffffffffffffffffull)
NPYV_IMPL_AVX512_ANYALL(b16, 0xfffffffful)
NPYV_IMPL_AVX512_ANYALL(b32, 0xffff)
NPYV_IMPL_AVX512_ANYALL(b64, 0xff)

# 取消定义 AVX512 SIMD 操作的任意和所有函数模板

#undef NPYV_IMPL_AVX512_ANYALL

# 重新定义 AVX512 SIMD 操作的任意和所有函数模板,支持不同的数据类型 SFX 和 BSFX,以及不同的掩码 MASK

#define NPYV_IMPL_AVX512_ANYALL(SFX, BSFX, MASK)   \
    # 定义检查是否存在非零元素的函数,返回值为布尔类型
    NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a)  \
    {                                              \
        return npyv_tobits_##BSFX(                 \
            npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \
        ) != MASK;                                 \
    }                                              \
    # 定义检查是否所有元素都等于给定掩码值的函数,返回值为布尔类型
    NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a)  \
    {                                              \
        return npyv_tobits_##BSFX(                 \
            npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \
        ) == 0;                                    \
    }

# 使用模板定义具体的 AVX512 SIMD 操作函数

NPYV_IMPL_AVX512_ANYALL(u8,  b8,  0xffffffffffffffffull)
NPYV_IMPL_AVX512_ANYALL(s8,  b8,  0xffffffffffffffffull)
NPYV_IMPL_AVX512_ANYALL(u16, b16, 0xfffffffful)
NPYV_IMPL_AVX512_ANYALL(s16, b16, 0xfffffffful)
NPYV_IMPL_AVX512_ANYALL(u32, b32, 0xffff)
NPYV_IMPL_AVX512_ANYALL(s32, b32, 0xffff)
NPYV_IMPL_AVX512_ANYALL(u64, b64, 0xff)
NPYV_IMPL_AVX512_ANYALL(s64, b64, 0xff)
NPYV_IMPL_AVX512_ANYALL(f32, b32, 0xffff)
NPYV_IMPL_AVX512_ANYALL(f64, b64, 0xff)

# 取消定义 AVX512 SIMD 操作的任意和所有函数模板

#undef NPYV_IMPL_AVX512_ANYALL

#endif // _NPY_SIMD_AVX512_OPERATORS_H

.\numpy\numpy\_core\src\common\simd\avx512\reorder.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_REORDER_H
#define _NPY_SIMD_AVX512_REORDER_H

// 定义宏:将两个向量的低部分合并
#define npyv_combinel_u8(A, B) _mm512_inserti64x4(A, _mm512_castsi512_si256(B), 1)
#define npyv_combinel_s8  npyv_combinel_u8
#define npyv_combinel_u16 npyv_combinel_u8
#define npyv_combinel_s16 npyv_combinel_u8
#define npyv_combinel_u32 npyv_combinel_u8
#define npyv_combinel_s32 npyv_combinel_u8
#define npyv_combinel_u64 npyv_combinel_u8
#define npyv_combinel_s64 npyv_combinel_u8
#define npyv_combinel_f64(A, B) _mm512_insertf64x4(A, _mm512_castpd512_pd256(B), 1)
#ifdef NPY_HAVE_AVX512DQ
    // 定义宏:将两个单精度浮点数向量的低部分合并
    #define npyv_combinel_f32(A, B) \
        _mm512_insertf32x8(A, _mm512_castps512_ps256(B), 1)
#else
    // 定义宏:将两个单精度浮点数向量的低部分合并(替代实现)
    #define npyv_combinel_f32(A, B) \
        _mm512_castsi512_ps(npyv_combinel_u8(_mm512_castps_si512(A), _mm512_castps_si512(B)))
#endif

// 定义宏:将两个向量的高部分合并
#define npyv_combineh_u8(A, B) _mm512_inserti64x4(B, _mm512_extracti64x4_epi64(A, 1), 0)
#define npyv_combineh_s8  npyv_combineh_u8
#define npyv_combineh_u16 npyv_combineh_u8
#define npyv_combineh_s16 npyv_combineh_u8
#define npyv_combineh_u32 npyv_combineh_u8
#define npyv_combineh_s32 npyv_combineh_u8
#define npyv_combineh_u64 npyv_combineh_u8
#define npyv_combineh_s64 npyv_combineh_u8
#define npyv_combineh_f64(A, B) _mm512_insertf64x4(B, _mm512_extractf64x4_pd(A, 1), 0)
#ifdef NPY_HAVE_AVX512DQ
    // 定义宏:将两个单精度浮点数向量的高部分合并
    #define npyv_combineh_f32(A, B) \
        _mm512_insertf32x8(B, _mm512_extractf32x8_ps(A, 1), 0)
#else
    // 定义宏:将两个单精度浮点数向量的高部分合并(替代实现)
    #define npyv_combineh_f32(A, B) \
        _mm512_castsi512_ps(npyv_combineh_u8(_mm512_castps_si512(A), _mm512_castps_si512(B)))
#endif

// 定义函数:从两个整型向量 a 和 b 中组合得到一个 m512ix2 结构体
NPY_FINLINE npyv_m512ix2 npyv__combine(__m512i a, __m512i b)
{
    npyv_m512ix2 r;
    // 将向量 a 和 b 的低部分合并
    r.val[0] = npyv_combinel_u8(a, b);
    // 将向量 a 和 b 的高部分合并
    r.val[1] = npyv_combineh_u8(a, b);
    return r;
}

// 定义函数:从两个单精度浮点数向量 a 和 b 中组合得到一个 f32x2 结构体
NPY_FINLINE npyv_f32x2 npyv_combine_f32(__m512 a, __m512 b)
{
    npyv_f32x2 r;
    // 将单精度浮点数向量 a 和 b 的低部分合并
    r.val[0] = npyv_combinel_f32(a, b);
    // 将单精度浮点数向量 a 和 b 的高部分合并
    r.val[1] = npyv_combineh_f32(a, b);
    return r;
}

// 定义函数:从两个双精度浮点数向量 a 和 b 中组合得到一个 f64x2 结构体
NPY_FINLINE npyv_f64x2 npyv_combine_f64(__m512d a, __m512d b)
{
    npyv_f64x2 r;
    // 将双精度浮点数向量 a 和 b 的低部分合并
    r.val[0] = npyv_combinel_f64(a, b);
    // 将双精度浮点数向量 a 和 b 的高部分合并
    r.val[1] = npyv_combineh_f64(a, b);
    return r;
}

// 定义宏:将两个整型向量的低部分合并,实际调用 npyv__combine 函数
#define npyv_combine_u8  npyv__combine
#define npyv_combine_s8  npyv__combine
#define npyv_combine_u16 npyv__combine
#define npyv_combine_s16 npyv__combine
#define npyv_combine_u32 npyv__combine
#define npyv_combine_s32 npyv__combine
#define npyv_combine_u64 npyv__combine
#define npyv_combine_s64 npyv__combine

// 定义宏:插入两个向量的低部分,根据 AVX512BW 的可用性选择实现
#ifndef NPY_HAVE_AVX512BW
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpacklo_epi8,  _mm256_unpacklo_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpackhi_epi8,  _mm256_unpackhi_epi8)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpacklo_epi16, _mm256_unpacklo_epi16)
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpackhi_epi16, _mm256_unpackhi_epi16)
#endif

#endif // _NPY_SIMD_AVX512_REORDER_H
# 定义一个内联函数,用于将两个 __m512i 类型的寄存器按特定规则进行元素混合并返回结果
NPY_FINLINE npyv_u64x2 npyv_zip_u64(__m512i a, __m512i b)
{
    # 声明一个存放结果的结构体
    npyv_u64x2 r;
    # 将第一个结果元素混合计算并存入结果结构体的第一个成员中
    r.val[0] = _mm512_permutex2var_epi64(a, npyv_set_u64(0, 8, 1, 9, 2, 10, 3, 11), b);
    # 将第二个结果元素混合计算并存入结果结构体的第二个成员中
    r.val[1] = _mm512_permutex2var_epi64(a, npyv_set_u64(4, 12, 5, 13, 6, 14, 7, 15), b);
    # 返回混合后的结果结构体
    return r;
}
# 定义一个宏,用于有符号 64 位整数的元素混合,实际上调用了无符号版本的混合函数
#define npyv_zip_s64 npyv_zip_u64

# 定义一个内联函数,用于将两个 __m512i 类型的寄存器按特定规则进行元素混合并返回结果
NPY_FINLINE npyv_u8x2 npyv_zip_u8(__m512i a, __m512i b)
{
    # 声明一个存放结果的结构体
    npyv_u8x2 r;
    # 如果支持 AVX512VBMI 指令集,则按照特定的字节顺序混合计算结果
#ifdef NPY_HAVE_AVX512VBMI
    r.val[0] = _mm512_permutex2var_epi8(a,
        npyv_set_u8(0,  64, 1,  65, 2,  66, 3,  67, 4,  68, 5,  69, 6,  70, 7,  71,
                    8,  72, 9,  73, 10, 74, 11, 75, 12, 76, 13, 77, 14, 78, 15, 79,
                    16, 80, 17, 81, 18, 82, 19, 83, 20, 84, 21, 85, 22, 86, 23, 87,
                    24, 88, 25, 89, 26, 90, 27, 91, 28, 92, 29, 93, 30, 94, 31, 95), b);
    r.val[1] = _mm512_permutex2var_epi8(a,
        npyv_set_u8(32, 96,  33, 97,  34, 98,  35, 99,  36, 100, 37, 101, 38, 102, 39, 103,
                    40, 104, 41, 105, 42, 106, 43, 107, 44, 108, 45, 109, 46, 110, 47, 111,
                    48, 112, 49, 113, 50, 114, 51, 115, 52, 116, 53, 117, 54, 118, 55, 119,
                    56, 120, 57, 121, 58, 122, 59, 123, 60, 124, 61, 125, 62, 126, 63, 127), b);
#else
    #ifdef NPY_HAVE_AVX512BW
    # 否则,根据 AVX512BW 指令集进行字节的拆分和混合
    __m512i ab0 = _mm512_unpacklo_epi8(a, b);
    __m512i ab1 = _mm512_unpackhi_epi8(a, b);
    #else
    # 如果以上指令集都不支持,则调用其他适配的函数进行低位和高位的字节拆分
    __m512i ab0 = npyv__unpacklo_epi8(a, b);
    __m512i ab1 = npyv__unpackhi_epi8(a, b);
    #endif
    # 将拆分后的结果进行 64 位整数的混合计算
    r.val[0] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(0, 1, 8, 9, 2, 3, 10, 11), ab1);
    r.val[1] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(4, 5, 12, 13, 6, 7, 14, 15), ab1);
#endif
    # 返回混合后的结果结构体
    return r;
}
# 定义一个宏,用于有符号 8 位整数的元素混合,实际上调用了无符号版本的混合函数
#define npyv_zip_s8 npyv_zip_u8

# 定义一个内联函数,用于将两个 __m512i 类型的寄存器按特定规则进行元素混合并返回结果
NPY_FINLINE npyv_u16x2 npyv_zip_u16(__m512i a, __m512i b)
{
    # 声明一个存放结果的结构体
    npyv_u16x2 r;
    # 如果支持 AVX512BW 指令集,则按照特定的 16 位整数顺序混合计算结果
#ifdef NPY_HAVE_AVX512BW
    r.val[0] = _mm512_permutex2var_epi16(a,
        npyv_set_u16(0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39,
                     8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47), b);
    r.val[1] = _mm512_permutex2var_epi16(a,
        npyv_set_u16(16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55,
                     24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63), b);
#else
    # 否则,调用其他适配的函数进行低位和高位的 16 位整数的拆分
    __m512i ab0 = npyv__unpacklo_epi16(a, b);
    __m512i ab1 = npyv__unpackhi_epi16(a, b);
    # 将拆分后的结果进行 64 位整数的混合计算
    r.val[0] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(0, 1, 8, 9, 2, 3, 10, 11), ab1);
    r.val[1] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(4, 5, 12, 13, 6, 7, 14, 15), ab1);
#endif
    # 返回混合后的结果结构体
    return r;
}
# 定义一个宏,用于有符号 16 位整数的元素混合,实际上调用了无符号版本的混合函数
#define npyv_zip_s16 npyv_zip_u16

# 定义一个内联函数,用于将两个 __m512i 类型的寄存器按特定规则进行元素混合并返回结果
NPY_FINLINE npyv_u32x2 npyv_zip_u32(__m512i a, __m512i b)
{
    # 声明一个存放
// 定义一个内联函数,用于将两个 __m512 类型的向量 a 和 b 进行压缩合并成一个 npyv_f32x2 结构体返回
NPY_FINLINE npyv_f32x2 npyv_zip_f32(__m512 a, __m512 b)
{
    // 声明一个 npyv_f32x2 结构体 r,用于存储结果
    npyv_f32x2 r;
    // 使用 _mm512_permutex2var_ps 函数,根据给定的索引将向量 a 和 b 进行混合,结果存入 r.val[0]
    r.val[0] = _mm512_permutex2var_ps(a,
        npyv_set_u32(0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23), b);
    // 同上,将向量 a 和 b 进行混合,结果存入 r.val[1]
    r.val[1] = _mm512_permutex2var_ps(a,
        npyv_set_u32(8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31), b);
    // 返回结果结构体 r
    return r;
}

// 定义一个内联函数,用于将两个 __m512d 类型的双精度向量 a 和 b 进行压缩合并成一个 npyv_f64x2 结构体返回
NPY_FINLINE npyv_f64x2 npyv_zip_f64(__m512d a, __m512d b)
{
    // 声明一个 npyv_f64x2 结构体 r,用于存储结果
    npyv_f64x2 r;
    // 使用 _mm512_permutex2var_pd 函数,根据给定的索引将双精度向量 a 和 b 进行混合,结果存入 r.val[0]
    r.val[0] = _mm512_permutex2var_pd(a, npyv_set_u64(0, 8, 1, 9, 2, 10, 3, 11), b);
    // 同上,将双精度向量 a 和 b 进行混合,结果存入 r.val[1]
    r.val[1] = _mm512_permutex2var_pd(a, npyv_set_u64(4, 12, 5, 13, 6, 14, 7, 15), b);
    // 返回结果结构体 r
    return r;
}

// 定义一个内联函数,用于将两个 npyv_u8 类型的向量 ab0 和 ab1 进行解交错,结果存入 npyv_u8x2 结构体返回
// 如果支持 AVX512VBMI 指令集,则使用 _mm512_permutex2var_epi8 函数进行解交错,否则根据是否支持 AVX512BW 选择相应的处理方式
NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1)
{
    // 声明一个 npyv_u8x2 结构体 r,用于存储解交错后的结果
    npyv_u8x2 r;
#ifdef NPY_HAVE_AVX512VBMI
    // 如果支持 AVX512VBMI,则定义解交错所需的索引 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u8(
        0,  2,  4,   6,   8,   10,  12,  14,  16,  18,  20,  22,  24,  26,  28,  30,
        32, 34, 36,  38,  40,  42,  44,  46,  48,  50,  52,  54,  56,  58,  60,  62,
        64, 66, 68,  70,  72,  74,  76,  78,  80,  82,  84,  86,  88,  90,  92,  94,
        96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126
    );
    const __m512i idx_b = npyv_set_u8(
        1,  3,  5,   7,   9,   11,  13,  15,  17,  19,  21,  23,  25,  27,  29,  31,
        33, 35, 37,  39,  41,  43,  45,  47,  49,  51,  53,  55,  57,  59,  61,  63,
        65, 67, 69,  71,  73,  75,  77,  79,  81,  83,  85,  87,  89,  91,  93,  95,
        97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127
    );
    // 使用 _mm512_permutex2var_epi8 函数,根据 idx_a 和 idx_b 进行解交错,结果存入 r.val[0] 和 r.val[1]
    r.val[0] = _mm512_permutex2var_epi8(ab0, idx_a, ab1);
    r.val[1] = _mm512_permutex2var_epi8(ab0, idx_b, ab1);
#else
    // 如果不支持 AVX512VBMI,根据是否支持 AVX512BW 选择相应的处理方式
    #ifdef NPY_HAVE_AVX512BW
        // 如果支持 AVX512BW,则定义解交错所需的 idx
        const __m512i idx = npyv_set_u8(
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15
        );
        // 使用 _mm512_shuffle_epi8 函数,根据 idx 进行解交错,结果存入 abl 和 abh
        __m512i abl = _mm512_shuffle_epi8(ab0, idx);
        __m512i abh = _mm512_shuffle_epi8(ab1, idx);
    #else
        // 如果以上都不支持,则使用 AVX2 指令集处理
        const __m256i idx = _mm256_setr_epi8(
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
            0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15
        );
        // 使用 _mm256_shuffle_epi8 函数,根据 idx 对 ab0 和 ab1 进行解交错,结果存入对应的低位和高位部分
        __m256i abl_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab0),  idx);
        __m256i abl_hi = _mm256_shuffle_epi
    return r;


# 返回变量 r 的值作为函数的结果
#define npyv_unzip_s8 npyv_unzip_u8



NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1)
{
    npyv_u16x2 r;
#ifdef NPY_HAVE_AVX512BW
    // 如果支持 AVX-512 BW 指令集,则定义两个索引向量 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u16(
        0,  2,  4,  6,  8,  10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
        32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62
    );
    const __m512i idx_b = npyv_set_u16(
        1,  3,  5,  7,  9,  11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31,
        33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63
    );
    // 使用 permute 操作按照 idx_a 和 idx_b 重新排列输入的 ab0 和 ab1,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_epi16(ab0, idx_a, ab1);
    r.val[1] = _mm512_permutex2var_epi16(ab0, idx_b, ab1);
#else
    // 如果不支持 AVX-512 BW 指令集,则定义一个字节级别的索引向量 idx
    const __m256i idx = _mm256_setr_epi8(
        0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15,
        0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15
    );
    // 对输入向量 ab0 和 ab1 进行字节级别的 shuffle 操作,以得到结果 r
    __m256i abl_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab0),  idx);
    __m256i abl_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab0), idx);
    __m256i abh_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab1),  idx);
    __m256i abh_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab1), idx);
    __m512i abl = npyv512_combine_si256(abl_lo, abl_hi);
    __m512i abh = npyv512_combine_si256(abh_lo, abh_hi);

    // 定义两个 64 位整数型的索引向量 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14);
    const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15);
    // 使用 permute 操作按照 idx_a 和 idx_b 重新排列 abl 和 abh,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_epi64(abl, idx_a, abh);
    r.val[1] = _mm512_permutex2var_epi64(abl, idx_b, abh);
#endif
    return r;
}



#define npyv_unzip_s16 npyv_unzip_u16



NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1)
{
    // 定义两个 32 位整数型的索引向量 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u32(
        0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
    );
    const __m512i idx_b = npyv_set_u32(
        1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
    );
    npyv_u32x2 r;
    // 使用 permute 操作按照 idx_a 和 idx_b 重新排列输入的 ab0 和 ab1,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_epi32(ab0, idx_a, ab1);
    r.val[1] = _mm512_permutex2var_epi32(ab0, idx_b, ab1);
    return r;
}



#define npyv_unzip_s32 npyv_unzip_u32



NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1)
{
    // 定义两个 64 位整数型的索引向量 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14);
    const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15);
    npyv_u64x2 r;
    // 使用 permute 操作按照 idx_a 和 idx_b 重新排列输入的 ab0 和 ab1,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_epi64(ab0, idx_a, ab1);
    r.val[1] = _mm512_permutex2var_epi64(ab0, idx_b, ab1);
    return r;
}



#define npyv_unzip_s64 npyv_unzip_u64



NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab0, npyv_f32 ab1)
{
    // 定义两个 32 位整数型的索引向量 idx_a 和 idx_b
    const __m512i idx_a = npyv_set_u32(
        0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
    );
    const __m512i idx_b = npyv_set_u32(
        1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
    );
    npyv_f32x2 r;
    // 使用 permute 操作按照 idx_a 和 idx_b 重新排列输入的 ab0 和 ab1,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_ps(ab0, idx_a, ab1);
    r.val[1] = _mm512_permutex2var_ps(ab0, idx_b, ab1);
    return r;
}



NPY_FINLINE npyv_f64x2 npyv_unzip_f64(npyv_f64 ab0, npyv_f64 ab1)
{
    // 定义两个 64 位整数型的索引向量 idx_a
    const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14);
    npyv_f64x2 r;
    // 使用 permute 操作按照 idx_a 重新排列输入的 ab0 和 ab1,存储到结果 r 中
    r.val[0] = _mm512_permutex2var_pd(ab0, idx_a, ab1);
    return r;
}
    // 创建一个包含固定顺序的无符号64位整数的__m512i类型变量,用于索引操作
    const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15);
    // 创建一个双精度浮点数向量变量r,包含两个元素
    npyv_f64x2 r;
    // 使用_mm512_permutex2var_pd函数对两个双精度浮点数向量ab0和ab1进行按索引混合操作,并将结果存入r的第一个元素
    r.val[0] = _mm512_permutex2var_pd(ab0, idx_a, ab1);
    // 使用_mm512_permutex2var_pd函数对两个双精度浮点数向量ab0和ab1进行按固定索引顺序(idx_b)混合操作,并将结果存入r的第二个元素
    r.val[1] = _mm512_permutex2var_pd(ab0, idx_b, ab1);
    // 返回双精度浮点数向量r
    return r;
#ifdef NPY_HAVE_AVX512BW
    // 如果编译器支持 AVX-512BW 指令集,则使用 AVX-512 实现反转每个 64 位 lane 的操作
    const __m512i idx = npyv_set_u8(
        // 创建 AVX-512 需要的索引,用于反转每个 64 位 lane 中的元素
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8,
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8,
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8,
        7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8
    );
    // 使用 AVX-512 指令集中的 shuffle 操作进行反转操作
    return _mm512_shuffle_epi8(a, idx);
#else
    // 如果编译器不支持 AVX-512BW 指令集,则使用 AVX2 实现反转每个 64 位 lane 的操作
    const __m256i idx = _mm256_setr_epi8(
        // 创建 AVX2 需要的索引,用于反转每个 64 位 lane 中的元素
        7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8,
        7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
    );
    // 分别对高低 256 位执行 shuffle 操作,然后将结果合并
    __m256i lo = _mm256_shuffle_epi8(npyv512_lower_si256(a),  idx);
    __m256i hi = _mm256_shuffle_epi8(npyv512_higher_si256(a), idx);
    return npyv512_combine_si256(lo, hi);
#endif
}

.\numpy\numpy\_core\src\common\simd\avx512\utils.h

#ifndef NPY_SIMD
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_AVX512_UTILS_H
#define _NPY_SIMD_AVX512_UTILS_H

// 定义将__m512i类型转换为__m256i类型的宏
#define npyv512_lower_si256 _mm512_castsi512_si256
// 定义将__m512类型转换为__m256类型的宏
#define npyv512_lower_ps256 _mm512_castps512_ps256
// 定义将__m512d类型转换为__m256d类型的宏
#define npyv512_lower_pd256 _mm512_castpd512_pd256

// 定义从__m512i类型中提取高128位__m256i类型的宏
#define npyv512_higher_si256(A) _mm512_extracti64x4_epi64(A, 1)
// 定义从__m512d类型中提取高128位__m256d类型的宏
#define npyv512_higher_pd256(A) _mm512_extractf64x4_pd(A, 1)

#ifdef NPY_HAVE_AVX512DQ
    // 如果支持 AVX512DQ,则定义从__m512类型中提取高256位__m256类型的宏
    #define npyv512_higher_ps256(A) _mm512_extractf32x8_ps(A, 1)
#else
    // 如果不支持 AVX512DQ,则通过组合操作从__m512类型中提取高256位__m256类型
    #define npyv512_higher_ps256(A) \
        _mm256_castsi256_ps(_mm512_extracti64x4_epi64(_mm512_castps_si512(A), 1))
#endif

// 定义将两个__m256i类型合并为一个__m512i类型的宏
#define npyv512_combine_si256(A, B) _mm512_inserti64x4(_mm512_castsi256_si512(A), B, 1)
// 定义将两个__m256d类型合并为一个__m512d类型的宏
#define npyv512_combine_pd256(A, B) _mm512_insertf64x4(_mm512_castpd256_pd512(A), B, 1)

#ifdef NPY_HAVE_AVX512DQ
    // 如果支持 AVX512DQ,则定义将两个__m256类型合并为一个__m512类型的宏
    #define npyv512_combine_ps256(A, B) _mm512_insertf32x8(_mm512_castps256_ps512(A), B, 1)
#else
    // 如果不支持 AVX512DQ,则通过组合操作将两个__m256类型合并为一个__m512类型
    #define npyv512_combine_ps256(A, B) \
        _mm512_castsi512_ps(npyv512_combine_si256(_mm256_castps_si256(A), _mm256_castps_si256(B)))
#endif

// 定义宏,用于从AVX2转换到AVX512的单参数函数实现,返回__m512i类型
#define NPYV_IMPL_AVX512_FROM_AVX2_1ARG(FN_NAME, INTRIN) \
    NPY_FINLINE __m512i FN_NAME(__m512i a)               \
    {                                                    \
        __m256i l_a  = npyv512_lower_si256(a);           \
        __m256i h_a  = npyv512_higher_si256(a);          \
        l_a = INTRIN(l_a);                               \
        h_a = INTRIN(h_a);                               \
        return npyv512_combine_si256(l_a, h_a);          \
    }

// 定义宏,用于从AVX2转换到AVX512的单参数函数实现,返回__m512类型
#define NPYV_IMPL_AVX512_FROM_AVX2_PS_1ARG(FN_NAME, INTRIN) \
    NPY_FINLINE __m512 FN_NAME(__m512 a)                    \
    {                                                       \
        __m256 l_a  = npyv512_lower_ps256(a);               \
        __m256 h_a  = npyv512_higher_ps256(a);              \
        l_a = INTRIN(l_a);                                  \
        h_a = INTRIN(h_a);                                  \
        return npyv512_combine_ps256(l_a, h_a);             \
    }

// 定义宏,用于从AVX2转换到AVX512的单参数函数实现,返回__m512d类型
#define NPYV_IMPL_AVX512_FROM_AVX2_PD_1ARG(FN_NAME, INTRIN) \
    NPY_FINLINE __m512d FN_NAME(__m512d a)                  \
    {                                                       \
        __m256d l_a  = npyv512_lower_pd256(a);              \
        __m256d h_a  = npyv512_higher_pd256(a);             \
        l_a = INTRIN(l_a);                                  \
        h_a = INTRIN(h_a);                                  \
        return npyv512_combine_pd256(l_a, h_a);             \
    }

// 定义宏,用于从AVX2转换到AVX512的双参数函数实现,返回__m512i类型
#define NPYV_IMPL_AVX512_FROM_AVX2_2ARG(FN_NAME, INTRIN) \
    NPY_FINLINE __m512i FN_NAME(__m512i a, __m512i b)    \
    {
        # 提取给定 AVX-512 512位向量 a 的低256位部分
        __m256i l_a  = npyv512_lower_si256(a);
        # 提取给定 AVX-512 512位向量 a 的高256位部分
        __m256i h_a  = npyv512_higher_si256(a);
        # 提取给定 AVX-512 512位向量 b 的低256位部分
        __m256i l_b  = npyv512_lower_si256(b);
        # 提取给定 AVX-512 512位向量 b 的高256位部分
        __m256i h_b  = npyv512_higher_si256(b);
        # 对 l_a 和 l_b 进行特定的 INTRIN 操作,结果保存在 l_a 中
        l_a = INTRIN(l_a, l_b);
        # 对 h_a 和 h_b 进行特定的 INTRIN 操作,结果保存在 h_a 中
        h_a = INTRIN(h_a, h_b);
        # 将修改后的 l_a 和 h_a 合并成一个 AVX-512 512位向量,并返回结果
        return npyv512_combine_si256(l_a, h_a);
    }
#define NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(FN_NAME, INTRIN) \
    // 定义一个内联函数 FN_NAME,接受两个 __m512 类型的参数 a 和 b,返回结果为 __m512 类型
    NPY_FINLINE __m512 FN_NAME(__m512 a, __m512 b)           \
    {                                                        \
        // 将 a 和 b 转换为 __m512i 类型,然后调用 INTRIN 进行处理,最后将结果转换回 __m512 类型并返回
        return _mm512_castsi512_ps(INTRIN(                   \
            _mm512_castps_si512(a), _mm512_castps_si512(b)   \
        ));                                                  \
    }

#define NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(FN_NAME, INTRIN) \
    // 定义一个内联函数 FN_NAME,接受两个 __m512d 类型的参数 a 和 b,返回结果为 __m512d 类型
    NPY_FINLINE __m512d FN_NAME(__m512d a, __m512d b)        \
    {                                                        \
        // 将 a 和 b 转换为 __m512i 类型,然后调用 INTRIN 进行处理,最后将结果转换回 __m512d 类型并返回
        return _mm512_castsi512_pd(INTRIN(                   \
            _mm512_castpd_si512(a), _mm512_castpd_si512(b)   \
        ));                                                  \
    }

#ifndef NPY_HAVE_AVX512BW
    // 如果没有 AVX512BW 扩展,则使用 AVX2 的 _mm256_packs_epi16 作为 npyv512_packs_epi16 的定义
    NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv512_packs_epi16,  _mm256_packs_epi16)
#else
    // 否则直接定义 npyv512_packs_epi16 为 _mm512_packs_epi16
    #define npyv512_packs_epi16 _mm512_packs_epi16
#endif

NPY_FINLINE __m256i npyv512_pack_lo_hi(__m512i a) {
    // 提取 a 的低 256 位和高 256 位分别存入 lo 和 hi
    __m256i lo = npyv512_lower_si256(a);
    __m256i hi = npyv512_higher_si256(a);
    // 使用 _mm256_packs_epi32 将 lo 和 hi 中的每对相邻元素进行有符号 16 位整数打包操作,返回结果
    return _mm256_packs_epi32(lo, hi);
}

#endif // _NPY_SIMD_AVX512_UTILS_H

.\numpy\numpy\_core\src\common\simd\emulate_maskop.h

/**
 * This header is used internally by all current supported SIMD extensions,
 * except for AVX512.
 */
#ifndef NPY_SIMD
    #error "Not a standalone header, use simd/simd.h instead"
#endif

#ifndef _NPY_SIMD_EMULATE_MASKOP_H
#define _NPY_SIMD_EMULATE_MASKOP_H

/**
 * Implements conditional addition and subtraction.
 * e.g. npyv_ifadd_f32(mask, a, b, c) -> mask ? a + b : c
 * e.g. npyv_ifsub_f32(mask, a, b, c) -> mask ? a - b : c
 */
#define NPYV_IMPL_EMULATE_MASK_ADDSUB(SFX, BSFX)              \
    NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX                   \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \
    {                                                         \
        npyv_##SFX add = npyv_add_##SFX(a, b);                \
        return npyv_select_##SFX(m, add, c);                  \
    }                                                         \
    NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX                   \
    (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \
    {                                                         \
        npyv_##SFX sub = npyv_sub_##SFX(a, b);                \
        return npyv_select_##SFX(m, sub, c);                  \
    }

/**
 * Conditional addition and subtraction implementation for unsigned and signed 8-bit integers,
 * 16-bit integers, 32-bit integers, and 64-bit integers.
 */
NPYV_IMPL_EMULATE_MASK_ADDSUB(u8,  b8)
NPYV_IMPL_EMULATE_MASK_ADDSUB(s8,  b8)
NPYV_IMPL_EMULATE_MASK_ADDSUB(u16, b16)
NPYV_IMPL_EMULATE_MASK_ADDSUB(s16, b16)
NPYV_IMPL_EMULATE_MASK_ADDSUB(u32, b32)
NPYV_IMPL_EMULATE_MASK_ADDSUB(s32, b32)
NPYV_IMPL_EMULATE_MASK_ADDSUB(u64, b64)
NPYV_IMPL_EMULATE_MASK_ADDSUB(s64, b64)

#if NPY_SIMD_F32
    /**
     * Conditional floating-point division implementation.
     * e.g. npyv_ifdiv_f32(mask, a, b, c) -> mask ? a / b : c
     */
    NPY_FINLINE npyv_f32
    npyv_ifdiv_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b, npyv_f32 c)
    {
        const npyv_f32 one = npyv_setall_f32(1.0f);
        npyv_f32 div = npyv_div_f32(a, npyv_select_f32(m, b, one));
        return npyv_select_f32(m, div, c);
    }

    /**
     * Conditional floating-point division implementation.
     * e.g. npyv_ifdivz_f32(mask, a, b) -> mask ? a / b : 0
     */
    NPY_FINLINE npyv_f32
    npyv_ifdivz_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b)
    {
        const npyv_f32 zero = npyv_zero_f32();
        return npyv_ifdiv_f32(m, a, b, zero);
    }
#endif

#if NPY_SIMD_F64
    /**
     * Conditional double-precision floating-point division implementation.
     * e.g. npyv_ifdiv_f64(mask, a, b, c) -> mask ? a / b : c
     */
    NPY_FINLINE npyv_f64
    npyv_ifdiv_f64(npyv_b64 m, npyv_f64 a, npyv_f64 b, npyv_f64 c)
    {
        const npyv_f64 one = npyv_setall_f64(1.0);
        npyv_f64 div = npyv_div_f64(a, npyv_select_f64(m, b, one));
        return npyv_select_f64(m, div, c);
    }

    /**
     * Conditional double-precision floating-point division implementation.
     * e.g. npyv_ifdivz_f64(mask, a, b) -> mask ? a / b : 0
     */
    NPY_FINLINE npyv_f64
    npyv_ifdivz_f64(npyv_b64 m, npyv_f64 a, npyv_f64 b)
    {
        const npyv_f64 zero = npyv_zero_f64();
        return npyv_ifdiv_f64(m, a, b, zero);
    }
#endif

#endif // _NPY_SIMD_EMULATE_MASKOP_H


注释说明了每个宏定义和条件分支函数的作用,以及它们如何实现条件操作(条件加减和条件除法)的功能。

.\numpy\numpy\_core\src\common\simd\intdiv.h

/**
 * This header implements `npyv_divisor_*` intrinsics used for computing the parameters
 * of fast integer division, while division intrinsics `npyv_divc_*` are defined in
 * {extension}/arithmetic.h.
 */
#ifndef NPY_SIMD
    #error "Not a standalone header, use simd/simd.h instead"
#endif
#ifndef _NPY_SIMD_INTDIV_H
#define _NPY_SIMD_INTDIV_H
/**
 * bit-scan reverse for non-zeros. returns the index of the highest set bit.
 * equivalent to floor(log2(a))
 */
#ifdef _MSC_VER
    #include <intrin.h> // _BitScanReverse
#endif
/**
 * Inline function to find the index of the highest set bit in a 32-bit unsigned integer.
 * Uses compiler-specific intrinsics or assembly for efficient implementation.
 */
NPY_FINLINE unsigned npyv__bitscan_revnz_u32(npy_uint32 a)
{
    assert(a > 0); // Ensure input 'a' is non-zero due to the use of __builtin_clz
#if defined(NPY_HAVE_SSE2) && defined(_MSC_VER)
    unsigned long rl;
    (void)_BitScanReverse(&rl, (unsigned long)a); // Use _BitScanReverse for MSC compiler
    r = (unsigned)rl;
#elif defined(NPY_HAVE_SSE2) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) \
    &&  (defined(NPY_CPU_X86) || defined(NPY_CPU_AMD64))
    __asm__("bsr %1, %0" : "=r" (r) : "r"(a)); // Use inline assembly for GCC, Clang, or Intel Compiler on x86/x86_64
#elif defined(__GNUC__) || defined(__clang__)
    r = 31 - __builtin_clz(a); // Fallback to built-in function __builtin_clz for other architectures
#else
    r = 0; // Default to 0 if no specific implementation found
    while (a >>= 1) {
        r++;
    }
#endif
    return r; // Return the index of the highest set bit
}
/**
 * Inline function to find the index of the highest set bit in a 64-bit unsigned integer.
 * Uses compiler-specific intrinsics or assembly for efficient implementation.
 */
NPY_FINLINE unsigned npyv__bitscan_revnz_u64(npy_uint64 a)
{
    assert(a > 0); // Ensure input 'a' is non-zero due to the use of __builtin_clzll
#if defined(_M_AMD64) && defined(_MSC_VER)
    unsigned long rl;
    (void)_BitScanReverse64(&rl, a); // Use _BitScanReverse64 for MSC compiler on AMD64
    return (unsigned)rl;
#elif defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
    npy_uint64 r;
    __asm__("bsrq %1, %0" : "=r"(r) : "r"(a)); // Use inline assembly for GCC, Clang, or Intel Compiler on x86_64
    return (unsigned)r;
#elif defined(__GNUC__) || defined(__clang__)
    return 63 - __builtin_clzll(a); // Fallback to built-in function __builtin_clzll for other architectures
#else
    npy_uint64 a_hi = a >> 32;
    if (a_hi == 0) {
        return npyv__bitscan_revnz_u32((npy_uint32)a); // Handle the upper 32 bits if they are zero
    }
    return 32 + npyv__bitscan_revnz_u32((npy_uint32)a_hi); // Calculate the index of highest set bit for 64-bit 'a'
#endif
}
/**
 * Inline function to divide a 128-bit unsigned integer by a 64-bit divisor,
 * returning the quotient.
 *
 * This function ensures the divisor is greater than 1.
 */
NPY_FINLINE npy_uint64 npyv__divh128_u64(npy_uint64 high, npy_uint64 divisor)
{
    assert(divisor > 1); // Ensure divisor is greater than 1 for valid division
    npy_uint64 quotient;
#if defined(_M_X64) && defined(_MSC_VER) && _MSC_VER >= 1920 && !defined(__clang__)
    npy_uint64 remainder;
    quotient = _udiv128(high, 0, divisor, &remainder); // Use _udiv128 for MSC compiler versions >= 1920
    (void)remainder;
#elif defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
    __asm__("divq %[d]" : "=a"(quotient) : [d] "r"(divisor), "a"(0), "d"(high)); // Use inline assembly for GCC, Clang, or Intel Compiler on x86_64
#elif defined(__SIZEOF_INT128__)
    quotient = (npy_uint64)((((__uint128_t)high) << 64) / divisor); // Use __uint128_t for 128-bit integers if available
#else
    /**
     * Minified version based on Donald Knuth’s Algorithm D (Division of nonnegative integers),
     * and Generic implementation in Hacker’s Delight.
     *
     * See https://skanthak.homepage.t-online.de/division.html
     * with respect to the license of the Hacker's Delight book
     * (https://web.archive.org/web/20190408122508/http://www.hackersdelight.org/permissions.htm)
     */
    // 计算使得除数归一化的位移量
    unsigned ldz = 63 - npyv__bitscan_revnz_u64(divisor);
    // 对除数进行归一化处理
    divisor <<= ldz;
    high    <<= ldz;
    // 将除数分解为两个32位的数字
    npy_uint32 divisor_hi  = divisor >> 32;
    npy_uint32 divisor_lo  = divisor & 0xFFFFFFFF;
    // 计算高位商数数字
    npy_uint64 quotient_hi = high / divisor_hi;
    npy_uint64 remainder   = high - divisor_hi * quotient_hi;
    npy_uint64 base32      = 1ULL << 32;
    // 使用循环计算更低位的商数数字
    while (quotient_hi >= base32 || quotient_hi*divisor_lo > base32*remainder) {
        --quotient_hi;
        remainder += divisor_hi;
        if (remainder >= base32) {
            break;
        }
    }
    // 计算被除数的数字对
    npy_uint64 dividend_pairs = base32*high - divisor*quotient_hi;
    // 计算较低零的第二个商数数字
    npy_uint32 quotient_lo = (npy_uint32)(dividend_pairs / divisor_hi);
    quotient = base32*quotient_hi + quotient_lo;
#endif
    return quotient;
}
// Initializing divisor parameters for unsigned 8-bit division
NPY_FINLINE npyv_u8x3 npyv_divisor_u8(npy_uint8 d)
{
    unsigned l, l2, sh1, sh2, m;
    switch (d) {
    case 0: // LCOV_EXCL_LINE
        // 处理可能的除零情况,对于 x86 架构,GCC 插入 `ud2` 指令以替代
        // 让硬件/CPU 陷入的行为,这会导致非法指令异常。
        // 'volatile' 应该抑制此行为,允许我们引发硬件/CPU 算术异常。
        m = sh1 = sh2 = 1 / ((npy_uint8 volatile *)&d)[0];
        break;
    case 1:
        m = 1; sh1 = sh2 = 0;
        break;
    case 2:
        m = 1; sh1 = 1; sh2 = 0;
        break;
    default:
        l   = npyv__bitscan_revnz_u32(d - 1) + 1;  // 计算 ceil(log2(d))
        l2  = (npy_uint8)(1 << l);                 // 2^l,若 l = 8 则溢出为 0
        m   = ((npy_uint16)((l2 - d) << 8)) / d + 1; // 计算乘数
        sh1 = 1;  sh2 = l - 1;                     // 计算位移量
    }
    npyv_u8x3 divisor;
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    divisor.val[0] = npyv_setall_u16(m);
    divisor.val[1] = npyv_set_u8(sh1);
    divisor.val[2] = npyv_set_u8(sh2);
#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
    divisor.val[0] = npyv_setall_u8(m);
    divisor.val[1] = npyv_setall_u8(sh1);
    divisor.val[2] = npyv_setall_u8(sh2);
#elif defined(NPY_HAVE_NEON)
    divisor.val[0] = npyv_setall_u8(m);
    divisor.val[1] = npyv_reinterpret_u8_s8(npyv_setall_s8(-sh1));
    divisor.val[2] = npyv_reinterpret_u8_s8(npyv_setall_s8(-sh2));
#else
    #error "please initialize the shifting operand for the new architecture"
#endif
    return divisor;
}
// Initializing divisor parameters for signed 8-bit division
NPY_FINLINE npyv_s16x3 npyv_divisor_s16(npy_int16 d);
NPY_FINLINE npyv_s8x3 npyv_divisor_s8(npy_int8 d)
{
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    npyv_s16x3 p = npyv_divisor_s16(d);
    npyv_s8x3 r;
    r.val[0] = npyv_reinterpret_s8_s16(p.val[0]);
    r.val[1] = npyv_reinterpret_s8_s16(p.val[1]);
    r.val[2] = npyv_reinterpret_s8_s16(p.val[2]);
    return r;
#else
    int d1 = abs(d);
    int sh, m;
    if (d1 > 1) {
        sh = (int)npyv__bitscan_revnz_u32(d1-1); // 计算 ceil(log2(abs(d))) - 1
        m = (1 << (8 + sh)) / d1 + 1;            // 计算乘数
    }
    else if (d1 == 1) {
        sh = 0; m = 1;
    }
    else {
        // 对于 d == 0,引发算术异常
        sh = m = 1 / ((npy_int8 volatile *)&d)[0]; // LCOV_EXCL_LINE
    }
    npyv_s8x3 divisor;
    divisor.val[0] = npyv_setall_s8(m);
    divisor.val[2] = npyv_setall_s8(d < 0 ? -1 : 0);
    #if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
        divisor.val[1] = npyv_setall_s8(sh);
    #elif defined(NPY_HAVE_NEON)
        divisor.val[1] = npyv_setall_s8(-sh);
    #else
        #error "please initialize the shifting operand for the new architecture"
    #endif
    return divisor;
#endif
}
// Initializing divisor parameters for unsigned 16-bit division
NPY_FINLINE npyv_u16x3 npyv_divisor_u16(npy_uint16 d)
{
    unsigned l, l2, sh1, sh2, m;
    switch (d) {
    case 0: // LCOV_EXCL_LINE
        // 若 d 等于 0,抛出算术异常
        m = sh1 = sh2 = 1 / ((npy_uint16 volatile *)&d)[0];
        break;
    case 1:
        m = 1; sh1 = sh2 = 0;
        break;
    case 2:
        m = 1; sh1 = 1; sh2 = 0;
        break;
    default:
        l   = npyv__bitscan_revnz_u32(d - 1) + 1; // 计算 ceil(log2(d))
        l2  = (npy_uint16)(1 << l);               // 2^l,若 l = 16 则溢出为 0
        m   = ((l2 - d) << 16) / d + 1;           // 计算乘数
        sh1 = 1;  sh2 = l - 1;                    // 计算移位数
    }
    npyv_u16x3 divisor;
    divisor.val[0] = npyv_setall_u16(m);
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    divisor.val[1] = npyv_set_u16(sh1);
    divisor.val[2] = npyv_set_u16(sh2);
#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
    divisor.val[1] = npyv_setall_u16(sh1);
    divisor.val[2] = npyv_setall_u16(sh2);
#elif defined(NPY_HAVE_NEON)
    divisor.val[1] = npyv_reinterpret_u16_s16(npyv_setall_s16(-sh1));
    divisor.val[2] = npyv_reinterpret_u16_s16(npyv_setall_s16(-sh2));
#else
    #error "please initialize the shifting operand for the new architecture"
#endif
    return divisor;
}



// 为有符号 16 位整数除法初始化除数参数
NPY_FINLINE npyv_s16x3 npyv_divisor_s16(npy_int16 d)
{
    int d1 = abs(d);
    int sh, m;
    if (d1 > 1) {
        sh = (int)npyv__bitscan_revnz_u32(d1 - 1); // 计算 ceil(log2(abs(d))) - 1
        m = (1 << (16 + sh)) / d1 + 1;             // 计算乘数
    }
    else if (d1 == 1) {
        sh = 0; m = 1;
    }
    else {
        // 若 d 等于 0,抛出算术异常
        sh = m = 1 / ((npy_int16 volatile *)&d)[0]; // LCOV_EXCL_LINE
    }
    npyv_s16x3 divisor;
    divisor.val[0] = npyv_setall_s16(m);
    divisor.val[2] = npyv_setall_s16(d < 0 ? -1 : 0); // 设置除数的符号
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    divisor.val[1] = npyv_set_s16(sh);
#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
    divisor.val[1] = npyv_setall_s16(sh);
#elif defined(NPY_HAVE_NEON)
    divisor.val[1] = npyv_setall_s16(-sh);
#else
    #error "please initialize the shifting operand for the new architecture"
#endif
    return divisor;
}



// 为无符号 32 位整数除法初始化除数参数
NPY_FINLINE npyv_u32x3 npyv_divisor_u32(npy_uint32 d)
{
    npy_uint32 l, l2, sh1, sh2, m;
    switch (d) {
    case 0: // LCOV_EXCL_LINE
        // 若 d 等于 0,抛出算术异常
        m = sh1 = sh2 = 1 / ((npy_uint32 volatile *)&d)[0]; // LCOV_EXCL_LINE
        break;
    case 1:
        m = 1; sh1 = sh2 = 0;
        break;
    case 2:
        m = 1; sh1 = 1; sh2 = 0;
        break;


这些注释解释了每个函数和代码段的作用,确保了读者能理解其背后的逻辑和功能。
    # 对于默认情况下的处理分支(switch-case结构),计算最小位数l,即ceil(log2(d))
    l   = npyv__bitscan_revnz_u32(d - 1) + 1;     // ceil(log2(d))
    # 计算2^l,注意如果l=32可能会导致溢出为0
    l2  = (npy_uint32)(1ULL << l);                // 2^l, overflow to 0 if l = 32
    # 计算乘数m,使用(l2 - d) * 2^32 / d + 1得到的结果
    m   = ((npy_uint64)(l2 - d) << 32) / d + 1;   // multiplier
    # 设置sh1为1,sh2为l - 1,这是用于后续的位移操作的位移计数
    sh1 = 1;  sh2 = l - 1;                        // shift counts
}
# 创建一个包含三个32位无符号整数的向量,所有元素初始化为m
npyv_u32x3 divisor;
divisor.val[0] = npyv_setall_u32(m);
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    // 如果支持 SSE2 或者更高版本的 SIMD 指令集,设置除数的第二和第三元素为 sh1 和 sh2
    divisor.val[1] = npyv_set_u32(sh1);
    divisor.val[2] = npyv_set_u32(sh2);
#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
    // 如果支持 VSX2 或者 VX 指令集,设置除数的第二和第三元素为 sh1 和 sh2 的全局设定
    divisor.val[1] = npyv_setall_u32(sh1);
    divisor.val[2] = npyv_setall_u32(sh2);
#elif defined(NPY_HAVE_NEON)
    // 如果支持 NEON 指令集,设置除数的第二和第三元素为 -sh1 和 -sh2 的重新解释的无符号整数
    divisor.val[1] = npyv_reinterpret_u32_s32(npyv_setall_s32(-sh1));
    divisor.val[2] = npyv_reinterpret_u32_s32(npyv_setall_s32(-sh2));
#else
    #error "please initialize the shifting operand for the new architecture"
#endif
    // 返回初始化后的除数
    return divisor;
}
// 初始化有符号 32 位整数除法的除数参数
NPY_FINLINE npyv_s32x3 npyv_divisor_s32(npy_int32 d)
{
    npy_int32 d1 = abs(d);
    npy_int32 sh, m;
    // 处理绝对值溢出的情况
    if ((npy_uint32)d == 0x80000000U) {
        m = 0x80000001;
        sh = 30;
    }
    else if (d1 > 1) {
        // 计算 d1 的对数向上取整减去 1,作为 sh 的值
        sh = npyv__bitscan_revnz_u32(d1 - 1); // ceil(log2(abs(d))) - 1
        // 计算乘数 m
        m =  (1ULL << (32 + sh)) / d1 + 1;    // multiplier
    }
    else if (d1 == 1) {
        sh = 0; m = 1;
    }
    else {
        // 对于 d == 0,抛出算术异常
        sh = m = 1 / ((npy_int32 volatile *)&d)[0]; // LCOV_EXCL_LINE
    }
    npyv_s32x3 divisor;
    // 设置除数的第一个元素为 m
    divisor.val[0] = npyv_setall_s32(m);
    // 设置除数的第三个元素为 d 的符号
    divisor.val[2] = npyv_setall_s32(d < 0 ? -1 : 0); // sign of divisor
#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    // 如果支持 SSE2 或者更高版本的 SIMD 指令集,设置除数的第二元素为 sh
    divisor.val[1] = npyv_set_s32(sh);
#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX)
    // 如果支持 VSX2 或者 VX 指令集,设置除数的第二元素为 sh 的全局设定
    divisor.val[1] = npyv_setall_s32(sh);
#elif defined(NPY_HAVE_NEON)
    // 如果支持 NEON 指令集,设置除数的第二元素为 -sh 的全局设定
    divisor.val[1] = npyv_setall_s32(-sh);
#else
    #error "please initialize the shifting operand for the new architecture"
#endif
    // 返回初始化后的除数
    return divisor;
}
// 初始化无符号 64 位整数除法的除数参数
NPY_FINLINE npyv_u64x3 npyv_divisor_u64(npy_uint64 d)
{
    npyv_u64x3 divisor;
#if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) || defined(NPY_HAVE_NEON)
    // 如果支持 VSX2、VX 或者 NEON 指令集,设置除数的第一个元素为 d 的全局设定
    divisor.val[0] = npyv_setall_u64(d);
#else
    npy_uint64 l, l2, sh1, sh2, m;
    switch (d) {
    case 0: // LCOV_EXCL_LINE
        // 对于 d == 0,抛出算术异常
        m = sh1 = sh2 = 1 / ((npy_uint64 volatile *)&d)[0]; // LCOV_EXCL_LINE
        break;
    case 1:
        m = 1; sh1 = sh2 = 0;
        break;
    case 2:
        m = 1; sh1 = 1; sh2 = 0;
        break;
    default:
        // 计算 d 的对数向上取整加 1,作为 l
        l = npyv__bitscan_revnz_u64(d - 1) + 1;      // ceil(log2(d))
        // 计算 2^l,作为 l2
        l2 = l < 64 ? 1ULL << l : 0;                 // 2^l
        // 计算乘数 m
        m = npyv__divh128_u64(l2 - d, d) + 1;        // multiplier
        // 设置移位计数 sh1 和 sh2
        sh1 = 1;  sh2 = l - 1;                       // shift counts
    }
    // 设置除数的第一个元素为 m
    divisor.val[0] = npyv_setall_u64(m);
    #ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
        // 如果支持 SSE2 或者更高版本的 SIMD 指令集,设置除数的第二和第三元素为 sh1 和 sh2
        divisor.val[1] = npyv_set_u64(sh1);
        divisor.val[2] = npyv_set_u64(sh2);
    #else
        #error "please initialize the shifting operand for the new architecture"
    #endif
#endif
    // 返回初始化后的除数
    return divisor;
}
// 初始化有符号 64 位整数除法的除数参数
NPY_FINLINE npyv_s64x3 npyv_divisor_s64(npy_int64 d)
{
    // 定义一个名为 divisor 的变量,其类型为 npyv_s64x3
    npyv_s64x3 divisor;
#if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) || defined(NPY_HAVE_NEON)
    // 设置除数向量的第一个元素为 d 的值
    divisor.val[0] = npyv_setall_s64(d);
    // 如果 d 是 -1,则设置除数向量的第二个元素为全 1,否则为全 0
    divisor.val[1] = npyv_cvt_s64_b64(
        npyv_cmpeq_s64(npyv_setall_s64(-1), divisor.val[0])
    );
#else
    npy_int64 d1 = llabs(d);
    npy_int64 sh, m;
    // 处理 abs(d) 溢出的情况
    if ((npy_uint64)d == 0x8000000000000000ULL) {
        m = 0x8000000000000001LL; // 设置特定溢出情况下的修正值
        sh = 62; // 对应的位移量
    }
    else if (d1 > 1) {
        sh = npyv__bitscan_revnz_u64(d1 - 1);       // 计算 ceil(log2(abs(d))) - 1
        m  = npyv__divh128_u64(1ULL << sh, d1) + 1; // 计算乘法因子
    }
    else if (d1 == 1) {
        sh = 0; m = 1; // 处理 d = 1 的情况
    }
    else {
        // 对于 d == 0,抛出算术异常
        sh = m = 1 / ((npy_int64 volatile *)&d)[0]; // LCOV_EXCL_LINE
        // 上面的语句标记为不计算覆盖率,处理 d = 0 的特殊情况
    }
    // 设置除数向量的第一个元素为 m
    divisor.val[0] = npyv_setall_s64(m);
    // 设置除数向量的第二个元素为 d 的符号位,如果 d < 0 则为 -1,否则为 0
    divisor.val[2] = npyv_setall_s64(d < 0 ? -1 : 0);  // 符号位
    #ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512
    divisor.val[1] = npyv_set_s64(sh); // 设置除数向量的第三个元素为 sh
    #else
        #error "please initialize the shifting operand for the new architecture"
    #endif
#endif
    // 返回填充好的 divisor 结构体
    return divisor;
}

#endif // _NPY_SIMD_INTDIV_H

.\numpy\numpy\_core\src\common\simd\neon\arithmetic.h

#ifndef NPY_SIMD
    // 如果未定义 NPY_SIMD,则抛出错误消息 "Not a standalone header"
    #error "Not a standalone header"
#endif

#ifndef _NPY_SIMD_NEON_ARITHMETIC_H
    // 如果未定义 _NPY_SIMD_NEON_ARITHMETIC_H,则开始定义该头文件
#define _NPY_SIMD_NEON_ARITHMETIC_H

/***************************
 * Addition
 ***************************/
// non-saturated
// 定义各种数据类型的无饱和加法操作
#define npyv_add_u8  vaddq_u8
#define npyv_add_s8  vaddq_s8
#define npyv_add_u16 vaddq_u16
#define npyv_add_s16 vaddq_s16
#define npyv_add_u32 vaddq_u32
#define npyv_add_s32 vaddq_s32
#define npyv_add_u64 vaddq_u64
#define npyv_add_s64 vaddq_s64
#define npyv_add_f32 vaddq_f32
#define npyv_add_f64 vaddq_f64

// saturated
// 定义各种数据类型的有饱和加法操作
#define npyv_adds_u8  vqaddq_u8
#define npyv_adds_s8  vqaddq_s8
#define npyv_adds_u16 vqaddq_u16
#define npyv_adds_s16 vqaddq_s16

/***************************
 * Subtraction
 ***************************/
// non-saturated
// 定义各种数据类型的无饱和减法操作
#define npyv_sub_u8  vsubq_u8
#define npyv_sub_s8  vsubq_s8
#define npyv_sub_u16 vsubq_u16
#define npyv_sub_s16 vsubq_s16
#define npyv_sub_u32 vsubq_u32
#define npyv_sub_s32 vsubq_s32
#define npyv_sub_u64 vsubq_u64
#define npyv_sub_s64 vsubq_s64
#define npyv_sub_f32 vsubq_f32
#define npyv_sub_f64 vsubq_f64

// saturated
// 定义各种数据类型的有饱和减法操作
#define npyv_subs_u8  vqsubq_u8
#define npyv_subs_s8  vqsubq_s8
#define npyv_subs_u16 vqsubq_u16
#define npyv_subs_s16 vqsubq_s16

/***************************
 * Multiplication
 ***************************/
// non-saturated
// 定义各种数据类型的无饱和乘法操作
#define npyv_mul_u8  vmulq_u8
#define npyv_mul_s8  vmulq_s8
#define npyv_mul_u16 vmulq_u16
#define npyv_mul_s16 vmulq_s16
#define npyv_mul_u32 vmulq_u32
#define npyv_mul_s32 vmulq_s32
#define npyv_mul_f32 vmulq_f32
#define npyv_mul_f64 vmulq_f64

/***************************
 * Integer Division
 ***************************/
// See simd/intdiv.h for more clarification
// divide each unsigned 8-bit element by a precomputed divisor
// 对每个无符号8位元素进行除法运算,除数为预先计算的值
NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor)
{
    const uint8x8_t mulc_lo = vget_low_u8(divisor.val[0]);
    // high part of unsigned multiplication
    // 无符号乘法的高位部分
    uint16x8_t mull_lo  = vmull_u8(vget_low_u8(a), mulc_lo);
#if NPY_SIMD_F64
    uint16x8_t mull_hi  = vmull_high_u8(a, divisor.val[0]);
    // get the high unsigned bytes
    // 获取高位的无符号字节
    uint8x16_t mulhi    = vuzp2q_u8(vreinterpretq_u8_u16(mull_lo), vreinterpretq_u8_u16(mull_hi));
#else
    const uint8x8_t mulc_hi = vget_high_u8(divisor.val[0]);
    uint16x8_t mull_hi  = vmull_u8(vget_high_u8(a), mulc_hi);
    uint8x16_t mulhi    = vuzpq_u8(vreinterpretq_u8_u16(mull_lo), vreinterpretq_u8_u16(mull_hi)).val[1];
#endif
    // floor(a/d)       = (mulhi + ((a-mulhi) >> sh1)) >> sh2
    // 计算 a/d 的下整值,通过位移和加法
    uint8x16_t q        = vsubq_u8(a, mulhi);
               q        = vshlq_u8(q, vreinterpretq_s8_u8(divisor.val[1]));
               q        = vaddq_u8(mulhi, q);
               q        = vshlq_u8(q, vreinterpretq_s8_u8(divisor.val[2]));
    return q;
}
// divide each signed 8-bit element by a precomputed divisor (round towards zero)
// 对每个有符号8位元素进行除法运算(向零舍入)
NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor)
{
    const int8x8_t mulc_lo = vget_low_s8(divisor.val[0]);
    // 使用 Neon 指令 vmull_s8 对两个 int8x8_t 类型的寄存器进行有符号乘法运算,得到低位结果
    int16x8_t mull_lo  = vmull_s8(vget_low_s8(a), mulc_lo);
#if NPY_SIMD_F64
    // 如果定义了 NPY_SIMD_F64 宏,则使用64位SIMD指令进行操作

    // 对a和divisor.val[0]的高位进行有符号8位乘法,并获取高16位结果
    int16x8_t mull_hi  = vmull_high_s8(a, divisor.val[0]);

    // 交错打包两个有符号8位向量,从mull_lo和mull_hi中获取高8位
    int8x16_t mulhi    = vuzp2q_s8(vreinterpretq_s8_s16(mull_lo), vreinterpretq_s8_s16(mull_hi));
#else
    // 如果未定义 NPY_SIMD_F64 宏,则执行以下代码块

    // 获取divisor.val[0]的高8位
    const int8x8_t mulc_hi = vget_high_s8(divisor.val[0]);

    // 对a的高8位和mulc_hi进行有符号8位乘法
    int16x8_t mull_hi  = vmull_s8(vget_high_s8(a), mulc_hi);

    // 从mull_lo和mull_hi中交错打包出第二个向量
    int8x16_t mulhi    = vuzpq_s8(vreinterpretq_s8_s16(mull_lo), vreinterpretq_s8_s16(mull_hi)).val[1];
#endif

// q               = ((a + mulhi) >> sh1) - XSIGN(a)
// 计算q,将a和mulhi相加后右移sh1位,再减去a的符号位
int8x16_t q        = vshlq_s8(vaddq_s8(a, mulhi), divisor.val[1]);
          q        = vsubq_s8(q, vshrq_n_s8(a, 7));
          q        = vsubq_s8(veorq_s8(q, divisor.val[2]), divisor.val[2]);

return q;
}
// divide each unsigned 16-bit element by a precomputed divisor
NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor)
{
    // 获取divisor.val[0]的低16位
    const uint16x4_t mulc_lo = vget_low_u16(divisor.val[0]);

    // 对a和mulc_lo进行无符号16位乘法
    uint32x4_t mull_lo  = vmull_u16(vget_low_u16(a), mulc_lo);

#if NPY_SIMD_F64
    // 如果定义了 NPY_SIMD_F64 宏,则执行以下代码块

    // 对a和divisor.val[0]的高16位进行无符号16位乘法
    uint32x4_t mull_hi  = vmull_high_u16(a, divisor.val[0]);

    // 交错打包两个无符号16位向量,从mull_lo和mull_hi中获取高16位
    uint16x8_t mulhi    = vuzp2q_u16(vreinterpretq_u16_u32(mull_lo), vreinterpretq_u16_u32(mull_hi));
#else
    // 如果未定义 NPY_SIMD_F64 宏,则执行以下代码块

    // 获取divisor.val[0]的高16位
    const uint16x4_t mulc_hi = vget_high_u16(divisor.val[0]);

    // 对a的高16位和mulc_hi进行无符号16位乘法
    uint32x4_t mull_hi  = vmull_u16(vget_high_u16(a), mulc_hi);

    // 从mull_lo和mull_hi中交错打包出第二个向量
    uint16x8_t mulhi    = vuzpq_u16(vreinterpretq_u16_u32(mull_lo), vreinterpretq_u16_u32(mull_hi)).val[1];
#endif

// floor(a/d)       = (mulhi + ((a-mulhi) >> sh1)) >> sh2
// 计算floor(a/d),首先计算a-mulhi的右移sh1位后加上mulhi,再左移sh2位
uint16x8_t q        = vsubq_u16(a, mulhi);
           q        = vshlq_u16(q, vreinterpretq_s16_u16(divisor.val[1]));
           q        = vaddq_u16(mulhi, q);
           q        = vshlq_u16(q, vreinterpretq_s16_u16(divisor.val[2]));

return q;
}
// divide each signed 16-bit element by a precomputed divisor (round towards zero)
NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor)
{
    // 获取divisor.val[0]的低16位
    const int16x4_t mulc_lo = vget_low_s16(divisor.val[0]);

    // 对a和mulc_lo进行有符号16位乘法
    int32x4_t mull_lo  = vmull_s16(vget_low_s16(a), mulc_lo);

#if NPY_SIMD_F64
    // 如果定义了 NPY_SIMD_F64 宏,则执行以下代码块

    // 对a和divisor.val[0]的高16位进行有符号16位乘法
    int32x4_t mull_hi  = vmull_high_s16(a, divisor.val[0]);

    // 交错打包两个有符号16位向量,从mull_lo和mull_hi中获取高16位
    int16x8_t mulhi    = vuzp2q_s16(vreinterpretq_s16_s32(mull_lo), vreinterpretq_s16_s32(mull_hi));
#else
    // 如果未定义 NPY_SIMD_F64 宏,则执行以下代码块

    // 获取divisor.val[0]的高16位
    const int16x4_t mulc_hi = vget_high_s16(divisor.val[0]);

    // 对a的高16位和mulc_hi进行有符号16位乘法
    int32x4_t mull_hi  = vmull_s16(vget_high_s16(a), mulc_hi);

    // 从mull_lo和mull_hi中交错打包出第二个向量
    int16x8_t mulhi    = vuzpq_s16(vreinterpretq_s16_s32(mull_lo), vreinterpretq_s16_s32(mull_hi)).val[1];
#endif

// q               = ((a + mulhi) >> sh1) - XSIGN(a)
// 计算q,将a和mulhi相加后右移sh1位,再减去a的符号位
int16x8_t q        = vshlq_s16(vaddq_s16(a, mulhi), divisor.val[1]);
          q        = vsubq_s16(q, vshrq_n_s16(a, 15));
          q        = vsubq_s16(veorq_s16(q, divisor.val[2]), divisor.val[2]);

return q;
}
// divide each unsigned 32-bit element by a precomputed divisor
NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor)
{
    // 获取除数的低位部分
    const uint32x2_t mulc_lo = vget_low_u32(divisor.val[0]);
    // 对 a 的低位部分和 mulc_lo 进行无符号乘法,得到64位结果
    uint64x2_t mull_lo  = vmull_u32(vget_low_u32(a), mulc_lo);
#if NPY_SIMD_F64
    // 对 a 和除数的低位部分进行无符号高位乘法
    uint64x2_t mull_hi  = vmull_high_u32(a, divisor.val[0]);
    // 将乘法结果进行交错排列,得到高位无符号32位结果
    uint32x4_t mulhi    = vuzp2q_u32(vreinterpretq_u32_u64(mull_lo), vreinterpretq_u32_u64(mull_hi));
#else
    // 获取除数的高位部分
    const uint32x2_t mulc_hi = vget_high_u32(divisor.val[0]);
    // 对 a 的高位部分和 mulc_hi 进行无符号乘法,得到64位结果
    uint64x2_t mull_hi  = vmull_u32(vget_high_u32(a), mulc_hi);
    // 将乘法结果进行交错排列,得到高位无符号32位结果
    uint32x4_t mulhi    = vuzpq_u32(vreinterpretq_u32_u64(mull_lo), vreinterpretq_u32_u64(mull_hi)).val[1];
#endif
    // 计算商,使用预先计算的移位因子 divisor.val[1] 和 divisor.val[2]
    uint32x4_t q        =  vsubq_u32(a, mulhi);
               q        =  vshlq_u32(q, vreinterpretq_s32_u32(divisor.val[1]));
               q        =  vaddq_u32(mulhi, q);
               q        =  vshlq_u32(q, vreinterpretq_s32_u32(divisor.val[2]));
    return q;
}

// divide each signed 32-bit element by a precomputed divisor (round towards zero)
NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor)
{
    // 获取除数的低位部分
    const int32x2_t mulc_lo = vget_low_s32(divisor.val[0]);
    // 对 a 的低位部分和 mulc_lo 进行有符号乘法,得到64位结果
    int64x2_t mull_lo  = vmull_s32(vget_low_s32(a), mulc_lo);
#if NPY_SIMD_F64
    // 对 a 和除数的低位部分进行有符号高位乘法
    int64x2_t mull_hi  = vmull_high_s32(a, divisor.val[0]);
    // 将乘法结果进行交错排列,得到高位有符号32位结果
    int32x4_t mulhi    = vuzp2q_s32(vreinterpretq_s32_s64(mull_lo), vreinterpretq_s32_s64(mull_hi));
#else
    // 获取除数的高位部分
    const int32x2_t mulc_hi = vget_high_s32(divisor.val[0]);
    // 对 a 的高位部分和 mulc_hi 进行有符号乘法,得到64位结果
    int64x2_t mull_hi  = vmull_s32(vget_high_s32(a), mulc_hi);
    // 将乘法结果进行交错排列,得到高位有符号32位结果
    int32x4_t mulhi    = vuzpq_s32(vreinterpretq_s32_s64(mull_lo), vreinterpretq_s32_s64(mull_hi)).val[1];
#endif
    // 计算商,使用预先计算的移位因子 divisor.val[1] 和 divisor.val[2]
    int32x4_t q        = vshlq_s32(vaddq_s32(a, mulhi), divisor.val[1]);
              q        = vsubq_s32(q, vshrq_n_s32(a, 31));
              q        = vsubq_s32(veorq_s32(q, divisor.val[2]), divisor.val[2]);
    return q;
}

// divide each unsigned 64-bit element by a divisor
NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor)
{
    // 获取除数的第一个元素作为64位整数
    const uint64_t d = vgetq_lane_u64(divisor.val[0], 0);
    // 将 a 的每个64位元素除以 d,返回结果
    return npyv_set_u64(vgetq_lane_u64(a, 0) / d, vgetq_lane_u64(a, 1) / d);
}

// returns the high 64 bits of signed 64-bit multiplication
NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor)
{
    // 获取除数的第一个元素作为64位整数
    const int64_t d = vgetq_lane_s64(divisor.val[0], 0);
    // 将 a 的每个64位元素除以 d,返回结果
    return npyv_set_s64(vgetq_lane_s64(a, 0) / d, vgetq_lane_s64(a, 1) / d);
}
/***************************
 * Division
 ***************************/
#if NPY_SIMD_F64
    // 如果定义了 NPY_SIMD_F64,则使用内置的单精度浮点除法
    #define npyv_div_f32 vdivq_f32
#else
    // 否则定义一个函数 npyv_div_f32,实现单精度浮点除法
    NPY_FINLINE npyv_f32 npyv_div_f32(npyv_f32 a, npyv_f32 b)
    {
        // 基于 ARM 文档,参见 https://developer.arm.com/documentation/dui0204/j/CIHDIACI
        // 估算 b 的倒数
        npyv_f32 recipe = vrecpeq_f32(b);
        /**
         * 牛顿-拉弗森迭代法:
         *  x[n+1] = x[n] * (2 - d * x[n])
         * 当 x0 是应用于 d 的 VRECPE 结果时,收敛到 (1/d)。
         *
         * 注意:至少需要 3 次迭代以提高精度。
         */
        recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe);
        recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe);
        recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe);
        // 返回 a/b = a * recip(b) 的结果
        return vmulq_f32(a, recipe);
    }
#ifdef NPY_HAVE_NEON_VFPV4 // FMA
    // multiply and add, a*b + c
    NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vfmaq_f32(c, a, b); }
    // multiply and subtract, a*b - c
    NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vfmaq_f32(vnegq_f32(c), a, b); }
    // negate multiply and add, -(a*b) + c
    NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vfmsq_f32(c, a, b); }
    // negate multiply and subtract, -(a*b) - c
    NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vfmsq_f32(vnegq_f32(c), a, b); }
#else
    // multiply and add, a*b + c
    NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vmlaq_f32(c, a, b); }
    // multiply and subtract, a*b - c
    NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vmlaq_f32(vnegq_f32(c), a, b); }
    // negate multiply and add, -(a*b) + c
    NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vmlsq_f32(c, a, b); }
    // negate multiply and subtract, -(a*b) - c
    NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
    { return vmlsq_f32(vnegq_f32(c), a, b); }
#endif

// multiply, add for odd elements and subtract even elements.
// (a * b) -+ c
NPY_FINLINE npyv_f32 npyv_muladdsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c)
{
    // Create a mask for selecting odd and even elements
    const npyv_f32 msign = npyv_set_f32(-0.0f, 0.0f, -0.0f, 0.0f);
    // XOR operation to toggle the sign bit, achieving -(c)
    // Perform fused multiply-add or fused multiply-subtract based on the mask
    return npyv_muladd_f32(a, b, npyv_xor_f32(msign, c));
}

#if NPY_SIMD_F64
    // F64 versions of fused operations for systems supporting SIMD with 64-bit floats
    NPY_FINLINE npyv_f64 npyv_muladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c)
    { return vfmaq_f64(c, a, b); }
    NPY_FINLINE npyv_f64 npyv_mulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c)
    { return vfmaq_f64(vnegq_f64(c), a, b); }
    NPY_FINLINE npyv_f64 npyv_nmuladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c)
    { return vfmsq_f64(c, a, b); }
    NPY_FINLINE npyv_f64 npyv_nmulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c)
    { return vfmsq_f64(vnegq_f64(c), a, b); }
    // Multiply, add for odd elements and subtract even elements for F64
    NPY_FINLINE npyv_f64 npyv_muladdsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c)
    {
        // Mask for selecting odd and even elements
        const npyv_f64 msign = npyv_set_f64(-0.0, 0.0);
        // XOR operation to toggle the sign bit, achieving -(c)
        // Perform fused multiply-add or fused multiply-subtract based on the mask
        return npyv_muladd_f64(a, b, npyv_xor_f64(msign, c));
    }
#endif // NPY_SIMD_F64

// Reduce sum across vector
#if NPY_SIMD_F64
    // SIMD operations for floating point 64-bit sums
    #define npyv_sum_u32 vaddvq_u32
    #define npyv_sum_u64 vaddvq_u64
    #define npyv_sum_f32 vaddvq_f32
    #define npyv_sum_f64 vaddvq_f64
#else
    // Summation for 64-bit unsigned integers
    NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a)
    {
        // Extract and sum low and high parts of the vector
        return vget_lane_u64(vadd_u64(vget_low_u64(a), vget_high_u64(a)), 0);
    }
    // Summation for 32-bit unsigned integers
    NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a)
    // 使用 NEON 指令,将输入向量 a 的低32位和高32位分别相加,生成新的向量 a0
    uint32x2_t a0 = vpadd_u32(vget_low_u32(a), vget_high_u32(a));

    // 使用 NEON 指令,将向量 a0 和输入向量 a 的高32位分别相加,返回相加结果的第0个元素,转换为无符号整数并返回
    return (unsigned)vget_lane_u32(vpadd_u32(a0, vget_high_u32(a)), 0);
}

// 定义一个内联函数,计算给定的浮点型 NEON 向量 a 中所有元素的总和
NPY_FINLINE float npyv_sum_f32(npyv_f32 a)
{
    // 使用 NEON 指令,将向量 a 中的高32位和低32位分别相加,得到结果向量 r
    float32x2_t r = vadd_f32(vget_high_f32(a), vget_low_f32(a));

    // 使用 NEON 指令,将结果向量 r 和自身相加,再取结果向量的第0个元素作为返回值,即向量中所有元素的总和
    return vget_lane_f32(vpadd_f32(r, r), 0);
}
#ifdef

// 如果定义了 NPY_SIMD_F64 宏,则使用 vaddlvq_u8 和 vaddlvq_u16 宏来进行向量内部求和操作
#if NPY_SIMD_F64
    #define npyv_sumup_u8  vaddlvq_u8     // 定义向量内部无符号8位整数求和宏
    #define npyv_sumup_u16 vaddlvq_u16    // 定义向量内部无符号16位整数求和宏
#else
    // 如果未定义 NPY_SIMD_F64 宏,则定义以下两个函数进行向量内部求和操作

    // 对无符号8位整数向量进行求和,返回一个16位无符号整数
    NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a)
    {
        uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(a));     // 将每个8位整数加倍扩展到16位,然后两两相加
        uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));  // 横向求和16位结果的低32位和高32return vget_lane_u32(vpadd_u32(t1, t1), 0);      // 将低32位和高32位再次相加并返回最低32位结果
    }

    // 对无符号16位整数向量进行求和,返回一个32位无符号整数
    NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a)
    {
        uint32x4_t t0 = vpaddlq_u16(a);                  // 将每个16位整数向量两两相加
        uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));  // 横向求和16位结果的低32位和高32return vget_lane_u32(vpadd_u32(t1, t1), 0);      // 将低32位和高32位再次相加并返回最低32位结果
    }
#endif

#endif // _NPY_SIMD_NEON_ARITHMETIC_H