31 const int m = (n + 1) / 2;
32 const double pi = std::acos(-1.0);
33 const double tol = 64.0 * std::numeric_limits<double>::epsilon();
35 for (
int i = 0; i < m; ++i) {
36 double z = std::cos(pi * (
static_cast<double>(i) + 0.75) / (
static_cast<double>(n) + 0.5));
38 for (
int iter = 0; iter < 100; ++iter) {
40 const double delta = pn / dpn;
42 if (std::abs(delta) < tol) {
49 const double w = 2.0 / ((1.0 - z * z) * dpn * dpn);
54 weights(n - 1 - i) = w;
57 return {nodes, weights};
91 for (
int k = 1; k < n; ++k) {
93 ((2.0 *
static_cast<double>(k) + 1.0) * x * p_n -
static_cast<double>(k) * p_nm1) /
94 (
static_cast<double>(k) + 1.0);
99 const double nn =
static_cast<double>(n);
100 const double endpoint_tol = 64.0 * std::numeric_limits<double>::epsilon();
101 const double one_minus_abs_x = std::abs(1.0 - std::abs(x));
104 if (one_minus_abs_x < endpoint_tol) {
105 const double endpoint = 0.5 * nn * (nn + 1.0);
109 const double sign = ((n + 1) % 2 == 0) ? 1.0 : -1.0;
110 dp_n =
sign * endpoint;
113 dp_n = nn * (x * p_n - p_nm1) / (x * x - 1.0);
127 for (Eigen::Index i = 0; i < x.size(); ++i) {
151 const double pi = std::acos(-1.0);
152 const double tol = 32.0 * std::numeric_limits<double>::epsilon();
154 for (
int j = 1; j < N - 1; ++j) {
155 double x = -std::cos(pi *
static_cast<double>(j) /
static_cast<double>(N - 1));
157 for (
int iter = 0; iter < 100; ++iter) {
159 const double denom = 1.0 - x * x;
160 const double ddpn = (2.0 * x * dpn -
static_cast<double>(n) * (n + 1) * pn) / denom;
162 const double delta = dpn / ddpn;
165 if (std::abs(delta) < tol) {
187 const double pi = std::acos(-1.0);
188 for (
int j = 0; j < N; ++j) {
189 nodes(j) = -std::cos(pi *
static_cast<double>(j) /
static_cast<double>(N - 1));
204 if (nodes.size() != N) {
209 const double scale = 2.0 / (
static_cast<double>(N) *
static_cast<double>(N - 1));
211 for (
int i = 0; i < N; ++i) {
213 w(i) = scale / (pn * pn);
228 if (nodes.size() != N) {
240 const double pi = std::acos(-1.0);
242 for (
int j = 0; j < N; ++j) {
243 theta(j) = pi *
static_cast<double>(j) /
static_cast<double>(n);
250 const double w0 = 1.0 / (
static_cast<double>(n) *
static_cast<double>(n) - 1.0);
254 for (
int k = 1; k < n / 2; ++k) {
255 const double denom = 4.0 *
static_cast<double>(k) *
static_cast<double>(k) - 1.0;
256 for (
int j = 1; j < N - 1; ++j) {
257 v(j - 1) -= 2.0 * std::cos(2.0 *
static_cast<double>(k) * theta(j)) / denom;
261 const double denom =
static_cast<double>(n) *
static_cast<double>(n) - 1.0;
262 for (
int j = 1; j < N - 1; ++j) {
263 v(j - 1) -= std::cos(
static_cast<double>(n) * theta(j)) / denom;
266 const double w0 = 1.0 / (
static_cast<double>(n) *
static_cast<double>(n));
270 for (
int k = 1; k <= (n - 1) / 2; ++k) {
271 const double denom = 4.0 *
static_cast<double>(k) *
static_cast<double>(k) - 1.0;
272 for (
int j = 1; j < N - 1; ++j) {
273 v(j - 1) -= 2.0 * std::cos(2.0 *
static_cast<double>(k) * theta(j)) / denom;
278 for (
int j = 1; j < N - 1; ++j) {
279 w(j) = 2.0 * v(j - 1) /
static_cast<double>(n);
291 const int N =
static_cast<int>(nodes.size());
297 for (
int j = 0; j < N; ++j) {
299 for (
int k = 0; k < N; ++k) {
303 prod *= (nodes(j) - nodes(k));
305 lambda(j) = 1.0 / prod;
320 const int N =
static_cast<int>(nodes.size());
322 throw InvalidArgument(
"barycentric_basis_eval: need at least 2 nodes");
324 if (bary_w.size() != N) {
325 throw InvalidArgument(
"barycentric_basis_eval: barycentric weight size mismatch");
327 if (j < 0 || j >= N) {
328 throw InvalidArgument(
"barycentric_basis_eval: basis index out of range");
331 const double tol = 128.0 * std::numeric_limits<double>::epsilon() * (1.0 + std::abs(s));
332 for (
int k = 0; k < N; ++k) {
333 if (std::abs(s - nodes(k)) <= tol) {
334 return (k == j) ? 1.0 : 0.0;
339 for (
int k = 0; k < N; ++k) {
340 denom += bary_w(k) / (s - nodes(k));
342 return (bary_w(j) / (s - nodes(j))) / denom;
355 const int N =
static_cast<int>(nodes.size());
357 throw InvalidArgument(
"birkhoff_integration_matrix: need at least 2 nodes");
361 const int n_quad = std::max(8, (N + 1) / 2 + 2);
365 const double a = nodes(0);
367 for (
int i = 0; i < N; ++i) {
368 const double b = nodes(i);
369 const double half = 0.5 * (b - a);
370 const double mid = 0.5 * (b + a);
375 for (
int q = 0; q < n_quad; ++q) {
376 const double s = mid + half * quad_x(q);
377 const double wq = half * quad_w(q);
380 const double tol = 128.0 * std::numeric_limits<double>::epsilon() * (1.0 + std::abs(s));
381 for (
int k = 0; k < N; ++k) {
382 if (std::abs(s - nodes(k)) <= tol) {
388 if (node_match >= 0) {
389 B(i, node_match) += wq;
394 for (
int k = 0; k < N; ++k) {
395 denom += bary_w(k) / (s - nodes(k));
397 for (
int j = 0; j < N; ++j) {
398 const double ell_j = (bary_w(j) / (s - nodes(j))) / denom;
399 B(i, j) += wq * ell_j;
413 const int N =
static_cast<int>(nodes.size());
421 for (
int i = 0; i < N; ++i) {
422 for (
int j = 0; j < N; ++j) {
426 D(i, j) = (lambda(j) / lambda(i)) / (nodes(i) - nodes(j));
430 for (
int i = 0; i < N; ++i) {
431 D(i, i) = -D.row(i).sum();
Custom exception hierarchy for Janus framework.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
Smooth approximation of ReLU function: softplus(x) = (1/beta) * log(1 + exp(beta * x)).
Definition Diagnostics.hpp:131
std::pair< NumericVector, NumericVector > gauss_legendre_rule(int n)
Definition OrthogonalPolynomials.hpp:23
constexpr double polynomial_root_tolerance
Tolerance for zero-length integration intervals in Birkhoff matrix.
Definition OrthogonalPolynomials.hpp:21
Definition Diagnostics.hpp:19
NumericMatrix birkhoff_integration_matrix(const NumericVector &nodes)
Compute Birkhoff integration matrix B^a for the node set.
Definition OrthogonalPolynomials.hpp:354
NumericVector legendre_poly_vec(int n, const NumericVector &x)
Evaluate P_n(x) at each x in vector.
Definition OrthogonalPolynomials.hpp:125
NumericVector cgl_weights(int N, const NumericVector &nodes)
CGL (Clenshaw-Curtis) quadrature weights on [-1, 1].
Definition OrthogonalPolynomials.hpp:224
JanusMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition JanusTypes.hpp:66
NumericVector lgl_weights(int N, const NumericVector &nodes)
LGL quadrature weights.
Definition OrthogonalPolynomials.hpp:200
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
std::pair< NumericVector, NumericVector > gauss_legendre_rule(int n)
Gauss-Legendre nodes and weights on [-1, 1].
Definition OrthogonalPolynomials.hpp:67
T sign(const T &x)
Computes sign of x.
Definition Arithmetic.hpp:326
double barycentric_basis_eval(const NumericVector &nodes, const NumericVector &bary_w, int j, double s)
Evaluate the j-th Lagrange basis polynomial at s using barycentric form.
Definition OrthogonalPolynomials.hpp:318
NumericMatrix spectral_diff_matrix(const NumericVector &nodes)
Spectral differentiation matrix using barycentric weights.
Definition OrthogonalPolynomials.hpp:412
NumericVector barycentric_weights(const NumericVector &nodes)
Compute barycentric interpolation weights for the given nodes.
Definition OrthogonalPolynomials.hpp:290
NumericVector lgl_nodes(int N)
Compute Legendre-Gauss-Lobatto nodes on [-1, 1].
Definition OrthogonalPolynomials.hpp:138
NumericVector cgl_nodes(int N)
Compute Chebyshev-Gauss-Lobatto nodes on [-1, 1].
Definition OrthogonalPolynomials.hpp:181
std::pair< double, double > legendre_poly(int n, double x)
Evaluate Legendre polynomial P_n(x) and derivative P'_n(x).
Definition OrthogonalPolynomials.hpp:77