| 296 | // that showed up in traces against libLBFGS and L-BFGS-B Fortran 3.0. |
| 297 | template <typename TScalar, int TDimension = Eigen::Dynamic> |
| 298 | struct FunctionState { |
| 299 | // Plain unconstrained state; `Progress::Update` uses this to pick the |
| 300 | // gradient/f-delta convergence branch rather than the feasibility |
| 301 | // branch that `AugmentedLagrangeState` takes. |
| 302 | static constexpr bool IsConstrained = false; |
| 303 | using ScalarType = TScalar; |
| 304 | using VectorType = Eigen::Matrix<TScalar, TDimension, 1>; |
| 305 | |
| 306 | VectorType x; |
| 307 | ScalarType value = ScalarType{0}; |
| 308 | VectorType gradient; // empty for DifferentiabilityMode::None. |
| 309 | |
| 310 | // Legacy x-only constructor. Leaves value = 0 and gradient = empty; the |
| 311 | // caller must populate them before the state is consumed by the new |
| 312 | // eval-free code paths. Kept so existing user code that writes |
| 313 | // `FunctionState(x0)` continues to compile; the outer solver `Minimize` |
| 314 | // will evaluate `function(x)` once and rebuild a fully-populated state. |
| 315 | explicit FunctionState(VectorType x_in) : x(std::move(x_in)) {} |
| 316 | |
| 317 | // Evaluate `function` at `x` once and populate all fields. |
| 318 | template <class FunctionT> |
| 319 | FunctionState(const FunctionT& function, VectorType x_in) |
| 320 | : x(std::move(x_in)) { |
| 321 | if constexpr (FunctionT::Differentiability == DifferentiabilityMode::None) { |
| 322 | value = function(x); |
| 323 | } else { |
| 324 | value = function(x, &gradient); |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | // Trust-me constructor: caller has already computed `value` and `gradient` |
| 329 | // at `x` (typically the line search's last internal evaluation). |
| 330 | FunctionState(VectorType x_in, ScalarType value_in, VectorType gradient_in) |
| 331 | : x(std::move(x_in)), value(value_in), gradient(std::move(gradient_in)) {} |
| 332 | }; |
| 333 | |
| 334 | template <typename TScalar, int TDimension> |
| 335 | FunctionState(Eigen::Matrix<TScalar, TDimension, 1>) |