Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `abs()` implemented differently?

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...

like image 880
Phill Avatar asked Apr 30 '19 08:04

Phill


1 Answers

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.

like image 84
Bathsheba Avatar answered Nov 16 '22 06:11

Bathsheba