Fortran (bilimsel hesaplama için tasarlanmış) yerleşik bir güç operatörüne sahiptir ve bildiğim kadarıyla Fortran derleyicileri, tamsayı güçlere yükseltmeyi tanımladığınız şekilde benzer şekilde optimize eder. C / C ++ maalesef bir güç operatörü yok, sadece kütüphane fonksiyonu pow()
. Bu, akıllı derleyicilerin pow
özel davranmasını ve özel durumlar için daha hızlı bir şekilde hesaplamasını engellemez , ancak daha az sıklıkta yaptıkları anlaşılıyor ...
Birkaç yıl önce tamsayı güçlerini en uygun şekilde hesaplamayı daha uygun hale getirmeye çalışıyordum ve aşağıdakileri buldum. C ++ değil, C değil ve yine de derleyicinin şeyleri nasıl optimize edeceği / satılacağı konusunda biraz akıllı olmasına bağlı. Her neyse, umarım pratikte faydalı bulabilirsin:
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);
}
Meraklılar için açıklama: Bu, güçleri hesaplamak için en uygun yolu bulmaz, ancak en uygun çözümü bulmak NP-tam bir problemdir ve bu sadece küçük güçler için yapmaya değer (kullanmanın aksine)pow
), karışıklık için bir neden yoktur detay ile.
Sonra sadece power<6>(a)
.
Bu, güç a
yazmayı kolaylaştırır ( parens ile 6 sn yazmanıza gerek yoktur ) ve telafi toplamı-ffast-math
gibi hassas bir şeye sahip olmanız durumunda bu tür bir optimizasyona sahip olmanızı sağlar (işlem sırasının gerekli olduğu bir örnek) .
Muhtemelen bunun C ++ olduğunu unutabilir ve sadece C programında kullanabilirsiniz (eğer bir C ++ derleyicisi ile derlenirse).
Umarım bu yararlı olabilir.
DÜZENLE:
Derleyicimden aldığım şey bu:
İçin a*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
İçin (a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
İçin power<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1