From 6fc701170e199fdbead3c137c304eff5f9d2d178 Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Wed, 14 Oct 2026 16:07:24 +0900 Subject: [PATCH] test(solvers): verify thread scope across retained size transitions --- .../linear/mkl_pardiso_solver_test.cpp | 26 +++++++++++++++++++ .../solvers/linear/tangent_solver_test.cpp | 26 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp b/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp index b77e150..4758e70 100644 --- a/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp +++ b/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp @@ -193,6 +193,32 @@ TEST(MklPardisoSolver, RefactorizesWithoutLeakingState) { 1.0e-10); } +TEST(MklPardisoSolver, SingleEquationScopeTransitionsBetweenRetainedSizes) { + const int previous = mkl_set_num_threads_local(0); + struct Restore { + int previous; + ~Restore() { static_cast(mkl_set_num_threads_local(previous)); } + } restore{previous}; + const int default_threads = mkl_get_max_threads(); + fesa::MklPardisoSolver solver; + ASSERT_TRUE(solver.Factorize(MakeDenseCsr(1U, {2.0})).IsOk()); + auto single = MakeVector({0.0}); + ASSERT_TRUE(solver.Solve(MakeVector({4.0}), single).IsOk()); + EXPECT_DOUBLE_EQ(single[0U], 2.0); + ASSERT_TRUE(solver.Factorize(MakeDenseCsr(2U, {2, 0, 0, 3})).IsOk()); + fesa::Vector pair{2U}; + ASSERT_TRUE(solver.Solve(MakeVector({4, 6}), pair).IsOk()); + EXPECT_NEAR(pair[0U], 2, 1e-14); + EXPECT_NEAR(pair[1U], 2, 1e-14); + EXPECT_EQ(mkl_get_max_threads(), default_threads); + EXPECT_EQ(mkl_set_num_threads_local(0), 0); + ASSERT_TRUE(solver.Factorize(MakeDenseCsr(1U, {4.0})).IsOk()); + ASSERT_TRUE(solver.Solve(MakeVector({8.0}), single).IsOk()); + EXPECT_DOUBLE_EQ(single[0U], 2.0); + EXPECT_EQ(mkl_get_max_threads(), default_threads); + EXPECT_EQ(mkl_set_num_threads_local(0), 0); +} + TEST(MklPardisoSolver, ClassifiesSingularIndefiniteAndNonfiniteFailures) { fesa::MklPardisoSolver solver; diff --git a/tests/unit/solvers/linear/tangent_solver_test.cpp b/tests/unit/solvers/linear/tangent_solver_test.cpp index 16795e7..bb7096f 100644 --- a/tests/unit/solvers/linear/tangent_solver_test.cpp +++ b/tests/unit/solvers/linear/tangent_solver_test.cpp @@ -205,4 +205,30 @@ TEST(TangentSolver, SingleEquationScopeRestoresTlsAcrossFreshFailureAndReuse) { EXPECT_TRUE(second.get()); } +TEST(TangentSolver, SingleEquationScopeTransitionsBetweenRetainedSizes) { + const int previous = mkl_set_num_threads_local(0); + struct Restore { + int previous; + ~Restore() { static_cast(mkl_set_num_threads_local(previous)); } + } restore{previous}; + const int default_threads = mkl_get_max_threads(); + fesa::MklPardisoTangentSolver solver; + ASSERT_TRUE(solver.FactorizeFresh(MakeDenseCsr(1U, {2.0})).IsOk()); + auto single = MakeVector({0.0}); + ASSERT_TRUE(solver.SolveCorrection(MakeVector({4.0}), single).IsOk()); + EXPECT_DOUBLE_EQ(single[0U], 2.0); + ASSERT_TRUE(solver.FactorizeFresh(MakeDenseCsr(2U, {2, 1, 0, 3})).IsOk()); + fesa::Vector pair{2U}; + ASSERT_TRUE(solver.SolveCorrection(MakeVector({6, 6}), pair).IsOk()); + EXPECT_NEAR(pair[0U], 2, 1e-14); + EXPECT_NEAR(pair[1U], 2, 1e-14); + EXPECT_EQ(mkl_get_max_threads(), default_threads); + EXPECT_EQ(mkl_set_num_threads_local(0), 0); + ASSERT_TRUE(solver.FactorizeFresh(MakeDenseCsr(1U, {4.0})).IsOk()); + ASSERT_TRUE(solver.SolveCorrection(MakeVector({8.0}), single).IsOk()); + EXPECT_DOUBLE_EQ(single[0U], 2.0); + EXPECT_EQ(mkl_get_max_threads(), default_threads); + EXPECT_EQ(mkl_set_num_threads_local(0), 0); +} + } // namespace