anderkve / FYS3150

https://anderkve.github.io/FYS3150
26 stars 14 forks source link

Clang and G++ can giving different results #57

Closed Daniel-Haas-B closed 2 years ago

Daniel-Haas-B commented 2 years ago

Hi! I am aware that project 2 has already passed, but this might be useful in the future nonetheless.

For the Jacobi rotation algorithm, half of my group (Linux users only) experienced a weird bug: the while loop check for whether the absolute value of the max off-diagonal term was bigger than the threshold epsilon was not behaving properly.

Despite having an epsilon value of 10e-8, the algorithm would return an R matrix with off-diagonal elements of 10e-4 (the code was effectively stopping earlier than desired, but not giving any errors). We later found out the reason for the discrepancy.

The threshold checking involves taking the absolute value of the off-diagonal elements. For this, we only used "abs(arg)", instead of "cmath::abs(arg)" or even "std::abs(arg)". Since we didn't state the namespace explicitly, each compiler then understood what they wanted to. The correct here is to use "std::abs(arg)" (or fabs), otherwise, the absolute value returns an int.

Apparently, this has to do with math.h using the C language abs, which returns an integer. I just don't understand why g++ was actually using math.h since we explicitly included cmath in the header.

Here is a related post on StackOverflow addressing the issue.

anderkve commented 2 years ago

Hi @Daniel-Haas-B!

Thanks a lot for the summary -- very useful to have for future reference. I'm sure more people will encounter this.

For more details on this issue, see also this StackOverflow post: https://stackoverflow.com/questions/21392627/abs-vs-stdabs-what-does-the-reference-say

Long story short: it's a messy part of C/C++ history, and the safe C++ option is to explicitly use std::abs.