studio - que es m_pi en c++
En C++ 11, ¿sqrt se define como constexpr? (5)
A continuación se muestra una implementación de raíz cuadrada constexpr que utiliza la búsqueda binaria. Funciona correctamente hasta 2 ^ 64 con gcc y clang, otras versiones más simples a menudo fallan para números> 2 ^ 32 porque los compiladores limitan la profundidad de recursión a, por ejemplo, 200.
// C++11 compile time square root using binary search
#define MID ((lo + hi + 1) / 2)
constexpr uint64_t sqrt_helper(uint64_t x, uint64_t lo, uint64_t hi)
{
return lo == hi ? lo : ((x / MID < MID)
? sqrt_helper(x, lo, MID - 1) : sqrt_helper(x, MID, hi));
}
constexpr uint64_t ct_sqrt(uint64_t x)
{
return sqrt_helper(x, 0, x / 2 + 1);
}
A continuación se muestra una versión más agradable (para las constantes enteras) que requiere C ++ 14, es similar a la presentada en la publicación de blog de Baptiste Wicht. Las funciones constexpr de C ++ 14 pueden usar variables locales y sentencias if.
// C++14 compile time square root using binary search
template <typename T>
constexpr T sqrt_helper(T x, T lo, T hi)
{
if (lo == hi)
return lo;
const T mid = (lo + hi + 1) / 2;
if (x / mid < mid)
return sqrt_helper<T>(x, lo, mid - 1);
else
return sqrt_helper(x, mid, hi);
}
template <typename T>
constexpr T ct_sqrt(T x)
{
return sqrt_helper<T>(x, 0, x / 2 + 1);
}
En C ++ 11 std::sqrt
define como constexpr
, es decir, ¿puede usarse legalmente desde otras funciones constexpr
o en contextos de tiempo de compilación como tamaños de matriz o argumentos de plantilla? g ++ parece permitirlo (usando -std=c++0x
), pero no estoy seguro de poder tomar eso como autoritario dado que el soporte de c ++ 0x / c ++ 11 aún está incompleto. El hecho de que parece que no puedo encontrar nada en Internet me hace dudar.
Parece que esto debería ser algo que uno pueda descubrir fácilmente usando Google, pero lo he intentado (durante 40 minutos ...) y no pude encontrar nada. Pude encontrar varias propuestas para agregar constexpr a varias partes de la biblioteca estándar (como, por ejemplo, esta ), pero nada sobre sqrt
u otras funciones matemáticas.
Aquí hay una implementación constexpr rápida y eficiente para números de double
punto flotante. También puede adaptarlo para float
, si es necesario:
#include <limits>
namespace Detail
{
double constexpr sqrtNewtonRaphson(double x, double curr, double prev)
{
return curr == prev
? curr
: sqrtNewtonRaphson(x, 0.5 * (curr + x / curr), curr);
}
}
/*
* Constexpr version of the square root
* Return value:
* - For a finite and non-negative value of "x", returns an approximation for the square root of "x"
* - Otherwise, returns NaN
*/
double constexpr sqrt(double x)
{
return x >= 0 && x < std::numeric_limits<double>::infinity()
? Detail::sqrtNewtonRaphson(x, x, 0)
: std::numeric_limits<double>::quiet_NaN();
}
En caso de que alguien esté interesado en una función de raíz cuadrada meta-entera, aquí hay una que escribí hace tiempo:
constexpr std::size_t isqrt_impl
(std::size_t sq, std::size_t dlt, std::size_t value){
return sq <= value ?
isqrt_impl(sq+dlt, dlt+2, value) : (dlt >> 1) - 1;
}
constexpr std::size_t isqrt(std::size_t value){
return isqrt_impl(1, 3, value);
}
Si observamos el anteproyecto estándar más cercano a C ++ 11 N3337 , podemos ver que sqrt
no está marcado constexpr , en la sección 26.8
c.math :
El contenido de estos encabezados es el mismo que el de los encabezados de biblioteca de C estándar y, respectivamente, con los siguientes cambios:
ninguno de los cambios incluye agregar constexpr a sqrt
.
Podemos ver a partir de la pregunta si gcc considera que las funciones integradas de expresión no constantes son expresiones constantes , que gcc
marca muchas funciones matemáticas como constexpr como una extensión. Esta extensión es una extensión no conforme , como señalo en mi respuesta a la pregunta vinculada cuando gcc
implementó esto parecía que sería una extensión conforme, pero esto cambió y es probable que gcc
corrija esta extensión para que sea conforme.
std::sqrt
no se define como constexpr
, según la sección 26.8 de N3291: C ++ 11 FDIS (y dudo que lo hayan agregado al estándar final después de eso). Uno podría escribir tal versión, pero la versión estándar de la biblioteca no es constexpr
.