FixMath
|
FixMath is a library to perform fixed point arithmetics. It uses integer types internally to provide fast computations of decimal numbers. As most micro-controllers do not have a floating point unit (FPU), this library allows fast computation of fractionnal numbers without resorting to floats.
This implements two fixed point types: UFix<NI,NF>
and SFix<NI,NF>
which are unsigned and signed respectively. The templates parameters NI
and NF
are the number of bits representing the integral and the fractionnal part, respectively.
The number of bits needed under the hood for the types implemented in this library, is statically determined by the compiler, for performance reasons, and all operations between fixed point types is safe (ie. it cannot overflow) as long as the number of underlying bits do not exceed 64 bits. On this aspect, they behave much like float
.
This library was original made for Mozzi.
A Doxygen documentation is available here and an overview of the library is given below.
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:
#define FIXMATH_UNSAFE
before including FixMath.h.Like standard C(++) types, the fixed point numbers defined here are following some rules:
FIXMATH_UNSAFE
set.More specifically on the returned types of the operations between fixed point math types:
UFix<NI,NF> + UFix<_NI,_NF>
returns UFix<MAX(NI,_NI)+1,MAX(NF,_NF)>
at worseSFix<NI,NF> + SFix<_NI,_NF>
returns SFix<MAX(NI,_NI)+1,MAX(NF,_NF)>
at worseUFix<NI,NF> + SFix<_NI,_NF>
returns SFix<MAX(NI,_NI)+1,MAX(NF,_NF)>
at worseUFix<NI,NF> + anything_else
(signed or not) returns UFix<NI,NF>
(only available with FIXMATH_UNSAFE
)SFix<NI,NF> + anything_else
(signed or not) returns SFix<NI,NF>
(only available with FIXMATH_UNSAFE
)UFix<NI,NF> - UFix<_NI,_NF>
returns SFix<MAX(NI,_NI),MAX(NF,_NF)>
at worseSFix<NI,NF> - SFix<_NI,_NF>
returns SFix<MAX(NI,_NI)+1,MAX(NF,_NF)>
at worseSFix<NI,NF> - UFix<_NI,_NF>
returns SFix<MAX(NI,_NI)+1,MAX(NF,_NF)>
at worseUFix<NI,NF> - anything_else
(signed or not) returns UFix<NI,NF>
(only available with FIXMATH_UNSAFE
)SFix<NI,NF> - anything_else
(signed or not) returns SFix<NI,NF>
(only available with FIXMATH_UNSAFE
)(-)SFix<NI,NF>
return SFix<NI,NF>
(-)UFix<NI,NF>
return SFix<NI,NF>
UFix<NI,NF> * UFix<_NI,_NF>
returns UFix<NI+_NI,NF+_NF>
at worseUFix<NI,NF> * SFix<_NI,_NF>
returns SFix<NI+_NI,NF+_NF>
at worseSFix<NI,NF> * SFix<_NI,_NF>
returns SFix<NI+_NI,NF+_NF>
at worseUFix<NI,NF> * anything_else
(signed or not) returns UFix<NI,NF>
(only available with FIXMATH_UNSAFE
)SFix<NI,NF> * anything_else
(signed or not) returns SFix<NI,NF>
(only available with FIXMATH_UNSAFE
)UFix<NI,NF>.invFast()
returns the inverse of the number as UFix<NF,NI>
SFix<NI,NF>.invFast()
returns the inverse of the number as SFix<NF,NI>
UFix<NI,NF>.invAccurate()
returns the inverse of the number as UFix<NF,2*NI+NF>
SFix<NI,NF>.invAccurate()
returns the inverse of the number as SFix<NF,2*NI+NF>
UFix<NI,NF>.inv<_NF>()
returns the inverse of the number as UFix<NF,_NF>
SFix<NI,NF>.inv<_NF>()
returns the inverse of the number as SFix<NF,_NF>
UFix<NI,NF>.asSFix()
returns SFix<NI,NF>
SFix<NI,NF>.asUFix()
returns UFix<NI,NF>
UFix<NI,NF>.asFloat()
returns the value as a float
SFix<NI,NF>.asFloat()
returns the value as a float
UFix<NI,NF>.asRaw()
returns the internal valueSFix<NI,NF>.asRaw()
returns the internal valueT.toUFraction()
returns UFix<0,NF>
with NF
the number of bits of T
(uint8_t
leads to NF=8
bits).T.toSFraction()
returns SFix<0,NF>
with NF
the number of bits of T
(int8_t
leads to NF=7
bits).T.toUInt()
returns UFix<NI,0>
with NI
the number of bits of T
(uint8_t
leads to NI=8
bits).T.toSInt()
returns SFix<NI,>
with NI
the number of bits of T
(int8_t
leads to NI=7
bits). Note on division: The division is not implemented. This is a deliberate choice made for two reasons:
updateControl()
, and use them in updateAudio()
.