Search code examples
cgccarmtexas-instrumentscortex-a8

Is there a way to port "best type" floating-point constants from a micro to another?


In my specific case, I firstly developed a program to run in a Texas Instruments microcontroller (TMS320F28335). It was a real time synchronous generator simulator so it needed to perform an important amount of floating-point operations. I did not specify any suffix for floating-point constants so they were treated as doubles (I guess that what the C standards says) but the compiler provided by Texas Instruments implements those doubles as 32 bits floating-point numbers so the FPU of the microcontroller was used (see Table 6-1 from the compiler user's guide) in an efficient way let's say. Then, I had to port that program to a BeagleBone Black with an embedded linux (patched for the real time requirements). Of course, all the constants were treated again as doubles by the compiler (GCC), but in this case that did not mean 32 bits floating-point numbers but 64 bits floating-point numbers. I do not fully understand how the FPU of the ARM Cortex A8 works but as far as I read (and since it is a 32 bits processor), performance would be improved if those floating-point constants were treated as 32 bits floating-point numbers. So, all of this led me to the question: is there a way to make more portable "best type" floating-point constants? In this case, I would have solve the problem by adding the "f" suffix to every constant because both processors are more efficient (I guess) treating with float, but if I am developing something in an amd64 PC and I want to port that to a 32 bits microcontroller, is there a way to add some suffix that could be changed to be "f" for 32 bits microcontrollers and "l" for an amd64 PC? I thought of something like this (of course, it doesn't work):

architecture-dependant header file for 32 bits microcontroller:

#define BEST_TYPE f
.
.
.

architecture-dependant header file for amd64 PC:

#define BEST_TYPE l
.
.
.

architecture-independent source file:

.
.
.
a = b * 0.1BEST_TYPE;
.
.
.

To clarify, by "best type" I meant the more precise numeric data type supported by the FPU of the microprocessor.


Solution

  • The question requests something similar to the macros in C 2018 7.20.4, “Macros for integer constants.” These macros, such as UINT64_C(value), expand to integer constants suitable for initializing objects with the corresponding type.

    If we look at the <stdint.h> supplied with Xcode 11 for macOS 10.14, we see the implementations simply append a suffix that indicates the type (or does nothing, if the value will have the desired type by default):

    #define UINT8_C(v)   (v)
    #define UINT16_C(v)  (v)
    #define UINT32_C(v)  (v ## U)
    #define UINT64_C(v)  (v ## ULL)
    

    We can use this as guidance for a similar macro for floating-point types, using one of:

    #define MyFloatType_C(v)   (v ## f)
    #define MyFloatType_C(v)   (v)
    #define MyFloatType_C(v)   (v ## l)
    

    Which definition of the macro to use could be chosen by various compile-time means, such as testing preprocessor macros (that are either built into the compiler to describe the target or that are explicitly passed on the command line).