簡體   English   中英

使用Horner方法進行多項式求值的C ++ constexpr

[英]C++ constexpr for polynomial evaluation with Horner's method

我希望能夠使用Horner方法評估多項式的​​導數,並將結果用作constexpr 這似乎非常平凡,但我遺漏了一些明顯的東西,因為編譯器說我超過了最大遞歸深度。 核心遞歸發生在這里:

template<size_t d, size_t i, typename C, typename X>
constexpr X evalImpl(const C &c, const X &x) {
    return i >= (C::SizeAtCompileTime - 1 - d) ? 1 : evalImpl<d, i + 1, C, X>(c, x);
}

您甚至不需要知道Horner的方法就知道它在這里發生了什么,所以我盡可能地刪除了代碼,甚至刪除了x的使用方式,因為它似乎與我遇到的問題無關。

這個想法是當索引i等於多項式Degree<C>::value減去導數d的階數時,則遞歸應該停止。 否則,它應該增加索引i並再次嘗試。

我通過調用表單來調用上面的遞歸

 eval<derivative, 0>(c, x)

其中cEigen::Matrix<double,1,7>類型的Eigen::Matrix<double,1,7>x是雙Eigen::Matrix<double,1,7> 想法是從0開始並基本上計算多項式的次數。

編譯器錯誤消息的形式

In file included from /mnt/c/proj/src/main.cpp:11:0:
/mnt/c/proj/src/polynomial.h: In instantiation of 'constexpr X {anonymous}::evalImpl(const C&, const X&) [with long unsigned int d = 1ul; long unsigned int i = 898ul; C = Eigen::Matrix<double, 1, 7>; X = double]':
/mnt/c/proj/src/polynomial.h:74:108:   recursively required from 'constexpr X {anonymous}::evalImpl(const C&, const X&) [with long unsigned int d = 1ul; long unsigned int i = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double]'
/mnt/c/proj/src/polynomial.h:74:108:   required from 'constexpr X {anonymous}::evalImpl(const C&, const X&) [with long unsigned int d = 1ul; long unsigned int i = 0ul; C = Eigen::Matrix<double, 1, 7>; X = double]'
/mnt/c/proj/src/polynomial.h:109:39:   required from 'constexpr X Polynomial::eval(const C&, const X&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double]'
/mnt/c/proj/src/main.cpp:306:66:   required from here
/mnt/c/proj/src/polynomial.h:74:108: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
         return i >= (C::SizeAtCompileTime - 1 - d) ? 1 : evalImpl<d, i + 1, C, X>(c, x);

這里的條件:

return i >= (C::SizeAtCompileTime - 1 - d) ? 1 : evalImpl<d, i + 1, C, X>(c, x);

不是if constexpr 因此,無論i >= (C::SizeAtCompileTime - 1 - d)true還是false ,其余的都將被實例化。 因此,遞歸不會像你想要的那樣停止。

改為:

if constexpr (i >= (C::SizeAtCompileTime - 1 - d)) {
    return 1;
} else { 
    return evalImpl<d, i + 1, C, X>(c, x);  
}

編輯:

如果您無權訪問C ++ 17,請使用標記調度:

template<size_t d, size_t i, typename C, typename X>
constexpr X evalImpl_impl(const C &c, const X &x, std::true_type) {
    return 1;
}

template<size_t d, size_t i, typename C, typename X>
constexpr X evalImpl_impl(const C &c, const X &x, std::false_type) {
    return evalImpl_impl<d, i + 1, C, X>(c, x, std::integral_constant<bool, C::SizeAtCompileTime-1-d <= i+1>{});
}

template<size_t d, size_t i, typename C, typename X>
constexpr X evalImpl(const C &c, const X &x) {
    return evalImpl_impl(c, x, std::integral_constant<bool, C::SizeAtCompileTime-1-d <= i>{});
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM