O Fortran (projetado para computação científica) possui um operador de energia embutido e, até onde eu sei, os compiladores do Fortran geralmente otimizam o aumento para potências inteiras de maneira semelhante à que você descreve. Infelizmente, o C / C ++ não possui um operador de energia, apenas a função de biblioteca pow()
. Isso não impede que os compiladores inteligentes tratem pow
especialmente e o computem de maneira mais rápida em casos especiais, mas parece que eles fazem isso com menos frequência ...
Alguns anos atrás, eu estava tentando torná-lo mais conveniente para calcular potências inteiras da maneira ideal, e criei o seguinte. É C ++, não C, e ainda depende do compilador ser um pouco inteligente sobre como otimizar / incorporar coisas. De qualquer forma, espero que você ache útil na prática:
template<unsigned N> struct power_impl;
template<unsigned N> struct power_impl {
template<typename T>
static T calc(const T &x) {
if (N%2 == 0)
return power_impl<N/2>::calc(x*x);
else if (N%3 == 0)
return power_impl<N/3>::calc(x*x*x);
return power_impl<N-1>::calc(x)*x;
}
};
template<> struct power_impl<0> {
template<typename T>
static T calc(const T &) { return 1; }
};
template<unsigned N, typename T>
inline T power(const T &x) {
return power_impl<N>::calc(x);
}
Esclarecimento para os curiosos: isso não encontra a maneira ideal de calcular potências, mas como encontrar a solução ideal é um problema completo de NP e vale a pena fazer para potências pequenas de qualquer maneira (ao contrário de usar pow
), não há razão para se preocupar com o detalhe.
Então apenas use-o como power<6>(a)
.
Isso facilita a digitação de poderes (não é necessário especificar 6 a
s com parênteses) e permite que você tenha esse tipo de otimização sem -ffast-math
ter algo dependente da precisão, como a soma compensada (um exemplo em que a ordem das operações é essencial) .
Você provavelmente também pode esquecer que este é C ++ e apenas usá-lo no programa C (se compilar com um compilador C ++).
Espero que isso possa ser útil.
EDITAR:
Isto é o que recebo do meu compilador:
Para a*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
Para (a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
Para power<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1