Cross-platform single-header modern C++ fixed-point arithmetic library.
requires c++11, recommands c++20
- 64-bits internal storage
- tweakable fraction precision (QM.N)
- protected from intermediatary overflows
- support rounding and saturation
- evaluated in compile time almostly(totally in c++20)
#include <iostream>
#include "fixed64.hpp"
int main(int argc, char* argv[])
{
f64::fixed64<40> a = 1.23; // Q24.40
std::cout << (a + 1);
return 0;
}
fixed64 is designed to find a balance between percision and performance. It is stored by int64. The target application scenario is physics engine,which has many distance calculation that cause the overflow on 32-bits fixed-point.
- fixed64.hpp fixed-point header
- trig_lut.hpp lut for sin, optional
- Arithmetic: + - * / fmod sqrt
- Trigonometry: sin cos tan asin acos atan atan2
- Exponential: exp exp2 log log2 log10 pow
- Other: abs ceil floor round
- support hardware int128 (MSVC only)
- support look-up table for trigonometric function
- support speed up the multiplication and division with integer
see more in benchmark
#define FIXED_64_ENABLE_ROUNDING // apply rounding
#define FIXED_64_ENABLE_OVERFLOW // checking overflow
#define FIXED_64_ENABLE_SATURATING // saturate result
#define FIXED_64_ENABLE_TRIG_LUT // use lut for trigonometric function
#define FIXED_64_FORCE_EVALUATE_IN_COMPILE_TIME //make all function be with constexpr, clz will use soft implemention
#define FIXED_64_ENABLE_FORCEINLINE // enable forceinline
- fpm good coding style,but has no overflow protection/alert, need to provide int128 as intermediate type by yourself
- libfixmath64 gives me great inspiration. but it is c-style and can not evaluate fixed-point value in compile time.
- fixmath I think the best one. support hardware int128, but need to include too many headers
- fixed_point, fp perform incorrect result in multiply operation when the fraction has large bits(intermediatary overflow happens).
- 64位存储
- 可变小数位精度
- 越界保护/警告
- 支持四舍五入和越界限制
- 支持大部分函数的编译期计算(c++20全部支持)
#include <iostream>
#include "fixed64.hpp"
int main(int argc, char* argv[])
{
f64::fixed64<40> a = 1.23; // Q24.40
std::cout << (a + 1);
return 0;
}
fixed64综合考虑了精度与性能的问题,使用了int64存储。个人的应用场景是物理引擎。物理引擎中存在大量距离计算,使用32位的定点数容易发生溢出。
- fixed64.hpp 定点数头文件
- trig_lut.hpp 三角函数查表文件,不是必须
- 算数操作: + - * / fmod sqrt
- 三角函数: sin cos tan asin acos atan atan2
- 指数函数: exp exp2 log log2 log10 pow
- 其他函数: abs ceil floor round
- 支持硬件int128加速计算(暂时只支持MSVC)
- 支持三角函数查表
- 支持与整型的乘除法加速
具体参考benchmark
#define FIXED_64_ENABLE_ROUNDING // 使用四舍五入
#define FIXED_64_ENABLE_OVERFLOW // 使用越界检查
#define FIXED_64_ENABLE_SATURATING // 使用越界限制
#define FIXED_64_ENABLE_TRIG_LUT // 三角函数使用查表方法
#define FIXED_64_FORCE_EVALUATE_IN_COMPILE_TIME //强制使函数支持编译期运算,主要是改变clz的实现
#define FIXED_64_ENABLE_FORCEINLINE // 开启强制内联
- fpm 优秀的代码风格,但是没有计算溢出检查,需要自己提供int128来支持64位的定点数实现。
- libfixmath64 给我很大启发. 但是是C风格代码,缺少编译期运算支持。
- fixmath 个人认为最好的定点数库. 支持硬件int128运算,但是头文件太多。
- fixed_point, fp 这些库没有考虑当小数部分占位数较多时,乘除法计算中间值越界问题,这将导致计算结果错误。