2015-12-11 16 views
5

Ben C++ 14 constexpr kullanarak derleme zamanında değerlendirilebilen taylor seri genişletme kullanarak basit bir sine işlevini oluşturmaya çalışıyorum. Kodum derleniyor, ancak derleyici sabit oluşturmuyor. GerekirseConstexpr olarak Taylor serisi genişletme

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

I power için kod sağlamak ve factorial aşağıdaki şekilde gösterilir:

sine tanımlanır. Onlar önemsiz ve ayrıca constexpr. Böyle bir döngü içinde sine arıyorum

: Ben derleyici sine ilişkin sonuçların bir dizi üretmek ve aslında Taylor serisi hesaplamak gerek kalmadan out içine koydu ki bekliyordum

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

. Bunun yerine, oluşturulan kod sine'u constexpr dışındaki herhangi bir işlev gibi çalıştırır.

Derleyicim, Xcode 7.2'den gelen ve -O3 ile derlenen bir dizedir.

cevap

6

Ben derleyici sinüs ilişkin sonuçların bir dizi üretmek ve aslında Taylor serisi hesaplamak gerek kalmadan dışarı içine koydu ki bekliyordum. Bunun yerine oluşturulan kod, gibi herhangi bir non-constexpr işlevi gibi sinüs yürütür. Bir constexpr fonksiyonu için

aşağıdaki geçerli olmalıdır derleme zamanında değerlendirilecek:

  • onun giriş argümanları hepsi sabit ifadeleri olması gerekir.
  • Bunun sonucu sabit bir ifadede kullanılmalıdır.

Döngü için test öğesinin ataması sabit bir ifade değildir. Sonuç olarak, sine derleme zamanında değerlendirilemez.

Gerçekten istediğiniz şey, bir dizinin öğelerini statik olarak sine() kullanarak başlatmaktır. aşağıda gösterildiği gibi bir std::array ve bazı yardımcı makine kullanma bunu yapmak mümkündür:

#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

, 'i M_PI/n 'sine'' etmek _argument_ * o sorun değil mi, değil Bir Constekspr? – Eric

+0

@Eric "Tüm giriş argümanları sabit ifadeler olmalıdır." yeterince açık değil mi? – 101010

+0

_ "Testin döngüdeki ataması sabit bir ifade değildir" _ ifadesini kullandım. Ödevin kendisi burada bir sorun mu var? – Eric

İlgili konular