1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! `BasisSystem` — a basis evaluation matrix bundled with its roughness penalty.
//!
//! This struct is the return type for the new basis factories introduced in Phase 35
//! (`monomial_basis`, `exponential_basis`, `power_basis`, `polygonal_basis`). It bundles:
//!
//! - a column-major evaluation matrix over a supplied set of evaluation points, and
//! - the corresponding roughness-penalty (Gram) matrix for the chosen derivative order.
//!
//! ## Column-major layout
//!
//! `eval_matrix` is stored in **column-major order**: element (t_i, j) — the value of the
//! j-th basis function at the i-th evaluation point — is at index `i + j * n_eval`.
//!
//! This matches the `bspline_basis` / `fourier_basis` convention used throughout
//! `fdars-core`.
//!
//! ## Penalty matrix
//!
//! `penalty_matrix` is the `nbasis × nbasis` Gram matrix of the `lfd_order`-th derivatives
//! of the basis functions:
//!
//! ```text
//! R[j, k] = ∫ D^lfd_order B_j(t) · D^lfd_order B_k(t) dt
//! ```
//!
//! It is stored column-major: element (j, k) is at index `j + k * nbasis`.
//! The matrix is symmetric and positive-semi-definite.
/// A basis evaluation matrix bundled with its roughness-penalty (Gram) matrix.
///
/// Created by the basis factories (`monomial_basis`, etc.) — never constructed directly
/// by callers. The `#[non_exhaustive]` attribute allows adding new fields (e.g., `domain`,
/// `basis_type`) in future versions without breaking existing code.
///
/// ## Field layout
///
/// - `eval_matrix`: column-major, shape `(n_eval × nbasis)`.
/// Element (t_i, j) is at index `i + j * n_eval`.
/// - `penalty_matrix`: column-major, shape `(nbasis × nbasis)`.
/// Element (j, k) is at index `j + k * nbasis`.
///
/// ## Example
///
/// ```
/// use fdars_core::monomial_basis;
///
/// let t = vec![0.0, 0.5, 1.0];
/// let bs = monomial_basis(&t, 3).unwrap();
/// assert_eq!(bs.nbasis, 3);
/// assert_eq!(bs.n_eval, 3);
/// assert_eq!(bs.eval_matrix.len(), 9);
/// assert_eq!(bs.penalty_matrix.len(), 9);
/// ```