On Fri, 7 Sep 2018 at 16:43, Xi Ruoyao wrote: > > On 2018-09-07 17:03 +0200, Marc Glisse wrote: > > On Sat, 8 Sep 2018, sisyphus1@xxxxxxxxxxxxxxx wrote: > > > > > Hi, > > > > > > The demo program: > > > > > > /****/ > > > /* try.c */ > > > #include <stdio.h> > > > #include <math.h> > > > > > > int main(void) { > > > > > > int x = -1074; > > > > > > printf("%e\n", pow (2.0, (double)x)); > > > printf("%e\n", pow (2.0, x)); > > > > > > return 0; > > > } > > > > > > /****/ > > > > > > If I build that program (using g++ version 7.3.0) with "g++ -ansi -o try > > > try.c" I get output of: > > > > > > 4.940656e-324 > > > 0.000000e+000 > > > > > > whereas I expected output to be: > > > > > > 4.940656e-324 > > > 4.940656e-324 > > > > > > I guess that means that either my expectation is buggy, or something else is > > > buggy. > > The "buggy" thing is > <https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Other-Builtins.html>: > > Built-in Function: double __builtin_powi (double, int) > Returns the first argument raised to the power of the second. Unlike the pow > function no guarantees about precision and rounding are made. > > GCC's <cmath> header do different thing for C++11 and C++03. In C++03, > `double std::pow(double, int)` is implemented by `__builtin_powi`. In C++11, > it is implemented by casting the second parameter to double, and then call > `pow(double, double)` from libc. > > The C++11 behavior is defined by 26.8 [c.math] para 11: > > > Moreover, there shall be additional overloads sufficient to ensure: > > 1. If any argument corresponding to a double parameter has type long > > double, then all arguments corresponding to double parameters are > > effectively cast to long double. > > 2. Otherwise, if any argument corresponding to a double parameter has > > type double or an integer type, then all arguments corresponding to > > double parameters are effectively cast to double. > > 3. Otherwise, all arguments corresponding to double parameters are > > effectively cast to float. > > And libstdc++ is doing right thing (casting the `int` parameter to > `double`). But C++03 is not so clear and does not define what should > libstdc++ do. Libstdc++ chooses to call __builtin_powi. Unfortunately > it is not so precise. > > > > Note 1: > > > If the "-ansi" switch is omitted, then the output matches my expectation. > > "-ansi" means "-std=c++98". Now GCC is defaulted to C++14. > > > Don't use -ansi, use -std= . Most likely you did not mean to use > > -std=c++98. > > > > The exact set of overloads of pow in the C++ standard has varied with > > time, https://en.cppreference.com/w/cpp/numeric/math/pow gives some idea. > > > > > Note 2: > > > If cmath is #included instead of math.h, then the output matches my > > > expectation. > > > > If you include cmath and not math.h, you should use std::pow. > > Yes. std::pow gives the same "buggy" output. > > But, I wonder why don't we change the C++98/03 `pow` behavior to be same > as C++11? This is still standard and is more precise. > > Jonathan how do you think? Maybe. I think that might resolve https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78851 too