fix: use residual stopping for FEAST eigenanalysis

This commit is contained in:
KOKO\Mimi
2026-09-10 01:52:49 +09:00
parent 76192508fd
commit 7ebdce373c
12 changed files with 209 additions and 17 deletions
@@ -3,6 +3,8 @@
#include <gtest/gtest.h>
#include <hdf5.h>
#include <array>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <functional>
@@ -78,6 +80,15 @@ TEST(EigenHdf5ResultsWriter, WritesModalSchemaAndRejectsTamperedState) {
H5Fopen(path.string().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
ASSERT_GE(file, 0);
EXPECT_GT(H5Lexists(file, "/steps/Step-1/eigen/modes", H5P_DEFAULT), 0);
const hid_t controls =
H5Dopen2(file, "/steps/Step-1/eigen/backend/base_fpm", H5P_DEFAULT);
ASSERT_GE(controls, 0);
std::array<std::int64_t, 128> stored_controls{};
ASSERT_GE(H5Dread(controls, H5T_NATIVE_INT64, H5S_ALL, H5S_ALL,
H5P_DEFAULT, stored_controls.data()),
0);
EXPECT_EQ(stored_controls[5U], 0);
EXPECT_GE(H5Dclose(controls), 0);
EXPECT_GE(H5Fclose(file), 0);
std::ifstream original_file{path, std::ios::binary};
const std::string original{std::istreambuf_iterator<char>{original_file}, {}};
@@ -91,6 +102,7 @@ TEST(EigenHdf5ResultsWriter, WritesModalSchemaAndRejectsTamperedState) {
[](auto& candidate) { candidate.modes[0].cluster_id = 7U; },
[](auto& candidate) { candidate.constraint_mask[0] = 1U; },
[](auto& candidate) { candidate.nodal_reduction[0].rcond_inf = 1e-15; },
[](auto& candidate) { candidate.backend.base_fpm[5U] = 1; },
[](auto& candidate) { candidate.eta_gram = 1e-5; }};
for (const auto& mutate : mutations) {
auto candidate = state;
@@ -71,6 +71,8 @@ TEST(MklFeastEigenSolver, SolvesN1AndRetainsBackendEvidence) {
EXPECT_EQ(result.Value().eigenvectors.Rows(), 1U);
EXPECT_EQ(result.Value().eigenvectors.Columns(), 1U);
EXPECT_EQ(result.Value().thread_count, 1U);
ASSERT_EQ(result.Value().base_fpm.size(), 128U);
EXPECT_EQ(result.Value().base_fpm[5U], 0);
ASSERT_FALSE(result.Value().backend_calls.empty());
EXPECT_EQ(result.Value().backend_calls.front().purpose, "total-enclosure");
EXPECT_EQ(result.Value().backend_calls.back().kind, "solve");