2015-12-11 8 views
5

私は単純なsine関数を、C++ 14 constexprを使ってコンパイル時に評価できるテイラー級数展開を使って構築しようとしています。私のコードはコンパイルされていますが、コンパイラは定数を生成しません。次のようにconstayprとしてのテイラー級数展開

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; 
} 

必要であれば、私はpowerfactorialためのコードを提供することができます。彼らは些細でもあり、またconstexprです。私はこのようなループ内からsineを呼んでいる

:私は、コンパイラはsineの結果のセットを生成し、実際にテイラー級数を計算するために必要とせずにoutにそれらを置くことができることを期待していた

template <int N> void test(double *out) { 
    for (int i = 0; i < N; ++i) { 
     out[i] = sine<20, double>(i * M_PI/N); 
    } 
} 

。その代わりに、生成されたコードは、sineを他の非constexpr関数のように実行します。

私のコンパイラはXcode 7.2のコンパイルで、-O3でコンパイルされています。

答えて

6

私は、コンパイラが サインのために結果のセットを生成し、実際に テイラー級数を計算するために必要とせずにアウトにそれらを置くことができることを期待していました。代わりに、生成されたコードは、それが 他の非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>{}); 
} 

Live Demo

+0

は、 '私はM_PI/N 'をsine''へ_argument_ *という問題ではなく、ISNコンステックス? – Eric

+0

@Eric "入力引数はすべて定数式でなければなりません。"十分に明確ではありませんか? – 101010

+0

私は "テストのforループの代入は定数式ではありません" _を参照していました。課題そのものはここで問題になっていますか? – Eric

関連する問題