Pregunta

In C++ 03, using e.g. std::pow(double_val, 6) was considerably faster than using std::pow(double_val, 6.0).

This is no longer the case when compiling with C++11. Looking at the cmath header from gcc's libstdc++-4.8, one can see an explicit pow(double, int) is no longer present, this case is handled by the following template which promotes the int to a double:

template<typename _Tp, typename _Up>
inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
pow(_Tp __x, _Up __y) {
  typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
  return std::pow(__type(__x), __type(__y));
}

Is this behavior in the C++11 standard or could future libstdc++ implementations return to the faster method?

Secondly, if for standard or implementation reasons the faster behavior is no longer possible, what is the most portable way to achieve it again? I see a power(...) function in the gcc stdlibc++ under "ext/numeric", but this is marked as a non-standard SGI(rip) extension.

¿Fue útil?

Solución

First of all, yes this behaviour is consistent with the C++11 standard (though not with C++03), which in section 26.8, paragraph 11 says:

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.

(In addition to the overloads for float-only, double-only and long double-only.)

So the implementation actually has to cast that integer argument into a double and I don't think there is a possibility for a conforming library to provide a faster std::pow for integer powers, apart from maybe checking the double argument for integrality (is that a word?) and using a special path in this case.

In order to provide a platform-independent faster way, the only thing that comes to my mind would be to write a custom wrapper that delegates to this non-standard power if it is present. Other than that I don't know how you could infuse that behaviour into std::pow again without writing your own implementation.

EDIT: Yet when looking at this answer it is indeed possible for an implementation to still provide an optimized overload for integer powers as long as it behaves exactly like std::pow(double(x), double(y)). So there is a possiblity for an implementation to provide that faster version, yet I wouldn't count so much on this as you have done in C++03 (where it was IMHO even part of the standard, but I might be wrong).

Otros consejos

C provides just the double pow(double, double) overload (recall that C doesn't allow function overloading anyway). The C++11 standard (26.8/9) says that the following overloads are added (in addition to C's) to namespace std:

float pow(float, float);
long double pow(long double, long double);

Hence, double pow(double, int) is an extension rather than a standard function. Therefore an implementation might provide it or not.

Edit After Christian Rau comment and answer.

Now I believe the overload must be there. Hence, there should be a double pow(double, int) overload. However, this overload must (as he says in his answer) cast the int to a double and call double pow(double, double).

Actually there are a lot of overloads. The easiest way to provide them is not as normal functions but as a template function exactly as the libstdc++ implementation shown in the OP.

See also this open issue where Howard Hinnant explains the details.

Finally the link provided by Hulk is very relevant and Howard Hinnant (again) explains that there's almost no reason to provide an optimized overload that does anything different from casting the intto the double.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top