186 lines
4.5 KiB
C++
186 lines
4.5 KiB
C++
/**
|
||
* @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<typename T>
|
||
[[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<u32 bits>
|
||
[[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<u32 bits>
|
||
[[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<bits>(distance);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief 将量化整数还原为 [0,1] 浮点值。
|
||
* @tparam bits 量化位宽。
|
||
* @param i 量化输入值。
|
||
* @return 反量化结果。
|
||
*/
|
||
template<u32 bits>
|
||
[[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<u32 bits>
|
||
[[nodiscard]] constexpr f32
|
||
unpack_float(f32 i, f32 min, f32 max)
|
||
{
|
||
assert(min < max);
|
||
return unpack_unit_float<bits>(i) * (max - min) + min;
|
||
}
|
||
|
||
/**
|
||
* @brief 按固定对齐值向上对齐。
|
||
* @tparam alignment 对齐粒度(2 的幂)。
|
||
* @param size 原始大小。
|
||
* @return 向上对齐后的大小。
|
||
*/
|
||
template<u64 alignment>
|
||
[[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<u64 alignment>
|
||
[[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<sizeof(u64)>(size) };
|
||
while (at < end)
|
||
{
|
||
crc = _mm_crc32_u64(crc, *((const u64*)at));
|
||
at += sizeof(u64);
|
||
}
|
||
|
||
return crc;
|
||
}
|
||
|
||
}
|