Skip to content

pawel2000pl/fixed_point

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 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_staylormath6982691669255346919083478826112980342369303379
fixed32_ataylormath6956692315722201881305426261547171984878552396626
fixed64taylormath13249132112076020567883679038451339233221863561434525
floatcmath101480105843164144254701202521534488553534615278352016006
doublecmath118830121311289294495233302688661469884320623390862996029
floattaylormath10148510584416351325533626859841839360143376584301234188721
doubletaylormath1188351213032886704946035820529824371170059863412912710240732

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