numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
legendre_roots.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <cmath>
23#include <limits>
24#include <tuple>
25
26#include <Eigen/Core>
27
32#include "num_collect/constants/pi.h" // IWYU pragma: keep
33#include "num_collect/constants/zero.h" // IWYU pragma: keep
38
39namespace num_collect::functions {
40
41namespace impl {
42
49template <base::concepts::real_scalar T>
51public:
53 using variable_type = T;
54
56 using jacobian_type = T;
57
63 explicit legendre_for_newton(index_type degree) : degree_(degree) {
65 degree >= 1, "Degree of Legendre function must be at least one.");
66 }
67
73 void evaluate_on(const variable_type& variable) {
74 std::tie(value_, jacobian_) = legendre_with_diff(variable, degree_);
75 }
76
82 [[nodiscard]] auto value() const noexcept -> const variable_type& {
83 return value_;
84 }
85
91 [[nodiscard]] auto jacobian() const noexcept -> const jacobian_type& {
92 return jacobian_;
93 }
94
95private:
98
101
104};
105
106} // namespace impl
107
113template <base::concepts::real_scalar T>
115public:
117 using variable_type = T;
118
125 if (degree == 0) {
126 roots_.resize(0);
127 return;
128 }
130 }
131
139 degree >= 1, "Degree of Legendre function must be at least one.");
140 degree_ = degree;
141
142 roots_.resize(degree_);
143 const index_type roots_to_solve = degree_ / 2;
144
145 using function_type = impl::legendre_for_newton<variable_type>;
146 using solver_type = roots::newton_raphson<function_type>;
147 auto solver = solver_type(function_type(degree_));
148 constexpr auto tol_last_change =
149 std::numeric_limits<variable_type>::epsilon() *
150 static_cast<variable_type>(1e+2);
151 constexpr auto tol_value_norm =
152 std::numeric_limits<variable_type>::epsilon() *
153 static_cast<variable_type>(1e+2);
154 solver.tol_last_change(tol_last_change);
155 solver.tol_value_norm(tol_value_norm);
156
157 for (index_type i = 0; i < roots_to_solve; ++i) {
158 using std::cos;
159 constexpr auto offset_in_num = static_cast<variable_type>(0.75);
160 constexpr auto offset_in_den = static_cast<variable_type>(0.5);
161 const variable_type init_var = cos(constants::pi<variable_type> *
162 (static_cast<variable_type>(i) + offset_in_num) /
163 (static_cast<variable_type>(degree_) + offset_in_den));
164
165 solver.init(init_var);
166 solver.solve();
167 roots_[i] = solver.variable();
168 }
169 const index_type center = (degree_ - 1) / 2;
170 if (degree_ % 2 == 1) {
172 }
173 for (index_type i = center + 1; i < degree_; ++i) {
174 roots_[i] = -roots_[degree_ - 1 - i];
175 }
176 }
177
183 [[nodiscard]] auto degree() const noexcept -> index_type { return degree_; }
184
190 [[nodiscard]] auto size() const noexcept -> index_type {
191 return roots_.size();
192 }
193
200 [[nodiscard]] auto root(index_type i) const -> variable_type {
203 return roots_[i];
204 }
205
212 [[nodiscard]] auto operator[](index_type i) const -> variable_type {
213 return root(i);
214 }
215
216private:
219
221 Eigen::Matrix<variable_type, Eigen::Dynamic, 1> roots_{};
222};
223
224} // namespace num_collect::functions
Definition of assertion macros.
#define NUM_COLLECT_DEBUG_ASSERT(CONDITION)
Macro to check whether a condition is satisfied in debug build only.
Definition assert.h:75
Class of Legendre function to use with num_collect::roots::newton_raphson class.
index_type degree_
Degree of Legendre function.
legendre_for_newton(index_type degree)
Constructor.
auto jacobian() const noexcept -> const jacobian_type &
Get Jacobian.
auto value() const noexcept -> const variable_type &
Get function value.
void evaluate_on(const variable_type &variable)
Evaluate on a variable.
Class of roots of Legendre function.
auto size() const noexcept -> index_type
Get the number of roots.
Eigen::Matrix< variable_type, Eigen::Dynamic, 1 > roots_
List of roots.
void compute(index_type degree)
Compute roots of Legendre function.
index_type degree_
Degree of Legendre function.
auto degree() const noexcept -> index_type
Get the degree of Legendre function.
auto operator[](index_type i) const -> variable_type
Get the i-th root.
auto root(index_type i) const -> variable_type
Get the i-th root.
legendre_roots(index_type degree=0)
Constructor.
Class of Newton-Raphson method.
Definition of exceptions.
Definition of index_type type.
Definition of legendre function.
Definition of macros for logging.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
constexpr T pi
Value of pi, .
Definition pi.h:40
constexpr T zero
Value 0.
Definition zero.h:30
Namespace of special functions.
Definition gamma.h:27
constexpr auto legendre_with_diff(F x, I n) -> std::pair< F, F >
Calculate Legendre function and its differential coefficient.
Definition legendre.h:80
Definition of newton_raphson class.
Definition of pi.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of real_scalar concept.
Definition of zero.