Fortran (conçu pour le calcul scientifique) a un opérateur de puissance intégré, et pour autant que je sache, les compilateurs Fortran optimisent généralement l'augmentation des puissances entières d'une manière similaire à ce que vous décrivez. C / C ++ n'a malheureusement pas d'opérateur de puissance, seulement la fonction de bibliothèque pow()
. Cela n'empêche pas les compilateurs intelligents de les traiter pow
spécialement et de les calculer plus rapidement pour des cas particuliers, mais il semble qu'ils le fassent moins souvent ...
Il y a quelques années, j'essayais de rendre plus pratique le calcul optimal des puissances entières, et j'ai proposé ce qui suit. C'est du C ++, pas du C cependant, et cela dépend toujours du fait que le compilateur soit quelque peu intelligent sur la façon d'optimiser / incorporer les choses. Quoi qu'il en soit, j'espère que cela vous sera utile dans la pratique:
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);
}
Clarification pour les curieux: cela ne trouve pas le moyen optimal de calculer les puissances, mais comme la recherche de la solution optimale est un problème NP-complet et que cela ne vaut de toute façon que pour les petites puissances (par opposition à l'utilisation pow
), il n'y a aucune raison de s'inquiéter avec le détail.
Ensuite, utilisez-le simplement comme power<6>(a)
.
Cela facilite la saisie des pouvoirs (pas besoin d'énoncer 6 a
s avec des parens), et vous permet d'avoir ce type d'optimisation sans -ffast-math
au cas où vous auriez quelque chose qui dépend de la précision comme la sommation compensée (un exemple où l'ordre des opérations est essentiel) .
Vous pouvez aussi probablement oublier qu'il s'agit de C ++ et simplement l'utiliser dans le programme C (s'il compile avec un compilateur C ++).
J'espère que cela peut être utile.
ÉDITER:
Voici ce que j'obtiens de mon compilateur:
Pour a*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
Pour (a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
Pour power<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1