fix(math): preserve certified sums and complete MKL algebra

This commit is contained in:
KOKO\Mimi
2026-10-14 15:40:52 +09:00
parent 59c8e93b07
commit 590a93793f
9 changed files with 236 additions and 95 deletions
@@ -22,6 +22,7 @@
#include "fesa/math/vector.h"
#include "fesa/solvers/linear/mkl_pardiso_solver.h"
#include "solvers/eigen/mkl_feast_eigen_solver_test_seam.h"
#include "math/dense_blas_internal.h"
namespace fesa {
@@ -1095,6 +1096,10 @@ Result<FeastEigenResult> MklFeastEigenSolver::SolveImpl(
const double difference = action[row] - mu * mass_action[row];
residual_norm += difference * difference;
ordered_vectors(row, output) = vectors[row + input * n] / norm;
if (!std::isfinite(ordered_vectors(row, output)))
return Result<FeastEigenResult>::Failure(
TraceFailure("eigenpair-validation-failed", std::to_string(input),
"FEAST returned a non-normalizable eigenvector."));
}
double residual_denominator = norm;
if (mass != nullptr) {
@@ -1183,20 +1188,20 @@ Result<FeastEigenResult> MklFeastEigenSolver::SolveImpl(
}
double gram_error = 0.0;
double gram_squared = 0.0;
std::vector<Vector> mass_modes;
mass_modes.reserve(count);
Matrix mass_modes{n, count};
for (std::size_t right = 0; right < count; ++right) {
Vector mode(n);
for (std::size_t row = 0; row < n; ++row)
mode[row] = ordered_vectors(row, right);
mass_modes.push_back(mass != nullptr ? mass->Multiply(mode)
: std::move(mode));
const auto action = mass != nullptr ? mass->Multiply(mode) : std::move(mode);
for (std::size_t row = 0; row < n; ++row)
mass_modes(row, right) = action[row];
}
const auto gram = dense_blas_internal::MultiplyTransposeLeft(ordered_vectors,
mass_modes);
for (std::size_t left = 0U; left < count; ++left) {
for (std::size_t right = 0U; right < count; ++right) {
double dot = 0.0;
for (std::size_t row = 0U; row < n; ++row)
dot += ordered_vectors(row, left) * mass_modes[right][row];
const double dot = gram(left, right);
const double expected = left == right ? 1.0 : 0.0;
const double difference = std::abs(dot - expected);
gram_squared += difference * difference;