C++ 将线性代数库与Boost::Units相结合

C++ 将线性代数库与Boost::Units相结合,c++,boost,linear-algebra,eigen,boost-units,C++,Boost,Linear Algebra,Eigen,Boost Units,我做了大量的科学编程,在Boost.Units(它提供了量的编译时量纲分析)和线性代数中使用本征2(Egeng 2)方面都有很好的经验。Boost.Units提供了量的编译时量纲分析(即用单位标记量,从而捕捉到经典物理量纲分析中的许多错误) 然而,Eigen没有单位的概念,虽然可以在矩阵中为Eigen设置标量,但它期望两个量的乘积产生相同的类型,这显然不适用于单位。例如,代码如下: using boost::units::quantity; namespace si = boost::units

我做了大量的科学编程,在Boost.Units(它提供了量的编译时量纲分析)和线性代数中使用本征2(Egeng 2)方面都有很好的经验。Boost.Units提供了量的编译时量纲分析(即用单位标记量,从而捕捉到经典物理量纲分析中的许多错误)

然而,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();
使用boost::units::quantity;
名称空间si=boost::units::si;
本征矩阵<数量<长度>,2,1>米向量;
数量norm=meter_vector.squaredNorm();
不起作用,即使它在逻辑上是正确的


是否有支持单位的矩阵库?我知道这在过去是出了名的难以实现,C++11和
decltype
将使这更容易实现,但使用C++03和模板专门化肯定是可行的。

您应该查看此Wiki页面:


Eigen需要一些工作来使用原始数据类型以外的数据类型,但通常是可能的。

我相信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;
}
#包括
#包括
#包括
#包括
使用boost::units::quantity;
名称空间si=boost::units::si;
命名空间闪电战{
模板
结构乘法<数量,数量>
{
typedef typename boost::units::multiply_typeof_helper::键入T_numtype;
静态内联T_numtype apply(数量a,数量b){返回a*b;}
};
}
使用名称空间闪电战;
int main(){
数组<数量,1>矩阵;
数组<数量,1>面积;
面积=矩阵*矩阵;
返回0;
}

使用标准Egen library插件选项的困难在于,需要更换现有的运算符+、-、*,以便使用增压装置数量

例如,对于要使用*multiply运算符的Boost units自定义类型,对于任意自定义类型,它需要如下所示:

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>( ... );
}
模板
自定义类型
运算符*(常数自定义类型和x,常数自定义类型和y)
{
typedef typename boost::units::multiply_typeof_helper::type type;
返回自定义_类型(…);
}
请注意,返回类型与输入类型不同。这里使用模板帮助器multiply\u typeof\u helper创建返回类型。这是因为将米与秒相乘不会得到任何一个单位的数量。但是,默认的Eigen*运算符将返回与输入相同的“类型”——这就是问题所在


另一个选项是将本征矩阵嵌入到数量中,而不是将数量嵌入到矩阵中。

谢谢您的提示。已经阅读了页面并按照提示进行了操作。关键是,operator+工作正常,但例如operator*是错误的,因为meter*meter不是一个meter。作为记录,因为我必须自己搜索一点:告诉你如何推广用户定义的类型。谢谢你的提示。