/** * @file Math.h * @brief 数学工具函数与二进制对齐辅助函数。 * @details * 提供模板化的数值打包/解包与内存对齐能力,包括: * - clamp 与归一化浮点量化打包; * - 固定/动态对齐粒度下的向上与向下对齐; * - 基于 SIMD 指令的 CRC32 快速计算辅助。 */ #pragma once #include "CommonHeader.h" #include "MathTypes.h" namespace XEngine::math { /** * @brief 将值限制在给定区间内。 * @tparam T 标量类型。 * @param value 输入值。 * @param min 下界。 * @param max 上界。 * @return 限制后的值。 */ template [[nodiscard]] constexpr T clamp(T value, T min, T max) { return (value < min) ? min : (value > max) ? max : value; } /** * @brief 将 [0,1] 浮点值量化到指定位宽的无符号整数。 * @tparam bits 量化位宽。 * @param i 归一化输入值。 * @return 量化结果。 */ template [[nodiscard]] constexpr u32 pack_unit_float(f32 i) { static_assert(bits <= sizeof(u32) * 8); assert(i >= 0.f && i <= 1.f); constexpr f32 intervals{ (f32)(((u32)1 << bits) - 1) }; return (u32)(intervals * i + 0.5f); } /** * @brief 将 [min,max] 浮点值量化到指定位宽。 * @tparam bits 量化位宽。 * @param i 输入值。 * @param min 下界。 * @param max 上界。 * @return 量化结果。 */ template [[nodiscard]] constexpr u32 pack_float(f32 i, f32 min, f32 max) { assert(min < max); assert(i <= max && i >= min); const f32 distance{ (i - min) / (max - min) }; return pack_unit_float(distance); } /** * @brief 将量化整数还原为 [0,1] 浮点值。 * @tparam bits 量化位宽。 * @param i 量化输入值。 * @return 反量化结果。 */ template [[nodiscard]] constexpr f32 unpack_unit_float(u32 i) { static_assert(bits <= sizeof(u32) * 8); assert(i < ((u32)i << bits)); constexpr f32 intervals{ (f32)(((u32)1 << bits) - 1) }; return (f32)i / intervals; } /** * @brief 将量化值还原到 [min,max] 区间。 * @tparam bits 量化位宽。 * @param i 量化输入值。 * @param min 下界。 * @param max 上界。 * @return 反量化结果。 */ template [[nodiscard]] constexpr f32 unpack_float(f32 i, f32 min, f32 max) { assert(min < max); return unpack_unit_float(i) * (max - min) + min; } /** * @brief 按固定对齐值向上对齐。 * @tparam alignment 对齐粒度(2 的幂)。 * @param size 原始大小。 * @return 向上对齐后的大小。 */ template [[nodiscard]] constexpr u64 align_size_up(u64 size) { static_assert(alignment, "Alignment must be non-zero."); constexpr u64 mask{ alignment - 1 }; static_assert(!(alignment & mask), "Alignment should be a power of 2."); return ((size + mask) & ~mask); } /** * @brief 按固定对齐值向下对齐。 * @tparam alignment 对齐粒度(2 的幂)。 * @param size 原始大小。 * @return 向下对齐后的大小。 */ template [[nodiscard]] constexpr u64 align_size_down(u64 size) { static_assert(alignment, "Alignment must be non-zero."); constexpr u64 mask{ alignment - 1 }; static_assert(!(alignment & mask), "Alignment should be a power of 2."); return (size & ~mask); } /** * @brief 按运行时对齐值向上对齐。 * @param size 原始大小。 * @param alignment 对齐粒度(2 的幂)。 * @return 向上对齐后的大小。 */ [[nodiscard]] constexpr u64 align_size_up(u64 size, u64 alignment) { assert(alignment && "Alignment must be non-zero."); const u64 mask{ alignment - 1 }; assert(!(alignment & mask) && "Alignment should be a power of 2."); return ((size + mask) & ~mask); } /** * @brief 按运行时对齐值向下对齐。 * @param size 原始大小。 * @param alignment 对齐粒度(2 的幂)。 * @return 向下对齐后的大小。 */ [[nodiscard]] constexpr u64 align_size_down(u64 size, u64 alignment) { assert(alignment && "Alignment must be non-zero."); const u64 mask{ alignment - 1 }; assert(!(alignment & mask) && "Alignment should be a power of 2."); return (size & ~mask); } /** * @brief 计算数据块的 64 位 CRC32 累积值。 * @param data 输入字节流。 * @param size 输入长度。 * @return CRC32 累积结果。 */ [[nodiscard]] constexpr u64 calcect_crc32_u64(const u8 *const data, u64 size) { assert(size >= sizeof(u64)); u64 crc{ 0 }; const u8* at{ data }; const u8 *const end{ data + align_size_down(size) }; while (at < end) { crc = _mm_crc32_u64(crc, *((const u64*)at)); at += sizeof(u64); } return crc; } }