Add EigenSystem with multi-dtype support and shared_ptr management#833
Conversation
Add float32/complex64/complex128 variants of EigenSystem alongside the existing float64 path. Complex eigenvalues are returned as separate wr/wi real arrays, and the Plex wrapper is renamed to `EigenSystem` in Python. The class is now managed exclusively via std::shared_ptr through a construct() factory function, The type-erased EigenSystemPlex implementation is consolidated into `EigenSystem.cpp` to save compilation time. Add more LAPACK type compatbility in `lapack_compat.hpp` and update the Python tests accordingly.
| // Reinterpret the plex's type-erased instance as the typed SimpleArray<T> it | ||
| // actually holds; the caller must have verified data_type() == T. | ||
| template <typename T> | ||
| static SimpleArray<T> const & typed_array(SimpleArrayPlex const & plex) |
There was a problem hiding this comment.
Static function template to support type-erased SimpleArray.
| static constexpr bool is_complex = is_complex_v<T>; | ||
|
|
||
| explicit EigenSystem(array_type const & matrix, bool do_vl = true, bool do_vr = true); | ||
| static std::shared_ptr<EigenSystem> construct(array_type const & matrix, bool do_vl = true, bool do_vr = true) |
There was a problem hiding this comment.
Factory function template to make EigenSystem exclusively managed by using std::shared_ptr.
| throw std::runtime_error(std::format( | ||
| "EigenSystem::run: DGEEV workspace query failed with info={}", | ||
| static_cast<int64_t>(info))); | ||
| // CGEEV/ZGEEV return eigenvalues as a single complex array and need a |
There was a problem hiding this comment.
[CZ]GEEV require a single complex array as the working space. To keep the external interface the same, the implementation here differs between complex and scalar input.
|
|
||
| /** | ||
| * Overloaded thin wrappers around the LAPACK *GEEV entry points, presenting a | ||
| * uniform call shape to EigenSystem<T>. modmesh's Complex<T> is |
There was a problem hiding this comment.
Complex<T> uses the same memory layout as std::complex.
| WrapEigenSystem<Complex<double>>::commit(mod, "EigenSystemComplex128", "Eigen problem solver (complex128)"); | ||
| // EigenSystem is the type-erased, general entry point that infers the | ||
| // element type from a SimpleArrayPlex (C++ class: EigenSystemPlex). | ||
| WrapEigenSystemPlex::commit(mod, "EigenSystem", "Type-erased eigen problem solver"); |
There was a problem hiding this comment.
Type-erased EigenSystemPlex is wrapped to Python as EigenSystem.
| conjugate pair (wi[j] > 0, wi[j+1] = -wi[j]) the j-th and (j+1)-th | ||
| columns hold the real and imaginary parts of the eigenvector; the | ||
| (j+1)-th eigenvector is the complex conjugate of the j-th. | ||
| class TestEigenSystemPlexTC(unittest.TestCase): |
There was a problem hiding this comment.
Test the type-erased EigenSystem.
|
|
||
| REAL = ("float32", "float64") | ||
| COMPLEX = ("complex64", "complex128") | ||
| ALL = REAL + COMPLEX |
|
|
||
| @classmethod | ||
| def get_complex_type(cls): | ||
| _ = {'float32': 'complex64', 'float64': 'complex128'} |
There was a problem hiding this comment.
Use corresponding complex types.
| np.testing.assert_array_equal(solver.matrix.ndarray, A_np) | ||
| @unittest.skipIf(mm.EigenSystemFloat32 is None, | ||
| "EigenSystem is not built (no vendor LAPACK)") | ||
| class TestLinalgEigenSystemFloat32TC(EigenSystemTB, unittest.TestCase): |
There was a problem hiding this comment.
Test for all 4 types with the explicitly typed EigenSystem* classes.
shared_ptr management
Add float32/complex64/complex128 variants of EigenSystem alongside the existing float64 path. Complex eigenvalues are returned as separate wr/wi real arrays, and the Plex wrapper is renamed to
EigenSystemin Python. The class is now managed exclusively viastd::shared_ptrthrough aconstruct()factory function,The type-erased EigenSystemPlex implementation is consolidated into
EigenSystem.cppto save compilation time.Add more LAPACK type compatbility in
lapack_compat.hppand update the Python tests accordingly.For issue #790.