23 double previous = 1.0;
25 for (
double j = 1; j < n; j++) {
27 ((2.0 * j + 1.0) * x * current - j * previous) / (j + 1.0);
37 return std::pow(-1, n - 1) * n * (n + 1) / 2.0;
39 return n * (n + 1) / 2.0;
63 static_cast<unsigned int>(std::floor(
static_cast<double>(n) / 2.0));
64 std::vector<double> computed_roots(n);
66 for (
auto i = 0; i < n_even; i++) {
68 computed_roots[i] = -computed_roots[n - 1 - i];
70 return computed_roots;
75 unsigned int safety = 10000;
76 for (
auto i = 0; i < safety; i++) {
79 double relative_error = std::abs((x_new - x_old) / std::max(1.0, x_new));
82 if (backward_error < 1e-8 && relative_error <
TOLERANCE)
return x_new;
85 throw std::runtime_error(
"LegendreRoot did not converge.");
89 if (k > n)
throw std::invalid_argument(
"k must be less than n.");
91 return std::cos((4.0 *
static_cast<double>(k) + 3.0) /
92 (4.0 *
static_cast<double>(n) + 2.0) * M_PI);
97 static_cast<unsigned int>(std::floor(
static_cast<double>(n - 1) / 2.0));
98 std::vector<double> computed_roots(n - 1);
100 for (
auto i = 0; i < n_even; i++) {
102 computed_roots[n - 2 - i] = -computed_roots[i];
104 return computed_roots;
109 unsigned int safety = 100;
111 double relative_error = std::numeric_limits<double>::infinity();
112 double backward_error = std::numeric_limits<double>::infinity();
113 for (
auto i = 0; i < safety; i++) {
116 relative_error = std::abs((x_new - x_old) / std::max(1.0, x_new));
119 if (backward_error < 1e-8 && relative_error <
TOLERANCE)
return x_new;
122 std::ostringstream error_message;
123 error_message << std::scientific << std::setprecision(6)
124 <<
"LegendrePrimeRoot did not converge. "
125 <<
"Backward Error: " << backward_error
126 <<
", Relative Error: " << relative_error;
128 throw std::runtime_error(error_message.str());
132 if (k >= n - 1)
throw std::invalid_argument(
"k must be less than n-1.");
std::vector< double > AllLegendrePrimeRoots(const int n)
Computes all roots of the polynomial. A total of n-1 roots will be computed and returned.
double LegendreRoot(const int n, const int k)
Computes the k-th root of the n-th order Legendre polynomial by first approximating the root with App...
double LegendrePolynomialPrime(const int n, const double x)
Computes the first derivative of the Legendre polynomial of degree n at a point x using the recurrenc...
double LegendrePrimeRoot(const int n, const int k)
Computes the k-th root of the n-th order first derivative of the Legendre polynomial by first approxi...
double LegendrePolynomialPrimePrime(const int n, const double x)
Computes the second derivative of the Legendre polynomial of degree n using Legendre's differential e...
bool DoubleEqual(const double first, const double second, const double tolerance=TOLERANCE)
Tests if two double-type numbers are equal using the TOLERANCE value. Taken from https://github....
double ApproximateLegendrePrimeRoot(const int n, const int k)
Approximates the k-th root of the first derivative of the n-th degree Legendre polynomial using the a...
double LegendrePolynomial(const int n, const double x)
Computes the Legendre polynomial of degree n at a point x using the formula:
std::vector< double > AllLegendreRoots(const int n)
Compute all roots of the Legendre polynomial of order n.
constexpr double TOLERANCE
General tolerance value for double comparisons.
double ApproximateLegendreRoot(const int n, const int k)
Approximates the k-th root of the n-th order Legendre polynomial with: