【发布时间】:2019-12-04 23:54:19
【问题描述】:
我有一个通过有限元法求解微分方程的代码。为此,我使用 Eigen,因此我不必自己实现矩阵。现在,在未来,我想在另一个库中尝试相同的代码,比如犰狳。我希望能够在库之间轻松切换。
我是新手,我的问题基本上是以下是否是好的做法。为了使我的代码适用于任何矩阵库,我在标题中定义了 DataType 和 MatrixImplementation 类型。后者应该决定是使用一个库还是另一个。
// data type
using DataType = double;
// matrix implementation
template <typename TYPE = DataType, size_t ROWS = 1, size_t COLS = 1>
using MatrixImplementation = Eigen::Matrix<DataType, ROWS, COLS>;
然后我可以检查 Eigen 是否是这样使用的:
// check which matrix implementation
constexpr static bool is_eigen = std::is_same<MatrixImplementation<DataType, 1, 1>,Eigen::Matrix<DataType, 1, 1>>::value;
我现在可以定义IndexType(通常是size_t 或unsigned int)来访问向量或矩阵的元素,如下所示:
// index type
using IndexType = std::conditional_t<is_eigen, Eigen::Index,
std::conditional_t<is_armadillo, ...,
std::conditional_t<is_***, ...,
...>;
同样,我可以如下定义Matrix 类型:
// matrix type
template <size_t ROWS, size_t COLS>
using Matrix = std::conditional_t<is_eigen, Eigen::Matrix<DataType, ROWS, COLS>, ...>;
等等。此外,我必须定义矩阵上的操作(仅我需要的那些),例如范数:
template <class Matrix>
constexpr auto norm(const Matrix& m)
{
if constexpr (is_eigen)
return m.norm();
else if constexpr (is_armadillo)
return ...;
else
return 0.0;
}
然后我会按如下方式计算范数:
Matrix<3,3> my_matrix;
auto norm_matrix = norm(my_matrix);
这是要走的路吗?还是有更好的选择,也许我应该考虑一些花哨的设计模式?
更新
感谢@MaxLanghof 的评论:
当您可能只在以下位置使用 Eigen 时,您将如何实现 is_armadillo 一点?您是否计划始终包含所有库?
我现在让 CMake 将要使用的矩阵库写入 config.h 文件:
#define MATRIX_LIBRARY EIGEN // this value is written by cmake
#define EIGEN 1
#define ARMADILLO 2
现在,我可以确定代码是使用 Eigen 还是 Armadillo,如下所示:
#if MATRIX_LIBRARY == EIGEN
constexpr static bool is_eigen = true;
#else
constexpr static bool is_eigen = false;
#endif
#if MATRIX_LIBRARY == ARMADILLO
constexpr static bool is_armadillo = true;
#else
constexpr static bool is_armadillo = false;
#endif
【问题讨论】:
-
当您在某些时候可能只使用
Eigen时,您将如何实现is_armadillo?您是否计划始终包含所有库? -
在任何情况下,
Eigen和armadillo都是具有非平凡接口的大型复杂库(可能与任何其他著名的 C++ 矩阵库相同)。核心矩阵类型可能具有足够相似的接口,可以或多或少地将它们换掉,但是(正如您已经注意到的norm),其他功能会有很大不同。并且差异可能不仅仅是表面上的——也许一个库就地执行 SVD,另一个库没有。您必须自己明智地包装所有此类功能。这不是一项小任务,我不确定它是否适用于更大的项目。 -
@MaxLanghof 好点...如果我想使用 Eigen 包含犰狳会很愚蠢...然后我将无法实现 is_armadillo...除非我对其进行硬编码,或者让 cmake 在哪个库可用的函数中为我生成该变量。
-
您可能想查看预处理器标志(您必须用一些
#ifdef包装MatrixImplementation的定义)。然后,您可以通过项目的 CMake 配置设置所需的标志,例如-DMYPROJECT_MATRIX_LIB=eigen/armadillo/adhoc。如果您将#ifdefs放在关键定义和依赖项周围 - 您将获得模块化行为。支持这个虽然很痛苦......
标签: c++ dependencies