Go Down

Topic: ESP32 calculates floats faultily opp. to my M4 and my M3/Due (Read 2001 times) previous topic - next topic

MartinL

Quote
So maybe the ESP32 core doesn't have this macro.
I had a peek at the ESP32's "Arduino.h" file, it uses the same macro.

dsyleixa

https://github.com/arduino/reference-en/issues/362#issuecomment-478540338
So maybe the ESP32 core doesn't have this macro.
I had a peek at the ESP32's "Arduino.h" file, it uses the same macro.
no, although the macro existed, the ESP32 worked with standard <math.h> C code which requires fabs() for double and fabsf()  for float, basically like gcc for Linux too (which produce the same  faulty values by abs).

Quote
The weird thing is, the Arduino core on ESP32 has an abs() macro as well:
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/Arduino.h#L76

So there is probably a bug in the Arduino core for ESP32 here, where it isn't using the "Arduino-ified" abs() macro for some reason.
https://github.com/espressif/esp-idf/issues/3405#issuecomment-488872389

If you look at the github discussion, that could be resolved by a PR using std::abs() instead, which works correctly for either value type.
Instead, using Arduino macros for abs() is actually a bad practice.

MartinL

Thanks for the link, I followed it through to the pull request: https://github.com/espressif/arduino-esp32/pull/2738.

So seems that the ESP's abs() macro in the "Arduino.h" file is being subsequently overriden by another redefinition of macro. This redefinition is in the included <algorithm> file (which in turn calls on the <cstdlib>), a number of lines further down. The standard library's abs() doesn't process float data types.

This explains why the abs() macro in the "Arduino.h" file exists, but is never used.

dsyleixa

Quote
The standard library's abs() doesn't process float data types.
You are right, I stand corrected - I was confused by a chart table

abs() for fp is only since C++17, not for C++11 or C++14:
Quote
(since C++17)
float       abs( float arg );
  (1)   
double      abs( double arg );
Quote
std::abs(float), std::fabs, std::fabsf, std::fabsl

C++

Numerics library

Common mathematical functions

Defined in header <cmath>

Defined in header <cstdlib>

(since C++17)
float       abs( float arg );
(1)
double      abs( double arg );
(2)
long double abs( long double arg );
(3)
Defined in header <cmath>

(4)
float       fabs ( float arg );

float       fabsf( float arg );
(since C++11)
double      fabs ( double arg );
(5)
(6)
long double fabs ( long double arg );

long double fabsl( long double arg );
(since C++11)
double      fabs ( IntegralType arg );
(7) (since C++11)
https://en.cppreference.com/w/cpp/numeric/math/fabs


MartinL

Hi dsyleixa,

Thanks for investigating, that's interesting, I think it makes sense that they're chosing to effectively overload the abs() function, so that it will operate with float data types in C++17 in the future.

In the ESP32's "Arduino.h" file, I noticed that they moved the min() and max() macros to the bottom of the file (after the <algorithm> include). If the Arduino abs() macro definition:

Code: [Select]
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif

#define abs(x) ((x)>0?(x):-(x))

 ...is also moved to the bottom of the "Arduino.h" file as well, it effectively overrides the standard library's abs() function and your LunarLander code works with abs() oncemore.

In other words the Arduino abs() macro itself works just fine, it's just that it's currently in the wrong place in the ESP32's "Arduino.h" file.

MartinL

Looks like projectgus's pull request on Github also solves the issue, just by calling on:

Code: [Select]
using std::abs;
...in the "Arduino.h" file and deleting the Arduino macro. This redefines abs() using the C++ standard library function.

dsyleixa

Looks like projectgus's pull request on Github also solves the issue, just by calling on:

Code: [Select]
using std::abs;
...in the "Arduino.h" file and deleting the Arduino macro. This redefines abs() using the C++ standard library function.
yes, but my point was:
C++11 and C++14 also have std::abs just for ints and std::fabs and std::fabsf for floats !
Just C++17 has std::abs  both for ints and fps...
but does Arduino actually use C++17 ...?

pert

Arduino SAMD Boards is currently using C++11:
https://github.com/arduino/ArduinoCore-samd/blob/master/platform.txt#L42

The toolchain version currently in use doesn't even support C++17. However, there are plans to update the toolchain and use C++17 in the near future:
https://github.com/arduino/ArduinoCore-samd/issues/313

The ESP32 core for Arduino is also using C++11:
https://github.com/espressif/arduino-esp32/blob/master/platform.txt#L31

MartinL

Quote
C++11 and C++14 also have std::abs just for ints and std::fabs and std::fabsf for floats !
Just C++17 has std::abs  both for ints and fps...
but does Arduino actually use C++17 ...?
Yes, it's really confusing. I was also wondering why simply adding the "using std::abs;" line, allows the abs() function to work with floats, although the ESP32 is using C++11 (and not C++17).

After some investigation, I believe that the C++11's <cmath> file which is included in "Arduino.h", undefines the "abs" macro and redefines it as an overloaded function "std::abs" for a number of data types including floats.

The "using std::abs;" line allows "abs" to be used in lieu of any predefined macros, so that it isn't necessary to call "std::abs" in your sketch, but simply use "abs" instead.

dsyleixa

Yes, it's really confusing. I was also wondering why simply adding the "using std::abs;" line, allows the abs() function to work with floats, although the ESP32 is using C++11 (and not C++17).

After some investigation, I believe that the C++11's <cmath> file which is included in "Arduino.h", undefines the "abs" macro and redefines it as an overloaded function "std::abs" for a number of data types including floats.

The "using std::abs;" line allows "abs" to be used in lieu of any predefined macros, so that it isn't necessary to call "std::abs" in your sketch, but simply use "abs" instead.
it appears as if gpp already features the std::abs() for fp since C14 or even 11, opposite to C++ standards only since 17
https://gcc.godbolt.org/z/Flkq60
https://en.cppreference.com/w/cpp/numeric/math/fabs
https://github.com/espressif/esp-idf/issues/3405#issuecomment-489480050

MartinL

Quote
it appears as if gpp already features the std::abs() for fp since C14 or even 11, opposite to C++ standards only since 17
https://gcc.godbolt.org/z/Flkq60
https://en.cppreference.com/w/cpp/numeric/math/fabs
https://github.com/espressif/esp-idf/issues/3405#issuecomment-489480050
Thanks for the links regarding the GCC and C++.

Yes, it appears to be a complex mix of Arduino, compiler and C/C++ standards. Thanks for flagging this up on Github. At least situation is now sorted, or a least will be once ESP32's "Arduino.h" is officially updated.

Go Up