I was reading GCC documentation on Fixed-point types from this link , but it seems GCC is not Elaborating on so many things which left me with many questions in my head
- first of all they, said
The fixed-point types are short _Fract, _Fract, long _Fract, long long _Fract, unsigned short _Fract, unsigned _Fract, unsigned long _Fract, unsigned long long _Fract, _Sat short _Fract, _Sat _Fract, _Sat long _Fract, _Sat long long _Fract, _Sat unsigned short _Fract, _Sat unsigned _Fract, _Sat unsigned long _Fract, _Sat unsigned long long _Fract, short _Accum, _Accum, long _Accum, long long _Accum, unsigned short _Accum, unsigned _Accum, unsigned long _Accum, unsigned long long _Accum, _Sat short _Accum, _Sat _Accum, _Sat long _Accum, _Sat long long _Accum, _Sat unsigned short _Accum, _Sat unsigned _Accum, _Sat unsigned long _Accum, _Sat unsigned long long _Accum.
so what are the differences between
- _Fract
- _Sat
- _Accum
since the fixed point types are just combination between primitive data type and the above 3 key works ,so what is the difference when I write short _Fract x;
or short _Accum x;
? and what does keyword _Sat add to the definition of the variable ? like what is the difference between _Sat _Fract x;
and _Sat _Accum x;
? as GCC didn't state anything about this thing ,
also they said:
Not all targets support fixed-point types.
so I couldn't test anything from the above types on my host machines as it gives me error stating that fixed-point types not supported for this target
- I have read about Decimal , float and Fixed-Point types
all of the above are just different representations of decimal with fraction numbers , from my understand they are just like:
- Decimal representation gives lower accuracy but higher range with big numbers , most 2 used standards are binary integer decimal (BID) and densely packed decimal (DPD)
- float and doubles gives higher accuracy than Decimal when talking about big numbers but lower range ,they follow IEEE 754 standard
- Fixed-Point types have the lowest range but they are the most accurate one
please correct me if I am wrong on the above 3 lines , so my question is as follow , in the narrow range of small numbers like when we are talking about Fixed-Point types , they provide high accuracy but also Decimals can be used instead of them in that small range and Decimals will provide same accuracy as nearly as Fixed-Point types , Decimals only lacks accuracy when numbers become big , so why we use Fixed-Point types ? as it will give us only small range of numbers and decimal can replace it in terms of accuracy in that small range of numbers.
CodePudding user response:
See https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf and https://en.wikipedia.org/wiki/Q_(number_format) .
what is the difference when I write short _Fract x; or short _Accum x; ?
short _Fract
would be a variable 1 sign bit and 15 fraction bits, short _Accum
would be a variable with 1 sign bit, 8 integer bits and 7 fraction bits. (Most commonly)
Different compilers have different sizes: https://onlinedocs.microchip.com/pr/GUID-C4E60FF5-3DAB-44F1-BA61-4BD962D8F469-en-US-1/index.html?GUID-8856FDD7-C356-499B-9B39-8F7304854058 . I saw such a list for GCC of all fixed-point types, but I can't find it.
what is the difference between them ?
The difference is in the representation, which translates into a different range and resolution of representable values. They have different count of integer and fraction bits.
what does keyword _Sat add to the definition of the variable ?
_Sat
comes from saturating fixed-point type. When you do UINT_MAX 1
it becomes 0, because it wraps around. In pseudocode, like (_Sat UINT_MAX) 1
would be equal to UINT_MAX
. It "saturates", not wraps around.
fixed-point types not supported for this target
So use a different target. For example, the following program:
#include <stdfix.h>
#include <stdio.h>
int main() {
_Fract unsigned a = UFRACT_MAX;
_Fract unsigned b = a 0.1;
_Sat _Fract unsigned c = UFRACT_MAX;
_Sat _Fract unsigned d = c 0.1;
printf("a=%f a 0.1=%f\n", (float)a, (float)b); // b "wrapped around"
printf("c=%f c 0.1=%f\n", (float)c, (float)d); // d is "capped to max"
}
Can be executed like the following:
$ arm-none-eabi-gcc -ufloat_print --specs=rdimon.specs 1.c && qemu-arm ./a.out
a=0.999985 a 0.1=0.099976
c=0.999985 c 0.1=0.999985
why we use Fixed-Point types ?
Speed. Calculating float * float
is super hard and slow. Calculating int * int
is superfast. Calculating fixed-point * fixed-point
is exactly as fast as int * int
.