FixMath
Classes | Namespaces | Typedefs | Functions
FixMath.h File Reference
#include <Arduino.h>
#include "IntegerType.h"
#include "FixMath_Autotests.h"
Include dependency graph for FixMath.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  FixMathPrivate::BitCounter< value, bits >
 
struct  FixMathPrivate::BitCounter< value, 0 >
 
class  UFix< NI, NF, RANGE >
 
class  SFix< NI, NF, RANGE >
 

Namespaces

 FixMathPrivate
 

Typedefs

template<int8_t NF, uint64_t RANGE>
using FixMathPrivate::UFixByRange_t = UFix< NIcount< RANGE >() -NF, NF, RANGE >
 
template<int8_t NF, uint64_t RANGE>
using FixMathPrivate::SFixByRange_t = SFix< NIcount< RANGE-1 >() -NF, NF, RANGE >
 

Functions

template<typename T >
constexpr T FixMathPrivate::shiftR (T x, int8_t bits)
 
constexpr int8_t FixMathPrivate::sBitsToBytes (int8_t N)
 
constexpr int8_t FixMathPrivate::uBitsToBytes (int8_t N)
 
template<typename T >
constexpr T FixMathPrivate::FM_max (T N1, T N2)
 
template<typename T >
constexpr T FixMathPrivate::FM_min (T N1, T N2)
 
constexpr uint64_t FixMathPrivate::sFullRange (int8_t N)
 
constexpr uint64_t FixMathPrivate::uFullRange (int8_t N)
 
constexpr uint64_t FixMathPrivate::rangeAdd (byte NF, byte _NF, uint64_t RANGE, uint64_t _RANGE)
 
constexpr uint64_t FixMathPrivate::rangeShift (int8_t N, int8_t SH, uint64_t RANGE)
 
template<uint64_t value>
constexpr int8_t FixMathPrivate::NIcount ()
 
template<typename T >
constexpr UFix< 0, sizeof(T) *8 > toUFraction (T val)
 
template<typename T >
constexpr UFix< sizeof(T) *8, 0 > toUInt (T val)
 
