written from scratch fixed point math library in C++17
- minimum c++17 compiler required
- fixed point 48.16 arithmethic strong type without implicit convertions with assignment and construction, fixed type is safe against unwanted type convertions
- all arithemtic types like float and integral types except double implicitly in base arithemitc operations are promoted to fixed_t
- all arithmetic operations of fixed_t with double type yelds double result type, are promoted and evaluated as double operations
- entire code including trigonometry functions is constexpr [1]
- fully header only library as everything is constexpr, see api interface api and implementation
- unit tests can be checked at compilation time just including header, see unittests
[1] - By default is used std:sqrt as current cpu's has hardware support for sqrt, but constexpr abacus algorithm could be used defining FIXEDMATH_ENABLE_SQRT_ABACUS_ALGO, which is slower than cpu one
At this point code wasn't been optimised, so results are from just from code written with quality only at this point in mind. Results are relative times of computing functions over bigtable of source values in function type (no value convertions)
Cortex-A73 - Snapdragon 865+
tag | function | fixed clang | fixed gcc | float | double | status |
---|---|---|---|---|---|---|
0.9.1 | sin | 50 ms | 31 ms | 77 ms | ||
0.9.4 | sin | 30 ms | 24ms | 31 ms | 77 ms | optimized |
0.9.1 | asin | 124 ms | 75 ms | 128 ms | ||
0.9.4 | asin | 63 ms | 54 ms | 75 ms | 127 ms | optimized |
0.9.1 | tan | 136 ms | 104 ms | 206 ms | ||
0.9.4 | tan | 136 ms | 130 ms | 104 ms | 206 ms | |
0.9.1 | atan | 113 ms | 110 ms | 165 ms | ||
0.9.5 | atan | 80 ms | 65 ms | 110 ms | 165 ms | optimized |
Ryzen 9 - 3900X
tag | function | fixed clang | fixed gcc | float | double | status |
---|---|---|---|---|---|---|
0.9.1 | sin | 27 ms | 22 ms | 75 ms | ||
0.9.4 | sin | 20 ms | 18ms | 21 ms | 74 ms | optimized |
0.9.1 | asin | 92 ms | 58 ms | 106 ms | ||
0.9.4 | asin | 49 ms | 44 ms | 57 ms | 104 ms | optimized |
0.9.1 | tan | 81 ms | 66 ms | 180 ms | ||
0.9.4 | tan | 78 ms | 88 ms | 67 ms | 176 ms | |
0.9.1 | atan | 90 ms | 78 ms | 162 ms | ||
0.9.5 | atan | 64 ms | 55ms | 77 ms | 161 ms | optimized |
this library is header only except tabelarized trigonometric functions. So If you can use precise trigonometric functions You don't have to build anything. Just add fixed_lib/include to include path and #include <fixedmath/fixed_math.hpp>. If you want additional inprecise aproxymated functions compile project like any other ordinary CMake project. At this point it doesn't have any tuning parameters for CMake.
Thise are known to compile without errors, if You found any problem with c++17 compiler let me know and post issue as stl shoudn't be a problem
- clang version 11.0.1 + gcc-libstdc++ 10.2.0 (main development platform) on x86-64 and aarch64
- clang version 11.0.1 + llvm-libcxx on x86-64
- gcc 10.2.0 on x86-64
- clang version 10.0.1 x86-64 + gcc-libstdc++ 10.2.0
- limitied msvc19 support *
* msvc problems
- constexpresions evaulated at compile time are causing compiler crash like one below in code block, this is really riduculus.
- there is no eficient easy way to calculate clz at compile time and runtime whith single code, as msvc doesn't have support for constexpr clz like clang or gcc with builtin. Implementation of countl_zero in msvc c++20 is somehow like a joke, different code will be exceuted at constexpr evaluation, different at runtime ... Thats not a way I implement code. So for c++17 msvc compile mode is simply a loop constexpr from msvc stl used, or for c++20 mode when available std::countl_zero. I'm not going to write broken implementations of countl_zero that can work differently at runtime compared to compile time and thus pass all bugs uncatched in unit tests.
1>D:\projects\fixed_math\fixed_lib\include\fixedmath\unittests\addition.h(19,43): fatal error C1001: Wewnętrzny błšd kompilatora.
1 > (plik kompilatora �d : \A01\_work\2\s\src\vctools\Compiler\CxxFE\sl\p1\c\constexpr\constexpr.cpp�, wiersz 6887)
fixed_t is typename of fixed point arithmetic type with common operators like, +, -, * ..
#include <fixedmath/fixed_math.hpp>
#include <fixedmath/iostream.h>
using fixedmath::fixed_t;
//fixed and all functionality is constexpr so You can declare constants see features [1]
inline constexpr fixed_t foo_constant{ fixedmath::tan( 15 * fixedmath::phi/180) };
constexpr fixed_t my_function( fixed_t value )
{
using namespace fixedmath;
return foo_constant + sin(value) / (1.41_fix - 2*cos(value) / 4);
}
// converting to/from fixed_t
// construction from other arithmetic types is explicit
fixed_t val { 3.14 };
fixed_t val { 3u };
//- there is no implicit assignment from other types
float some_float{};
fixed_t some_fixed{};
...
some_fixed = fixed_t{some_float};
//- converting to other arithmetic types coud be done with static cast and is explicit
double some_double { static_cast<double>(some_fixed) };
// for constant values postfix operator _fix may be used
some_fixed = some_float * 2.45_fix; //operation with float is promoted to fixed_t
some_double = 4.15 * some_fixed; //operation with double is promoted to double
std::cout << some_fixed;
To check unit tests just #include <fixedmath/unittests/compile_time_unit_tests.h> in any of Your source file. or run them wit CMake/CTest "ninja/make test" as they are available in default CMakeConfiguration of source folder see ENABLE_UNIT_TESTS cmake feature i CMakeLists.txt
- base arithemtic operations
- sqrt - abacus algorithm using CLZ ( CLZ is available on x86 and >=armv6, aarch64) error ~<= 0.000015
- hypot - with normalization to suitable range, to avoid overflow and underflow
- sin, cos - error ~<= 0.0001
- tan - error on normalized range |x| <= PI/4 ~<= 0.0001, PI/4 |x| <= PI/2 ~<=0.001 exept near 90deg ~<= 0.01
- tan - improve calculations, limit tan__ to |x|<=pi/4
- atan, atan2 - error ~<= 0.00005
- asin error ~<= 0.0001
- [ ] remove all old compat code that is compiled
- [ ] cover all functionality with static_assert unit tests
- support clang, gcc c++17 compilers
- support msvc c++17 compiler, partial see notes for compilers tested in "c++ compilers"
- performance comparisions on arm64 and x86 with float/double arithemetic
- [ ] dual licence project with MIT and BOOST licence
-
[ ] more math functionality, if somthing is missing in library that You need post issue and let me know about that.
-
[ ] more optimisations, calculation quality enchacments
If you think you have found a bug, please file an issue via issue submission form. Include the relevant information to reproduce the bug for example as static_assert( expression ), if it is important also the compiler version and target architecture. Feature requests and contributions can be filed as issues or pull requests.
This library is available to anybody free of charge, under the terms of MIT License (see LICENSE.md).