Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cmath> 7 : #include <numeric> 8 : #include <utility> 9 : #include <vector> 10 : 11 : #include "DataStructures/DataVector.hpp" 12 : #include "Utilities/ErrorHandling/Error.hpp" 13 : #include "Utilities/MakeWithValue.hpp" 14 : 15 : namespace Spectral { 16 : /// Clenshaw's algorithm for evaluating linear combinations of 17 : /// basis functions obeying a given three term recurrence relation. 18 : /// See numerical recipes 3rd edition 5.4.2 for details. 19 : /// `alpha` and `beta` define the recursion 20 : /// \f$ f_n(x) = \alpha f_{n-1}(x) + \beta f_{n-2}(x) \f$ 21 : /// `f0_of_x` and `f1_of_x` are \f$ f_0(x)\f$ and \f$f_1(x)\f$ respectively 22 : template <typename CoefficientDataType, typename DataType> 23 1 : DataType evaluate_clenshaw(const std::vector<CoefficientDataType>& coefficients, 24 : const DataType& alpha, const DataType& beta, 25 : const DataType& f0_of_x, const DataType& f1_of_x) { 26 : if (coefficients.empty()) { 27 : return make_with_value<DataType>(f0_of_x, 0.0); 28 : } 29 : 30 : DataType y_upper{make_with_value<DataType>(f0_of_x, 0.0)}; // y_{N+2} = 0 31 : DataType new_y_lower; 32 : // Do the loop to calculate y_1 and y_2 (the accumulate function leaves 33 : // y_lower_final = y_1, and y_upper = y_2) 34 : const DataType y_lower_final = 35 : std::accumulate(coefficients.rbegin(), coefficients.rend() - 1, 36 : make_with_value<DataType>(f0_of_x, 0.0), 37 : [&y_upper, &alpha, &beta, &new_y_lower]( 38 : const auto& y_lower, const auto& c_k) { 39 : new_y_lower = c_k + alpha * y_lower + beta * y_upper; 40 : y_upper = y_lower; 41 : return new_y_lower; 42 : }); 43 : return f0_of_x * coefficients[0] + f1_of_x * y_lower_final + 44 : beta * f0_of_x * y_upper; 45 : } 46 : 47 : } // namespace Spectral