template<uint64_t value>
constexpr FixMathPrivate::UFixByRange_t< 0, value > UFixAuto ()
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator> (const SFix< NI, NF > &op1, const UFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator> (const UFix< NI, NF > &op1, const SFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator< (const UFix< NI, NF > &op1, const SFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator< (const SFix< NI, NF > &op1, const UFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator== (const SFix< NI, NF > &op1, const UFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator== (const UFix< NI, NF > &op1, const SFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator!= (const SFix< NI, NF > &op1, const UFix< _NI, _NF > &op2)
 
template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator!= (const UFix< NI, NF > &op1, const SFix< _NI, _NF > &op2)
 
template<typename T >
constexpr SFix< 0, sizeof(T) *8-1 > toSFraction (T val)
 
template<typename T >
constexpr SFix< sizeof(T) *8-1, 0 > toSInt (T val)
 

Detailed Description

This file implements two fixed point number classes. These numbers can have a fractional part but are actually standard integers under the hood which makes calculations with them efficient on platforms which do not have a FPU like most micro-controllers. These numbers can be signed (SFix) or unsigned (UFix).

A fixed point number has its range defined by the number of bits encoding the integer part (NI in the following) and its precision by the number of bits encoding the fractional part (NF). For UFix types, the integral part can hold values in [0,2^NI-1], for SFix types, the integral part can hold values in [-2^NI,2^NI-1]. The number of bits encoding the fractional can be considered as the precision of the number: given NF, the number of possible values in the [0,1[ range will 2^NF. Hence, given NF, the resolution will be 1/(2^NF).

Under the hood, these types will keep track of the maximum possible value they might hold (this is the RANGE template parameter), and, if only SAFE operations (see below) are used, will automatically adjust there NI and NF to accomodate the result of a operation. It will also try not to promote there internal type when possible, assuFM_ming that you use the complete range of a given type.

The operations possible with these types can be divided into two categories:

Like standard C(++) types, the fixed point numbers defined here are following some rules:

More specifically on the returned types of the operations between fixed point math types:

Note on division: The division is not implemented. This is a deliberate choice made for two reasons:

Function Documentation

◆ operator!=() [1/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator!= ( const SFix< NI, NF > &  op1,
const UFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a SFix and an UFix.

Parameters
op1a SFix
op2A UFix
Returns
true if op1 is not equal to op2, false otherwise

◆ operator!=() [2/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator!= ( const UFix< NI, NF > &  op1,
const SFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a UFix and an SFix.

Parameters
op1a UFix
op2A SFix
Returns
true if op1 is not equal to op2, false otherwise

◆ operator<() [1/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator< ( const SFix< NI, NF > &  op1,
const UFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a SFix and an UFix.

Parameters
op1a SFix
op2A UFix
Returns
true if op1 is smaller than op2, false otherwise

◆ operator<() [2/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator< ( const UFix< NI, NF > &  op1,
const SFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a UFix and an SFix.

Parameters
op1a UFix
op2A SFix
Returns
true if op1 is smaller than op2, false otherwise

◆ operator==() [1/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator== ( const SFix< NI, NF > &  op1,
const UFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a SFix and an UFix.

Parameters
op1a SFix
op2A UFix
Returns
true if op1 is equal to op2, false otherwise

◆ operator==() [2/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator== ( const UFix< NI, NF > &  op1,
const SFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a UFix and an SFix.

Parameters
op1a UFix
op2A SFix
Returns
true if op1 is equal to op2, false otherwise

◆ operator>() [1/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator> ( const SFix< NI, NF > &  op1,
const UFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a SFix and an UFix.

Parameters
op1a SFix
op2A UFix
Returns
true if op1 is bigger than op2, false otherwise

◆ operator>() [2/2]

template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
constexpr bool operator> ( const UFix< NI, NF > &  op1,
const SFix< _NI, _NF > &  op2 
)
constexpr

Comparison between a UFix and an SFix.

Parameters
op1a UFix
op2A SFix
Returns
true if op1 is bigger than op2, false otherwise

◆ toSFraction()

template<typename T >
constexpr SFix<0, sizeof(T)*8-1> toSFraction ( val)
constexpr

Create a pure fractional signed fixed number (SFix) from an integer. The number of fractional bits (NF) is chosen automatically depending on the input type. Hence toSFraction(127) and toSFraction(int8_t(127)) do not lead to the same thing: on an AVR, the former will lead to NF=15 - which is overkill and incorrect if you expect toSFraction(127) = 1 - whereas the latter will lead to NF=7. Mozzi's objects (Oscil and the like) returns correct types, hence you can use this function to convert the return value of a Mozzi's function/class member into a pure fractional number.

Note
If the value is known at compile time, it is much more efficient to construct using SFixAuto(), and then shifting to the right.
Parameters
valThe value to be converted into a pure fractional number.
Returns
A SFix<0,NF> with NF chosen according to the input type

◆ toSInt()

template<typename T >
constexpr SFix<sizeof(T)*8-1,0> toSInt ( val)
constexpr

Create a pure integer signed fixed number (SFix) from an integer. The number of fractional bits (NI) is chosen automatically depending on the input type. Hence toSInt(127) and toSInt(int8_t(127)) do not lead to the same thing: on an AVR, the former will lead to NI=15 - which is overkill - whereas the latter will lead to NI=7. Mozzi's objects (Oscil and the like) returns correct types, hence you can use this function to convert the return value of a Mozzi's function/class member into a pure fractional number.

Note
If the value is known at compile time, it is much more efficient to construct using SFixAuto().
Parameters
valThe value to be converted into a pure integer fixed math number.
Returns
A SFix<NI,0> with NI chosen according to the input type

◆ toUFraction()

template<typename T >
constexpr UFix<0, sizeof(T)*8> toUFraction ( val)
inlineconstexpr

Create a pure fractional unsigned fixed number (UFix) from an unsigned integer. The number of fractional bits (NF) is chosen automatically depending on the input type. Hence toUFraction(255) and toUFraction(uint8_t(255)) do not lead to the same thing: on an AVR, the former will lead to NF=16 - which is overkill and incorrect if you expect toUFraction(255) = 1 - whereas the latter will lead to NF=8. Mozzi's objects (Oscil and the like) returns correct types, hence you can use this function to convert the return value of a Mozzi's function/class member into a pure fractional number.

Note
If the value is known at compile time, it is much more efficient to construct using UFixAuto(), and then shifting to the right.
Parameters
valThe value to be converted into a pure fractional number.
Returns
A UFix<0,NF> with NF chosen according to the input type

◆ toUInt()

template<typename T >
constexpr UFix<sizeof(T)*8,0> toUInt ( val)
inlineconstexpr

Create a pure integer unsigned fixed number (UFix) from an unsigned integer. The number of fractional bits (NI) is chosen automatically depending on the input type. Hence toUInt(255) and toUInt(uint8_t(255)) do not lead to the same thing: on an AVR, the former will lead to NI=16 - which is overkill - whereas the latter will lead to NI=8. Mozzi's objects (Oscil and the like) returns correct types, hence you can use this function to convert the return value of a Mozzi's function/class member into a pure fractional number.

Note
If the value is known at compile time, it is much more efficient to construct using UFixAuto().
Parameters
valThe value to be converted into a pure unsigned integer fixed math number.
Returns
A UFix<NI,0> with NI chosen according to the input type

◆ UFixAuto()

template<uint64_t value>
constexpr FixMathPrivate::UFixByRange_t<0, value> UFixAuto ( )
constexpr

Create a pure integer unsigned fix number (UFix) from a compile time constant. The number of integer bits needed is determined, automatically, based on the actual value. This allows to easily create constants requiring minimal storage, without counting bits, manually.

Examples:

auto three = UFixAuto<3>(); // UFix<2, 0>
auto ten_point_five = UFixAuto<21>().sR<1>(); // UFix<5, 1>
auto nearly_Pi = UFixAuto<201>().sR<6>(); // UFix<2, 6> = 3.140625