Fortran(科学計算用に設計されています)にはべき乗演算子が組み込まれており、私が知る限り、Fortranコンパイラーは通常、整数のべき乗に最適化します。C / C ++には、残念ながらパワーオペレーターがありませんpow()
。ライブラリ関数のみです。これは、スマートコンパイラがpow
特別に処理し、特別な場合にそれをより高速に計算することを妨げませんが、あまり一般的ではないようです...
数年前、整数のべき乗を最適な方法で計算することをより便利にするために、次のことを思いつきました。それはCではなくC ++ですが、最適化/インライン化の方法についてコンパイラがいくらか賢いことに依存しています。とにかく、実際に役立つと思います:
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);
}
好奇心の明確化:これはべき乗を計算する最適な方法を見つけませんが、最適な解決策を見つけることはNP完全な問題であり、これはいずれにせよ(を使用pow
するのではなく)小さな力に対してのみ行う価値があるため、混乱する理由はありません。ディテール付き。
次に、そのまま使用しますpower<6>(a)
。
これにより、累乗を簡単に入力できるようになり(a
括弧で6 秒を入力する必要はありません)、補正された合計(演算の順序が不可欠な例)-ffast-math
など、精度に依存するものがない場合でも、この種の最適化を行うことができます。。
また、これがC ++であることを忘れて、Cプログラムで使用することもできます(C ++コンパイラでコンパイルする場合)。
これが役立つことを願っています。
編集:
これは私のコンパイラから得られるものです:
の場合a*a*a*a*a*a
、
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
の場合(a*a*a)*(a*a*a)
、
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
の場合power<6>(a)
、
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1