26template<std::
size_t K,
typename Scalar>
31 if (p > K) {
return ret; }
33 for (
auto i = 0u; i < p; ++i) { ret[0][i] =
Scalar(0); }
36 for (
auto j = 2u; j <= p; ++j) { P2 *= j; }
37 ret[0][p] = P1 *
static_cast<Scalar>(P2);
38 for (
auto i = p + 1; i <= K; ++i) {
42 ret[0][i] = P1 *
static_cast<Scalar>(P2);
60template<std::
size_t K, std::
size_t P,
typename Scalar>
64 for (
auto p = 0u; p <= P; ++p) { ret[p] = monomial_derivative<K, Scalar>(u, p)[0]; }
74template<std::
size_t K,
typename Scalar =
double>
78 if constexpr (K == 0) {
86 for (
auto i = 0u; i != K; ++i) {
87 for (
auto j = 0u; j != K; ++j) {
88 low[i][j] = coeff_mat_km1[i][j];
89 high[i + 1][j] = coeff_mat_km1[i][j];
93 for (
auto k = 0u; k != K; ++k) {
94 left[k][k + 1] =
static_cast<Scalar>(K - (k + 1)) /
static_cast<Scalar>(K);
95 left[k][k] =
Scalar(1) - left[k][k + 1];
98 right[k][k] = -right[k][k + 1];
101 return low * left + high * right;
109template<std::
size_t K,
typename Scalar =
double>
113 if constexpr (K == 0) {
121 for (
auto i = 0u; i != K; ++i) {
122 for (
auto j = 0u; j != K; ++j) {
123 low[i][j] = coeff_mat_km1[i][j];
124 high[i + 1][j] = coeff_mat_km1[i][j];
128 for (
auto k = 0u; k != K; ++k) {
132 right[k][k + 1] =
Scalar(1);
135 return low * left + high * right;
143template<std::
size_t K,
typename Scalar =
double>
149 if constexpr (K > 0) { ret[1][1] = 2; }
151 if constexpr (K > 1) {
152 for (
auto k = 2u; k < K + 1; ++k) {
153 for (
auto i = 0u; i < k; ++i) { ret[i + 1][k] += 2 * ret[i][k - 1]; }
154 for (
auto i = 0u; i + 1 < k; ++i) { ret[i][k] -= 2 * (k - 1) * ret[i][k - 2]; }
164template<std::
size_t K,
typename Scalar =
double>
170 if constexpr (K > 0) {
175 if constexpr (K > 1) {
176 for (
auto k = 2u; k < K + 1; ++k) {
177 for (
auto i = 0u; i < k; ++i) {
178 ret[i][k] += (2 * k - 1) * ret[i][k - 1] / k;
179 ret[i + 1][k] -= ret[i][k - 1] / k;
181 for (
auto i = 0u; i + 1 < k; ++i) { ret[i][k] -=
static_cast<double>(k - 1) * ret[i][k - 2] / k; }
198template<std::
size_t K,
typename Scalar =
double>
204 if constexpr (K > 0) {
205 ret[0][1] = alpha + 1. - (alpha + beta + 2) / 2;
206 ret[1][1] = (alpha + beta + 2.) / 2;
209 if constexpr (K > 1) {
210 for (
auto k = 2u; k < K + 1; ++k) {
211 const auto frac = 1. / ((2 * k) * (k + alpha + beta) * (2 * k + alpha + beta - 2));
212 const auto c1 = (2 * k + alpha + beta - 1) * (alpha * alpha - beta * beta);
213 const auto c2 = (2 * k + alpha + beta - 1) * (2 * k + alpha + beta) * (2 * k + alpha + beta - 2);
214 const auto c3 = 2 * (k + alpha - 1) * (k + beta - 1) * (2 * k + alpha + beta);
215 for (
auto i = 0u; i < k; ++i) {
216 ret[i][k] += c1 * ret[i][k - 1] * frac;
217 ret[i + 1][k] += c2 * ret[i][k - 1] * frac;
219 for (
auto i = 0u; i + 1 < k; ++i) { ret[i][k] -= c3 * ret[i][k - 2] * frac; }
263template<PolynomialBasis Basis, std::
size_t K,
typename Scalar =
double>
268 for (
auto k = 0u; k <= K; ++k) { ret[k][k] =
Scalar(1); }
276 auto ret = detail::jacobi_basis<K, Scalar>(-0.5, -0.5);
277 const auto fac = monomial_derivative<K>(1.) * ret;
278 for (
auto k = 0u; k < K + 1; ++k) {
279 for (
auto r = 0u; r < K + 1; ++r) { ret[r][k] /= fac[0][k]; }
284 auto ret = detail::jacobi_basis<K, Scalar>(0.5, 0.5);
285 const auto fac = monomial_derivative<K>(1.) * ret;
286 for (
auto k = 0u; k < K + 1; ++k) {
287 for (
auto r = 0u; r < K + 1; ++r) { ret[r][k] *=
static_cast<Scalar>(k + 1) / fac[0][k]; }
312template<std::
size_t K, std::ranges::random_access_range R,
typename Scalar = std::ranges::range_value_t<R>>
317 for (
auto row = 0u; row < K + 1; ++row) {
319 for (
auto col = 0u; col < K + 1; ++col) {
321 const auto row_copy = ret[row];
323 for (
auto i = 0u; i <= col - (col > row ? 1 : 0); ++i) {
324 ret[row][i + 1] += row_copy[i] / (*(ts.begin() + row) - *(ts.begin() + col));
325 ret[row][i] -= *(ts.begin() + col) * row_copy[i] / (*(ts.begin() + row) - *(ts.begin() + col));
345template<std::
size_t K, std::
size_t N,
typename Scalar, std::ranges::sized_range R>
349 assert(std::ranges::size(ts) == N);
353 for (
auto j = 0u;
const auto t : ts) {
354 const auto U = monomial_derivative<K>(t, 1);
355 const auto U_B = U * B;
356 for (
auto i = 0u; i < K + 1; ++i) { ret[i][j] = U_B[0][i]; }
381template<PolynomialBasis Basis, std::
size_t K,
typename Scalar =
double>
384 auto M = polynomial_basis<Basis, K, Scalar>();
385 for (
auto i = 0u; i != K + 1; ++i) {
386 for (
auto j = 0u; j != K; ++j) { M[i][K - 1 - j] += M[i][K - j]; }
399template<std::
size_t K, std::
size_t P,
typename Scalar =
double>
403 for (
auto i = 0u; i <= K; ++i) {
404 for (
auto j = i; j <= K; ++j) {
405 if (i >= P && j >= P) {
407 for (
auto _i = i - P + 1; _i <= i; ++_i) { c *= _i; }
408 for (
auto _j = j - P + 1; _j <= j; ++_j) { c *= _j; }
409 ret[i][j] =
static_cast<Scalar>(c) /
static_cast<Scalar>(i + j - 2 * P + 1);
413 ret[j][i] = ret[i][j];
430 double mid1 = std::numeric_limits<double>::infinity();
432 double mid2 = std::numeric_limits<double>::infinity();
434 if (std::abs(A) < 1e-9 && std::abs(B) > 1e-9) {
436 mid1 = std::clamp(-C / B, t0, t1);
437 }
else if (std::abs(A) > 1e-9) {
439 const double res = B * B / (4 * A * A) - C / A;
442 mid1 = -B / (2 * A) - std::sqrt(res);
443 mid2 = -B / (2 * A) + std::sqrt(res);
447 const auto integ = [&](
double u) {
return A * u * u * u / 3 + B * u * u / 2 + C * u; };
449 const double mid1cl = std::clamp(mid1, t0, t1);
450 const double mid2cl = std::clamp(mid2, t0, t1);
452 return std::abs(integ(t1) - integ(t0) + 2 * integ(mid1cl) - 2 * integ(mid2cl));
constexpr StaticMatrix< Scalar, K+1, K+1 > jacobi_basis(double alpha, double beta)
Jacobi basis coefficient matrix.
constexpr StaticMatrix< Scalar, K+1, K+1 > monomial_integral()
Calculate integral over matrix of squared monomial P-derivatives.
SMOOTH_BEGIN_NAMESPACE constexpr StaticMatrix< Scalar, 1, K+1 > monomial_derivative(Scalar u, std::size_t p=0)
Monomial derivative (compile-time version).
constexpr StaticMatrix< Scalar, P+1, K+1 > monomial_derivatives(Scalar u)
Monomial derivatives up to order.
constexpr StaticMatrix< Scalar, K+1, K+1 > lagrange_basis(const R &ts)
Lagrange polynomial basis coefficients.
constexpr double integrate_absolute_polynomial(double t0, double t1, double A, double B, double C)
Integrate the absolute value of a quadratic 1D polynomial.
constexpr StaticMatrix< Scalar, K+1, K+1 > bernstein_basis()
Bernstein basis coefficient matrix.
constexpr StaticMatrix< Scalar, K+1, N > polynomial_basis_derivatives(const StaticMatrix< Scalar, K+1, K+1 > &B, const R &ts)
Polynomial basis derivative coefficients.
constexpr StaticMatrix< Scalar, K+1, K+1 > bspline_basis()
Bspline basis coefficient matrix.
constexpr StaticMatrix< Scalar, K+1, K+1 > hermite_basis()
Hermite basis coefficient matrix.
constexpr StaticMatrix< Scalar, K+1, K+1 > polynomial_basis()
Compile-time coefficient matrix for given basis.
constexpr StaticMatrix< Scalar, K+1, K+1 > polynomial_cumulative_basis()
Cumulative coefficient matrix for given basis.
PolynomialBasis
Polynomial basis types.
@ Bspline
Basis on [0, 1] with left to right ordering.
@ Bernstein
Basis on [0, 1] with left to right ordering.
@ Hermite
Orthogonal basis on [-inf, inf] w.r.t the weight exp(-x^2)
@ Laguerre
Orthogonal basis on [0, inf] w.r.t the weight exp(-x)
@ Monomial
The standard monomial basis (1, x, x^2, ...)
@ Chebyshev2nd
Orthogonal basis on [-1, 1] w.r.t the weight sqrt(1-x^2)
@ Chebyshev1st
Orthogonal basis on [-1, 1] w.r.t the weight 1 / sqrt(1-x^2)
@ Legendre
Orthogonal basis on [-1, 1].
constexpr StaticMatrix< Scalar, K+1, K+1 > laguerre_basis()
Laguerre basis coefficient matrix.
typename traits::man< M >::Scalar Scalar
Manifold scalar type.
Utilities for compile-time matrix algebra.
Elementary structure for compile-time matrix algebra.
constexpr StaticMatrix< _Scalar, _Rows, _Cols > transpose() const
Matrix transpose.