Tim*_*Tim 4 c++ trigonometry taylor-series constexpr c++14
我正在尝试sine使用泰勒系列扩展构建一个简单的函数,可以在编译时使用C++ 14进行评估constexpr.我的代码正在编译,但编译器不会生成常量.
sine 定义如下:
template <int P, typename T = double> constexpr T sine(T x) {
T result = x;
for (int i = 1; i < P; ++i)
result += power<T>(-1, i) * power<T>(x, 1 + 2 * i) / factorial<T>(1 + 2 * i);
return result;
}
Run Code Online (Sandbox Code Playgroud)
我可以提供代码power,factorial如果需要的话.它们是微不足道的constexpr.
我sine在这样的循环中调用:
template <int N> void test(double *out) {
for (int i = 0; i < N; ++i) {
out[i] = sine<20, double>(i * M_PI / N);
}
}
Run Code Online (Sandbox Code Playgroud)
我期待编译器可以生成一组结果sine并将其放入,out而不需要实际计算泰勒系列.相反,生成的代码sine就像执行任何其他非constexpr函数一样执行.
我的编译器是从Xcode 7.2编译而来的-O3.
我期待编译器可以为正弦生成一组结果并将它们放入,而不需要实际计算泰勒系列.相反,生成的代码执行正弦,就像它是任何其他非constexpr函数一样.
要constexpr在编译时评估函数,必须满足以下条件:
test'for循环中的赋值不是常量表达式.因此,sine无法在编译时进行评估.
你真正想要的是使用静态初始化数组的元素sine().使用一个std::array和一些辅助机械可以这样做,如下所示:
#define r 0.01745329251
constexpr double factorial(int n) {
double res = 1.0;
for(int i(2); i <= n; ++i) res *= i;
return res;
}
template<typename T>
constexpr T power(T &&base, int const n) {
if(!n) return 0.0;
T res = base;
for(int i(1); i < n; ++i) res *= base;
return res;
}
template <typename T, int N = 5>
constexpr T sine(T &&x) {
T res = x * r;
for (int i(3), sgn(-1); i <= N; i += 2, sgn = -sgn) {
res += power(x * r, i) / factorial(i);
}
return res;
}
template <class T, std::size_t N, std::size_t... Is>
constexpr std::array<T, N> sine_array_impl(std::index_sequence<Is...>) {
return {{sine(T{Is})...}};
}
template <class T, std::size_t N>
constexpr std::array<T, N> sine_array() {
return sine_array_impl<T, N>(std::make_index_sequence<N>{});
}
Run Code Online (Sandbox Code Playgroud)