我正在进行大量的科学编程,并使用Boost.Units提供了非常好的经验,它提供了数量的编译时维度分析(即带有单位的标签数量,从而通过经典的物理尺寸分析捕获了许多错误)并使用特征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和模板专业化。
答案 0 :(得分:7)
我相信Blitz ++支持很多Boost.Units功能。
由OP编辑:这里的参考是用于测试Blitz矩阵乘法功能的完整测试代码:
#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;
}
答案 1 :(得分:1)
您应该查看此Wiki页面: http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html
Eigen需要使用除原始数据类型以外的一些工作,但通常是可能的。
答案 2 :(得分:0)
使用标准Eigen库插件选项的难点在于,现有的运算符+, - ,*等需要替换为要使用的Boost Units数量。
例如,对于使用* multiply运算符的Boost单位自定义类型,对于任意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 *运算符将返回相同的&#34;类型&#34;作为输入 - 这就是问题。
另一种选择是将特征矩阵嵌入数量中,而不是将数量嵌入矩阵中。