Skip to content

pawel2000pl/fixed_point

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Library for fixed point operations with math module based on (mostly) taylor series.

Template dedicated for RISC-V 32 IM.

Usage

Files

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)

Usage in code

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 is fast type of the T (on 64-bits systems it is usually int64 / 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 for TC, 3 fraction bits
      • fixed16 - signed 16 bit T, fast 16 bit type for TC, 7 fraction bits
      • fixed32 - signed 32 bit T, fast 32 bit type for TC, 15 fraction bits
      • fixed64 - signed 64 bit T, fast 64 bit type for TC, 31 fraction bits
    • unsigned

      • ufixed8 - unsigned 8 bit T, fast 8 bit type for TC, 3 fraction bits
      • ufixed16 - unsigned 16 bit T, fast 16 bit type for TC, 7 fraction bits
      • ufixed32 - unsigned 32 bit T, fast 32 bit type for TC, 15 fraction bits
      • ufixed64 - unsigned 64 bit T, fast 64 bit type for TC, 31 fraction bits
  • Accurate types (TC two times larger than T - except [u]int64)

    • signed

      • fixed8_a - signed 8 bit T, fast 16 bit type for TC, 3 fraction bits
      • fixed16_a - signed 16 bit T, fast 32 bit type for TC, 7 fraction bits
      • fixed32_a - signed 32 bit T, fast 64 bit type for TC, 15 fraction bits
      • fixed64_a - signed 64 bit T, fast 64 bit type for TC, 31 fraction bits
    • unsigned

      • ufixed8_a - unsigned 8 bit T, fast 16 bit type for TC, 3 fraction bits
      • ufixed16_a - unsigned 16 bit T, fast 32 bit type for TC, 7 fraction bits
      • ufixed32_a - unsigned 32 bit T, fast 64 bit type for TC, 15 fraction bits
      • ufixed64_a - unsigned 64 bit T, fast 64 bit type for TC, 31 fraction bits
  • Simple types (same size of T and TC)

    • signed

      • fixed8_s - signed 8 bit T, 8 bit type for TC, 3 fraction bits
      • fixed16_s - signed 16 bit T, 16 bit type for TC, 7 fraction bits
      • fixed32_s - signed 32 bit T, 32 bit type for TC, 15 fraction bits
      • fixed64_s - signed 64 bit T, 64 bit type for TC, 31 fraction bits
    • unsigned

      • ufixed8_s - unsigned 8 bit T, 8 bit type for TC, 3 fraction bits
      • ufixed16_s - unsigned 16 bit T, 16 bit type for TC, 7 fraction bits
      • ufixed32_s - unsigned 32 bit T, 32 bit type for TC, 15 fraction bits
      • ufixed64_s - unsigned 64 bit T, 64 bit type for TC, 31 fraction bits

Problem with operators

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;

Conversions from IEEE754

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.

Test results

Speed comparision (microseconds per 100000 operations on ESP32C3@160MHz)

STARTING TESTS

typelibraryadditionsubtractionmultiplicationdivisionsinsqrtasinlogexp
fixed32_staylormath6982691762986165218984585509113827360010300977
fixed32_ataylormath6956692215729201253303803254862170733861728397566
fixed64taylormath13247132112076120630883590239944839615122178241437792
floatcmath101477105844164146254705202524734489253536015278572016053
doublecmath118830121306289300495248302692961469984322323391212996070
floattaylormath10149010584416351725533026860191839398143416484389564190184
doubletaylormath1188301213132886674946165820614824382470064653411031310240876

Taylormath calculates until increasing accuracy is not possible, so the more accurate type, the more time is needed to calculate a function result.

Taylormath accuracy

Differences with double and cmath as reference.

asin plot cos plot sin plot log plot exp plot sqrt plot

About

Template for fixed-point operations with a simplified math library (dedicated for RISC-V IM).

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published