Fortran (dirancang untuk komputasi ilmiah) memiliki operator daya bawaan, dan sejauh yang saya tahu kompiler Fortran biasanya akan mengoptimalkan peningkatan daya integer dengan cara yang mirip dengan yang Anda gambarkan. C / C ++ sayangnya tidak memiliki operator listrik, hanya fungsi perpustakaan pow()
. Ini tidak mencegah kompiler pintar memperlakukan pow
khusus dan menghitungnya dengan cara yang lebih cepat untuk kasus khusus, tetapi tampaknya mereka melakukannya lebih jarang ...
Beberapa tahun yang lalu saya mencoba membuatnya lebih nyaman untuk menghitung kekuatan bilangan bulat secara optimal, dan muncul sebagai berikut. Ini C ++, bukan C, dan masih tergantung pada kompiler yang agak pintar tentang cara mengoptimalkan / inline sesuatu. Ngomong-ngomong, semoga bermanfaat dalam praktik:
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);
}
Klarifikasi untuk yang penasaran: ini tidak menemukan cara optimal untuk menghitung kekuatan, tetapi karena menemukan solusi optimal adalah masalah NP-complete dan ini hanya layak dilakukan untuk kekuatan kecil (bukan menggunakan pow
), tidak ada alasan untuk meributkan dengan detail.
Kemudian gunakan saja sebagai power<6>(a)
.
Ini membuatnya mudah untuk mengetikkan kekuatan (tidak perlu menjelaskan 6 a
detik dengan parens), dan memungkinkan Anda memiliki optimasi semacam ini tanpa -ffast-math
seandainya Anda memiliki sesuatu yang bergantung pada ketelitian seperti penjumlahan terkompensasi (contoh di mana urutan operasi sangat penting) .
Anda mungkin juga bisa lupa bahwa ini adalah C ++ dan hanya menggunakannya dalam program C (jika dikompilasi dengan kompiler C ++).
Semoga ini bisa bermanfaat.
EDIT:
Ini yang saya dapatkan dari kompiler saya:
Untuk a*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
Untuk (a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
Untuk power<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1