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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! Math abstraction the solvers depend on.
//!
//! Two tiers per `AGENTS.md` tenet 5:
//!
//! - **Vector tier** (this module): small ops every backend can implement
//! well — [`ScaledAdd`], [`NormSquared`], [`NormInfinity`], [`Dot`],
//! [`NegInPlace`]. Backend-generic solvers (gradient descent,
//! Nelder-Mead) bound on these.
//! - **`linalg` tier** ([`linalg`]): LA-heavy ops — [`MatVec`],
//! [`MatTransposeVec`], [`GramMatrix`], [`LinearSolveSpd`],
//! [`LinearSolveLstsq`] — that only the matrix-capable backends
//! (nalgebra, faer; sparse counterparts in S2b) implement. LA-heavy
//! solvers (Gauss-Newton, LM) bound on these so other backends
//! produce compile-time errors instead of runtime surprises.
/// In-place `self ← self + scalar · other`. Backend-generic vector update.
/// `‖x‖₂² = Σ xᵢ²`. Avoids the `sqrt` cost when the squared form is
/// what's actually needed (most quadratic-cost convergence checks).
/// `‖x‖_∞ = maxᵢ |xᵢ|`. Used by first-order optimality stopping rules
/// (e.g. `‖∇f‖_∞ ≤ tol`).
/// Inner product of two same-shaped values. Used by line searches that take
/// an explicit search direction (Armijo and curvature checks both need
/// `gᵀd`). Generalizes `NormSquared`: `x.norm_squared() == x.dot(x)`.
/// In-place negation. Lets solvers compute `direction = -gradient` in a
/// backend-generic way without allocating per-iteration scratch types.
/// In-place scalar multiplication `self ← scalar · self`. Used by
/// CMA-ES to update the cumulation paths (`p_σ ← (1−c_σ) p_σ + …`,
/// Hansen 2016 eq. 31) and the covariance matrix
/// (`C ← (1 + c_1 δ_h − c_1 − c_µ Σ w_j) C + …`, eq. 47) without
/// allocating a clone per iteration.
///
/// `ScaledAdd<f64>` already covers `self ← self + s · other`; the
/// borrow checker forbids `self.scaled_add(s, &self)`, so an honest
/// in-place scale needs its own trait.
/// Number of components in a 1-D vector. Used by CMA-ES to derive the
/// search-space dimension `n` from a template vector at solver
/// construction time, so callers don't have to thread `n` separately
/// from the initial mean. Method named `vec_len` to avoid colliding
/// with the inherent `len()` methods on `Vec`, `DVector`, `Array1`,
/// `Col`.
/// In-place componentwise multiplication `self[i] ← self[i] · other[i]`.
/// CMA-ES uses this to apply the diagonal `D` (sqrt-eigenvalue) factor:
/// the sampling step `y_k = B D z_k` is `z.component_mul_assign(&d);
/// y = B.matvec(&z)`, and the conjugate-path step `C^{−1/2} v =
/// B (1/d ⊙ Bᵀv)` is the same pattern with `1/d`.
/// In-place componentwise maximum `self[i] ← max(self[i], other[i])`.
/// Levenberg-Marquardt uses this to maintain the monotone running-max
/// scaling diagonal `D_k = max(D_{k−1}, diag(JᵀJ))` of MINPACK-style
/// Marquardt damping (Moré 1978): a parameter whose column curvature
/// momentarily drops doesn't lose the damping floor accumulated from
/// earlier iterations.
/// In-place componentwise division `self[i] ← self[i] / other[i]`. The
/// counterpart of [`ComponentMulAssign`]. Levenberg-Marquardt forms the
/// MINPACK `gtol` measure — the per-column cosine `g_j² / (JᵀJ)ⱼⱼ` —
/// with this.
///
/// # Contract
///
/// - **Caller must:** ensure `other[i] ≠ 0` for every `i`; division by a
/// zero divisor yields a non-finite value that propagates. (LM floors
/// the divisor away from zero with [`FloorZerosInPlace`] first.)
/// In-place floor of non-positive entries to a positive `value`,
/// leaving strictly-positive entries untouched
/// (`self[i] ← value` where `self[i] ≤ 0`, else unchanged).
///
/// This is *not* a blanket lower-clamp: a legitimately small positive
/// entry keeps its value. It exists for MINPACK's zero-column guard in
/// Marquardt-scaled Levenberg-Marquardt — a Jacobian column that is
/// entirely zero gives `diag(JᵀJ)ⱼ = 0`, which would make the damping
/// `μ·D` vanish on that coordinate and leave the normal-equations
/// matrix singular there. MINPACK sets such a column's scale to `1`
/// (lmder, `mode = 1`); flooring zeros to `1` reproduces that, so a
/// fully-insensitive parameter simply stays put instead of failing the
/// Cholesky.
/// Per-component scalar read/write on a 1-D vector backend. The minimal
/// access finite-difference differentiation needs: perturb one coordinate
/// of a parameter vector and read derivative values back out
/// ([`crate::core::numdiff`]).
///
/// Methods are named `get_scalar` / `set_scalar` rather than `get` / `set`
/// to dodge the inherent `slice::get -> Option<&T>` (which would shadow a
/// trait `get` at call sites on a concrete `Vec`) and the `Index` /
/// `IndexMut` traits — the same defensive convention as
/// [`VectorLen::vec_len`].
///
/// # Contract
///
/// - **Caller must:** pass `i < self.vec_len()`. Backends index directly and
/// panic on out-of-bounds, matching the underlying `Index` impls.
pub use BoxAffineScaling;
pub use ClampInPlace;
pub use ;
pub use ;