14#include <xtensor/containers/xarray.hpp>
16namespace oiseau::utils {
19template <
class Container>
21 std::is_floating_point_v<std::ranges::range_value_t<Container>>;
24template <std::
floating_po
int Real>
25Real jacobi(
unsigned n, Real alpha, Real beta, Real x) {
31 Real y1 = (alpha + 1) + (alpha + beta + 2) * (x - 1) / Real(2);
35 Real k_max = n * (1 + std::numeric_limits<Real>::epsilon());
38 Real denom = 2 * k * (k + alpha + beta) * (2 * k + alpha + beta - 2);
40 (2 * k + alpha + beta - 1) *
41 ((2 * k + alpha + beta) * (2 * k + alpha + beta - 2) * x + alpha * alpha - beta * beta);
42 Real gamma0 = -2 * (k + alpha - 1) * (k + beta - 1) * (2 * k + alpha + beta);
43 yk = (gamma1 * y1 + gamma0 * y0) / denom;
52template <std::
floating_po
int Real, FloatingArrayLike Container>
53Container jacobi_p(
unsigned n, Real alpha, Real beta,
const Container& input) {
55 Real norm = std::pow(2, alpha + beta + 1) / (2 * n + alpha + beta + 1);
56 norm *= std::tgamma(n + alpha + 1) * std::tgamma(n + beta + 1);
57 norm /= (std::tgamma(n + 1) * std::tgamma(n + alpha + beta + 1));
58 auto partial = [n, alpha, beta, norm](
auto& k) {
59 k = jacobi(n, alpha, beta, k) / std::sqrt(norm);
61 std::for_each(v.begin(), v.end(), partial);
66template <std::
floating_po
int Real, FloatingArrayLike Container>
67Container grad_jacobi_p(
int n, Real alpha, Real beta,
const Container& input) {
70 std::fill(v.begin(), v.end(), Real(0));
73 Real norm = std::sqrt(n * (n + alpha + beta + 1));
74 Container output = jacobi_p(n - 1, alpha + 1, beta + 1, v);
75 std::for_each(output.begin(), output.end(), [norm](
auto& k) { k *= norm; });
Concept that checks for contiguous floating-point containers.
Definition math.hpp:20