Template dedicated for RISC-V 32 IM.
All library files can be found in src/lib/
.
Just copy the files and include them.
Additionally taylormath
need to be linked with its cpp
file.
The library works with C++:
- std-c++23
- std-c++20
- std-c++17
- std-c++11 if you are not going to use constexpr functionalities (they works but not everywhere)
The template has the following prototype:
template<typename T, typename TC=typename make_fast_int<T>::type, unsigned frac_bits=sizeof(T)*4-1> class fixedpoint;
T
- integer type for calculations.TC
- integer type for multiplication and division. By default it isfast
type of theT
(on 64-bits systems it is usuallyint64
/uint64
)frac_bits
- number - where to put the fraction point.
There are predefinied types:
-
Standard types (the fastest TC with at least T size)
-
signed
- fixed8 - signed 8 bit
T
, fast 8 bit type forTC
, 3 fraction bits - fixed16 - signed 16 bit
T
, fast 16 bit type forTC
, 7 fraction bits - fixed32 - signed 32 bit
T
, fast 32 bit type forTC
, 15 fraction bits - fixed64 - signed 64 bit
T
, fast 64 bit type forTC
, 31 fraction bits
- fixed8 - signed 8 bit
-
unsigned
- ufixed8 - unsigned 8 bit
T
, fast 8 bit type forTC
, 3 fraction bits - ufixed16 - unsigned 16 bit
T
, fast 16 bit type forTC
, 7 fraction bits - ufixed32 - unsigned 32 bit
T
, fast 32 bit type forTC
, 15 fraction bits - ufixed64 - unsigned 64 bit
T
, fast 64 bit type forTC
, 31 fraction bits
- ufixed8 - unsigned 8 bit
-
-
Accurate types (TC two times larger than T - except [u]int64)
-
signed
- fixed8_a - signed 8 bit
T
, fast 16 bit type forTC
, 3 fraction bits - fixed16_a - signed 16 bit
T
, fast 32 bit type forTC
, 7 fraction bits - fixed32_a - signed 32 bit
T
, fast 64 bit type forTC
, 15 fraction bits - fixed64_a - signed 64 bit
T
, fast 64 bit type forTC
, 31 fraction bits
- fixed8_a - signed 8 bit
-
unsigned
- ufixed8_a - unsigned 8 bit
T
, fast 16 bit type forTC
, 3 fraction bits - ufixed16_a - unsigned 16 bit
T
, fast 32 bit type forTC
, 7 fraction bits - ufixed32_a - unsigned 32 bit
T
, fast 64 bit type forTC
, 15 fraction bits - ufixed64_a - unsigned 64 bit
T
, fast 64 bit type forTC
, 31 fraction bits
- ufixed8_a - unsigned 8 bit
-
-
Simple types (same size of T and TC)
-
signed
- fixed8_s - signed 8 bit
T
, 8 bit type forTC
, 3 fraction bits - fixed16_s - signed 16 bit
T
, 16 bit type forTC
, 7 fraction bits - fixed32_s - signed 32 bit
T
, 32 bit type forTC
, 15 fraction bits - fixed64_s - signed 64 bit
T
, 64 bit type forTC
, 31 fraction bits
- fixed8_s - signed 8 bit
-
unsigned
- ufixed8_s - unsigned 8 bit
T
, 8 bit type forTC
, 3 fraction bits - ufixed16_s - unsigned 16 bit
T
, 16 bit type forTC
, 7 fraction bits - ufixed32_s - unsigned 32 bit
T
, 32 bit type forTC
, 15 fraction bits - ufixed64_s - unsigned 64 bit
T
, 64 bit type forTC
, 31 fraction bits
- ufixed8_s - unsigned 8 bit
-
Due to possible inconsistency of result type on calculations of various fixedpoints both operands should be the same type. But it is not something that you must remember because the compiler will remind you.
The solution is to use casting, f.e.:
fixed32 x = 7.35;
fixed64 y = 21.37;
std::cout << x + (fixed32)y << std::endl;
std::cout << (fixed64)x + y << std::endl;
All conversions from floats works by multiplying float / double variable by some constant and then casting it to an integer type. It could be faster by using one of the following functions:
- from_ieee754
- from_float
- from_double
all of them might be faster or slower - it depends on the target platform. Results of these functions could be also incorrect so always check results on the new target. Although some assertions were made to avoid errors and thus in case of detection of an unsupported float/double format, these functions will use "standard" multiplication.
STARTING TESTS
type | library | addition | subtraction | multiplication | division | sin | sqrt | asin | log | exp |
---|---|---|---|---|---|---|---|---|---|---|
fixed32_s | taylormath | 6982 | 6917 | 6298 | 61652 | 189845 | 85509 | 113827 | 360010 | 300977 |
fixed32_a | taylormath | 6956 | 6922 | 15729 | 201253 | 303803 | 254862 | 170733 | 861728 | 397566 |
fixed64 | taylormath | 13247 | 13211 | 20761 | 206308 | 835902 | 399448 | 396151 | 2217824 | 1437792 |
float | cmath | 101477 | 105844 | 164146 | 254705 | 2025247 | 344892 | 535360 | 1527857 | 2016053 |
double | cmath | 118830 | 121306 | 289300 | 495248 | 3026929 | 614699 | 843223 | 2339121 | 2996070 |
float | taylormath | 101490 | 105844 | 163517 | 255330 | 2686019 | 1839398 | 1434164 | 8438956 | 4190184 |
double | taylormath | 118830 | 121313 | 288667 | 494616 | 5820614 | 8243824 | 7006465 | 34110313 | 10240876 |
Taylormath calculates until increasing accuracy is not possible, so the more accurate type, the more time is needed to calculate a function result.
Differences with double and cmath as reference.