我在Eigen Library中使用混合表达式中的自定义标量类型时遇到问题。我按照指示添加了自定义标量类型 这里https://eigen.tuxfamily.org/dox/TopicCustomizing_CustomScalar.html。尽管遵循这些我无法得到我的代码编译。我假设我没有正确地遵循指示,所以我希望有人可以帮我告诉我我做错了什么。
具体来说,我把我的问题归结为一个非常简单的例子。我有一个名为“cplx”的类型(你可以在这里找到它:http://mdolab.engin.umich.edu/sites/default/files/complexify.h_0.txt),我用它来做复杂的数值微分。我试图在Eigen中使用cplx作为标量类型。我按照上面链接的说明生成了以下NumTraits结构,
template<> struct NumTraits<cplx> : NumTraits<std::complex<double>>
{
typedef double Real;
typedef cplx NonInteger;
typedef cplx Nested;
enum {
IsComplex = 1,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 2 * NumTraits<double>::ReadCost,
AddCost = 2 * NumTraits<double>::AddCost,
MulCost = 4 * NumTraits<double>::MulCost + 2 * NumTraits<double>::AddCost
};
};
然后我想构建以下形式的表达式:
Eigen::Matrix<cplx, 3, 10> dc;
Eigen::Matrix<double, 10, 3> dNdx;
Eigen::Matrix<cplx, 3, 3> Fc = dc * dNdx;
当我尝试编译时,我得到以下错误:
Severity Code Description Project File Line Suppression State
Error C2672 'Eigen::internal::gebp_traits<cplx,double,false,false>::madd': no matching overloaded function found Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 999
Error C2782 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': template parameter 'AccPacketType' is ambiguous Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 999
Error C2784 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': could not deduce template argument for 'AccPacketType &' from 'double' Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 999
Error C2672 'Eigen::internal::gebp_traits<cplx,double,false,false>::madd': no matching overloaded function found Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1000
Error C2782 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': template parameter 'AccPacketType' is ambiguous Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1000
Error C2784 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': could not deduce template argument for 'AccPacketType &' from 'double' Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1000
Error C2672 'Eigen::internal::gebp_traits<cplx,double,false,false>::madd': no matching overloaded function found Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1001
Error C2782 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': template parameter 'AccPacketType' is ambiguous Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1001
Error C2784 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': could not deduce template argument for 'AccPacketType &' from 'double' Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1001
Error C2782 'void Eigen::internal::gebp_traits<cplx,double,false,false>::madd(const LhsPacketType &,const RhsPacketType &,AccPacketType &,AccPacketType &) const': template parameter 'AccPacketType' is ambiguous Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1002
Error C2672 'Eigen::internal::gebp_traits<cplx,double,false,false>::madd': no matching overloaded function found Simulation_MechanicalTest c:\users\nick.burgess\documents\code\toolsets\eigen\3.3.3\source\eigen\src\core\products\generalblockpanelkernel.h 1002
之前有没有人遇到此错误。我对可能出错的事感到困惑?作为尝试调试的一部分,我当然尝试像
这样的表达式Eigen::Matrix<cplx, 3, 10> dc;
Eigen::Matrix<cplx, 10, 3> dNdx;
Eigen::Matrix<cplx, 3, 3> Fc = dc * dNdx;
编译得很好。完全没有错误。因此,将double和cplx混合在一起显然是一个问题。任何帮助,将不胜感激。
答案 0 :(得分:1)
默认情况下,Eigen不允许在表达式中混合使用不同的标量类型(无隐式转换)。
Eigen::Matrix<float, 4,4> Af;
Eigen::Matrix<double,4,4> Ad;
// Af*Ad; // not allowed
Af.cast<double>()*Ad; // explicitly cast Af to double
要允许混合不同的标量类型,您可以如上所述明确地将一种类型转换为另一种类型,或者专门化以下特征(另外还有Eigen::NumTraits
):
namespace Eigen{
template<typename BinOp>
struct ScalarBinaryOpTraits<cplx,double,BinOp>
{ typedef cplx ReturnType; };
template<typename BinOp>
struct ScalarBinaryOpTraits<double,cplx,BinOp>
{ typedef cplx ReturnType; };
}
这还应允许添加,减去和除以cplx
和double
表达式(我没有使用您的代码对此进行测试)。
答案 1 :(得分:0)
我不知道这是否会对你有所帮助;我正在使用visual studio 2017 CE,编译器选项设置为c ++ 17。我不得不禁用sdl检查。我将您的复杂类移植到头文件中,这就是我所看到的:
如果你定义它并尝试编译它可以正常工作:
Eigen::Matrix<cplx, 3, 10> dc;
Eigen::Matrix<double, 10, 3> dNdx;
但是,当您尝试声明您的特征矩阵的第三个实例时
Eigen::Matrix<cplx, 3, 3> Fc = dc * dNdx;
这是编译器错误的来源;尝试扩展表达式,这可能会对您有所帮助。
Eigen::Matrix<cplx, 3, 3> = Eigen::Matrix<cplx, 3, 10> * Eigen::Matrix<double, 10, 3>
您似乎收到operator=
,operator*
或两者的编译错误,因为它不知道如何解决简单表达式的歧义
cplx = cplx * double.
它不知道如何从double转换为cplx,要么没有定义转换,要么模板实例化不明确。
修改强>
我对你的情况做了一些研究。在您的标题中,我注释掉了行using namespace std;
并在需要时使用了std::
解析运算符,认为库命名空间之间可能存在冲突。这最终给了我与编译完全相同的结果。
我的下一步是我使用了所有用户定义的重载构造函数,对于只采用单个参数的任何构造函数,我使用explicit
作为前缀。他们现在看起来像这样:
cplx() : std::complex<double>() {};
explicit cplx( const double& d ) : std::complex<double>( d ) {};
cplx( const double& r, const double& i ) : std::complex<double>( r, i ) {};
explicit cplx( const std::complex<double>& z ) : std::complex<double>( z ) {};
explicit cplx( const std::complex<float>& z ) : std::complex<double>( z ) {};
我还为此cpp file
添加了.h
,这样我就可以单独编译此文件。
你的大多数重载和一些函数现在都给我带来了与MSVC完全相同的编译器错误。
错误C2440:'return':无法从'std :: complex'转换为'cplx'
这些运算符和函数是给出此错误的:
inline cplx cplx::operator+() const {
return +std::complex<double>( *this );
}
inline cplx cplx::operator+( const cplx& z ) const {
return std::complex<double>( *this ) + std::complex<double>( z );
}
inline cplx cplx::operator+( const double& r ) const {
return std::complex<double>( *this ) + r;
}
inline cplx cplx::operator+( const int& i ) const {
return std::complex<double>( *this ) + double( i );
}
inline cplx operator+( const double& r, const cplx& z ) {
return r + std::complex<double>( z );
}
inline cplx operator+( const int& i, const cplx& z ) {
return double( i ) + std::complex<double>( z );
}
inline cplx cplx::operator-() const {
return -std::complex<double>( *this );
}
inline cplx cplx::operator-( const cplx& z ) const {
return std::complex<double>( *this ) - std::complex<double>( z );
}
inline cplx cplx::operator-( const double& r ) const {
return std::complex<double>( *this ) - r;
}
inline cplx cplx::operator-( const int& i ) const {
return std::complex<double>( *this ) - double( i );
}
inline cplx operator-( const double& r, const cplx& z ) {
return r - std::complex<double>( z );
}
inline cplx operator-( const int& i, const cplx& z ) {
return double( i ) - std::complex<double>( z );
}
inline cplx cplx::operator*( const cplx& z ) const {
return std::complex<double>( *this )*std::complex<double>( z );
}
inline cplx cplx::operator*( const double& r ) const {
return std::complex<double>( *this )*r;
}
inline cplx cplx::operator*( const int& i ) const {
return std::complex<double>( *this )*double( i );
}
inline cplx operator*( const double& r, const cplx& z ) {
return r * std::complex<double>( z );
}
inline cplx operator*( const int& i, const cplx& z ) {
return double( i )*std::complex<double>( z );
}
inline cplx cplx::operator/( const cplx& z ) const {
return std::complex<double>( *this ) / std::complex<double>( z );
}
inline cplx cplx::operator/( const double& r ) const {
return std::complex<double>( *this ) / r;
}
inline cplx cplx::operator/( const int& i ) const {
return std::complex<double>( *this ) / double( i );
}
inline cplx operator/( const double& r, const cplx& z ) {
return r / std::complex<double>( z );
}
inline cplx operator/( const int& i, const cplx& z ) {
return double( i ) / std::complex<double>( z );
}
inline cplx sin( const cplx& z ) {
return sin( std::complex<double>( z ) );
}
inline cplx sinh( const cplx& z ) {
return sinh( std::complex<double>( z ) );
}
inline cplx cos( const cplx& z ) {
return cos( std::complex<double>( z ) );
}
inline cplx cosh( const cplx& z ) {
return cosh( std::complex<double>( z ) );
}
inline cplx tan( const cplx& z ) {
return tan( std::complex<double>( z ) );
}
inline cplx tanh( const cplx& z ) {
return tanh( std::complex<double>( z ) );
}
inline cplx log10( const cplx& z ) {
return log10( std::complex<double>( z ) );
}
inline cplx log( const cplx& z ) {
return log( std::complex<double>( z ) );
}
inline cplx sqrt( const cplx& z ) {
return sqrt( std::complex<double>( z ) );
}
inline cplx exp( const cplx& z ) {
return exp( std::complex<double>( z ) );
}
inline cplx pow( const cplx& a, const cplx& b ) {
return pow( std::complex<double>( a ), std::complex<double>( b ) );
}
inline cplx pow( const cplx& a, const double& b ) {
return pow( std::complex<double>( a ), b );
}
inline cplx pow( const cplx& a, const int& b ) {
return pow( std::complex<double>( a ), double( b ) );
}
inline cplx pow( const double& a, const cplx& b ) {
return pow( a, std::complex<double>( b ) );
}
inline cplx pow( const int& a, const cplx& b ) {
return pow( double( a ), std::complex<double>( b ) );
}
此外,我没有为您的班级operator=()
cplx
根据Eigen在using custom scalar types
的网站上的最后一点,我没有看到Eigen::NumTraits<T>
的专业化来自他们对第2步的要求:
2.添加struct Eigen :: NumTraits的特化(参见NumTraits)
答案 2 :(得分:0)
我一直在研究类似的问题,但是使用双数的类进行微分而不是复杂(这是更好的选择-操作更少,没有epsilon大小调整问题)。
仍然存在一些较小的编译器问题,但是无论如何...以防万一这些将有助于将来有人再次遇到这个问题,以下是在Eigen中使用该类型的文件:
https://github.com/tesch1/CppNumericalSolvers/tree/templated/unsupported/Eigen/src/DualNum