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).
Це полегшує набір повноважень (не потрібно писати 6 a набір с за допомогою паролів), і дозволяє вам здійснити подібну оптимізацію без -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