#include <tgmath.h>
#include <iostream>
int main(int argc, char** argv) {
#define NUM1 -0.031679909079365576
#define NUM2 -0.11491794452567111
std::cout << "double precision :"<< std::endl;
typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10);
std::cout << std::hypot((double)NUM1, (double)NUM2);
std::cout << " VS sqrt :" << sqrt((double )NUM1*(double )NUM1
+ (double )NUM2*(double )NUM2) << std::endl;
std::cout << "long double precision :"<< std::endl;
typedef std::numeric_limits<long double > ldbl;
std::cout.precision(ldbl::max_digits10);
std::cout << std::hypot((long double)NUM1, (long double)NUM2);
std::cout << " VS sqrt :" << sqrt((long double )NUM1*(long double )NUM1 + (long double )NUM2*(long double )NUM2);
}
Returns under Linux (Ubuntu 18.04 clang or gcc, whatever optimisation, glic 2.25):
double precision : 0.1192046585217293 VS sqrt :0.11920465852172932
long double precision : 0.119204658521729311251 VS sqrt :0.119204658521729311251
According to the cppreference :
Implementations usually guarantee precision of less than 1 ulp (units in the last place): GNU, BSD, Open64 std::hypot(x, y) is equivalent to std::abs(std::complex(x,y)) POSIX specifies that underflow may only occur when both arguments are subnormal and the correct result is also subnormal (this forbids naive implementations)
So, hypot((double)NUM1, (double)NUM2) should return 0.11920465852172932, i suppose (as naive sqrt implementation). On windows, using MSVC 64 bit, this is the case.
Why do we see this difference using glibc ? How is it possible to solve this inconsistency ?