Fortran (được thiết kế cho máy tính khoa học) có một nhà điều hành năng lượng tích hợp và theo như tôi biết, trình biên dịch Fortran thường sẽ tối ưu hóa việc nâng lên các số nguyên theo cách tương tự như những gì bạn mô tả. Thật không may, C / C ++ không có toán tử nguồn, chỉ có chức năng thư viện pow()
. Điều này không ngăn các trình biên dịch thông minh xử lý pow
đặc biệt và tính toán nó theo cách nhanh hơn cho các trường hợp đặc biệt, nhưng có vẻ như chúng làm điều đó ít phổ biến hơn ...
Vài năm trước tôi đã cố gắng làm cho nó thuận tiện hơn để tính toán các số nguyên theo cách tối ưu, và đã đưa ra những điều sau đây. Đó là C ++, không phải C, và vẫn phụ thuộc vào trình biên dịch có phần thông minh về cách tối ưu hóa / nội tuyến. Dù sao, hy vọng bạn có thể thấy nó hữu ích trong thực tế:
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);
}
Làm rõ cho người tò mò: điều này không tìm ra cách tối ưu để tính toán sức mạnh, nhưng vì việc tìm ra giải pháp tối ưu là một vấn đề hoàn chỉnh NP và điều này chỉ đáng làm đối với các quyền lực nhỏ (trái ngược với việc sử dụng pow
), không có lý do gì để làm phiền với các chi tiết.
Sau đó chỉ cần sử dụng nó như power<6>(a)
.
Điều này giúp bạn dễ dàng nhập các quyền hạn (không cần phải đánh vần 6 a
giây bằng parens) và cho phép bạn có loại tối ưu hóa này mà không cần -ffast-math
trong trường hợp bạn có thứ gì đó phụ thuộc chính xác như tổng bù (một ví dụ trong đó thứ tự hoạt động là cần thiết) .
Có lẽ bạn cũng có thể quên rằng đây là C ++ và chỉ sử dụng nó trong chương trình C (nếu nó biên dịch với trình biên dịch C ++).
Hy vọng điều này có thể hữu ích.
BIÊN TẬP:
Đây là những gì tôi nhận được từ trình biên dịch của mình:
Đối với a*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
Đối với (a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
Đối với power<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1