我做了大量的科学编程,并且使用这两个Boost都有很好的体验。单元,它提供了对数量的编译时量纲分析(即用单位标记数量,从而捕获经典物理量纲分析的许多错误),并使用特征2用于线性代数。
然而,Eigen没有单位的概念,虽然你可以为Eigen设置矩阵中的标量,但它期望两个量的乘法产生相同的类型,这对于单位显然是不正确的。例如,代码如下:
using boost::units::quantity;
namespace si = boost::units::si;
Eigen::Matrix< quantity< si::length >, 2, 1 > meter_vector;
quantity< si::area > norm = meter_vector.squaredNorm();
不工作,即使它在逻辑上是正确的。
有支持单位的矩阵库吗?我知道这在过去是出了名的难以实现的,c++ 11和decltype
将使它变得容易得多,但这在c++ 03和模板专门化中肯定是可能的。
我相信Blitz++支持Boost的大部分功能。单位功能。
编辑OP:作为参考,这里是我测试闪电战矩阵乘法功能的完整测试代码:
#include <blitz/array.h>
#include <boost/units/systems/si/area.hpp>
#include <boost/units/systems/si/length.hpp>
#include <boost/units/quantity.hpp>
using boost::units::quantity;
namespace si = boost::units::si;
namespace blitz {
template< typename U1, typename T1, typename U2, typename T2>
struct Multiply< quantity<U1,T1>, quantity<U2,T2> >
{
typedef typename boost::units::multiply_typeof_helper< quantity<U1,T1>, quantity<U2,T2> >::type T_numtype;
static inline T_numtype apply( quantity<U1,T1> a, quantity<U2,T2> b ) { return a*b; }
};
}
using namespace blitz;
int main() {
Array< quantity<si::length>, 1 > matrix;
Array< quantity<si::area>, 1 > area;
area = matrix * matrix;
return 0;
}
您应该查看这个Wiki页面:http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html
特征需要一些工作来使用除了基本数据类型,但通常是可能的。
使用标准Eigen库插件选项的困难在于,要使用Boost Units数量,需要替换现有的操作符+,-,*等。
例如,对于Boost units自定义类型,要使用*乘法运算符,对于任意的CUSTOM_TYPE,它需要看起来像这样:
template<class X,class Y>
CUSTOM_TYPE<typename boost::units::multiply_typeof_helper<X,Y>::type>
operator*(const CUSTOM_TYPE<X>& x,const CUSTOM_TYPE<Y>& y)
{
typedef typename boost::units::multiply_typeof_helper<X,Y>::type type;
return CUSTOM_TYPE<type>( ... );
}
注意返回类型与输入类型不一样。这里使用模板帮助器multiply_typeof_helper来创建返回类型。这是因为米乘以秒不会得到任何一个单位的量。然而,默认的Eigen *运算符将返回与输入相同的"类型"——这就是问题所在。
另一种选择是将特征矩阵嵌入到数量中,而不是将数量嵌入到矩阵中。
具有一致单位的向量/矩阵的简单情况可以通过调整特征矩阵的值类型来部分解决,但这需要大量的用户以专门化特征的形式进行干预,即使这也不足以满足所有操作。
然而,如果你想解决包含非均匀单位的矩阵的一般情况(即每个条目可以有附加单位),那么通过自定义矩阵的值类型将无法工作。
您需要一种类似于这里展示的方法,它在线性代数库之上分层并提供单元注释:https://m.youtube.com/watch?v=4LmMwhM8ODI