Why is `abs()` implemented differently?

C++GccCompilationClang

C++ Problem Overview


I've had a super frustrating bug in my code for the past few weeks. My code would work exactly as expected on my computer, but as soon as I farmed it out to the HPC server, it would produce weird results.

I've boiled it down to this: on my computer (iMac) the function abs() works with floating point numbers, but on the server abs() truncates it to an integer.

Example:

Server

abs(-1.1341234) = 1

My Mac

abs(-1.1341234) = 1.1341234

Now I know I can fix this by using fabs(), that's not the question. I looked at the versions of gcc on either machine and this is the output:

Server

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/apps/software/GCCcore/5.4.0/libexec/gcc/x86_64-unknown-linux-gnu/5.4.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --enable-languages=c,c++,fortran --enable-lto --enable-checking=release --disable-multilib --enable-shared=yes --enable-static=yes --enable-threads=posix --enable-gold=default --enable-plugins --enable-ld --with-plugin-ld=ld.gold --prefix=/apps/software/GCCcore/5.4.0 --with-local-prefix=/apps/software/GCCcore/5.4.0 --enable-bootstrap --with-isl=/dev/shm/GCCcore/5.4.0/dummy-/gcc-5.4.0/stage2_stuff
Thread model: posix
gcc version 5.4.0 (GCC) 

My Mac

g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.3)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

So my question, why does abs() produce different results between gcc and clang? This issue literally cost me 3 weeks of progress, so as you can imagine I'm a little salty just now...

C++ Solutions


Solution 1 - C++

You must use std::abs, which has overloads for the primitive types.

You are falling through to the C++ version in one case, and the old C version (which converts its parameters to integral types) in the other.

Things to avoid: (1) using namespace std; (here is why) and (2) not having the appropriate #includes to bring in the functionality you need. Don't rely on C++ standard library implementations to include files for you implicitly.

Some compilers will warn you of a "lossy" conversion if you set the warning level appropriately.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBambooView Question on Stackoverflow
Solution 1 - C++BathshebaView Answer on Stackoverflow