Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 特征值中的自定义标量类型_C++_Eigen_Eigen3 - Fatal编程技术网

C++ 特征值中的自定义标量类型

C++ 特征值中的自定义标量类型,c++,eigen,eigen3,C++,Eigen,Eigen3,我目前正在尝试设置一个自定义标量类型,以便与Egeng3库一起使用(atm它是一个围绕double的简单包装器)。我已经尽我所知遵循了这些原则,基本的事情都很顺利 我需要用我的自定义类型来解决矩阵的特征值问题,而这正是事情开始分裂的地方。我的编译器向我吐出以下错误消息: /Eigen3/Eigen/src/Householder/Householder.h:131:18: error: no viable overloaded '-=' this->row(0) -= tau *

我目前正在尝试设置一个自定义标量类型,以便与Egeng3库一起使用(atm它是一个围绕
double
的简单包装器)。我已经尽我所知遵循了这些原则,基本的事情都很顺利

我需要用我的自定义类型来解决矩阵的特征值问题,而这正是事情开始分裂的地方。我的编译器向我吐出以下错误消息:

/Eigen3/Eigen/src/Householder/Householder.h:131:18: error: no viable overloaded '-='
    this->row(0) -= tau * tmp;
    ~~~~~~~~~~~~ ^  ~~~~~~~~~
/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h:314:10: note: in instantiation of function template specialization 'Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<MyDouble, 2,
      2, 0, 2, 2>, -1, -1, false> >::applyHouseholderOnTheLeft<Eigen::VectorBlock<Eigen::Block<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>, 2, 1, true>, -1> >' requested here
        .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0));
         ^
/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h:161:7: note: in instantiation of member function 'Eigen::HessenbergDecomposition<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>
      >::_compute' requested here
      _compute(m_matrix, m_hCoeffs, m_temp);
      ^
/Eigen3/Eigen/src/Eigenvalues/./RealSchur.h:271:10: note: in instantiation of function template specialization 'Eigen::HessenbergDecomposition<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>
      >::compute<Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<MyDouble, MyDouble>, const Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<MyDouble>, const
      Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2> > > >' requested here
  m_hess.compute(matrix.derived()/scale);
         ^
/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h:389:15: note: in instantiation of function template specialization 'Eigen::RealSchur<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>
      >::compute<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2> >' requested here
  m_realSchur.compute(matrix.derived(), computeEigenvectors);
              ^
/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h:156:7: note: in instantiation of function template specialization 'Eigen::EigenSolver<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2>
      >::compute<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2> >' requested here
      compute(matrix.derived(), computeEigenvectors);
      ^
/home/adam/Documents/Git/spin_phonon_coupling/src/test.cpp:205:52: note: in instantiation of function template specialization 'Eigen::EigenSolver<Eigen::Matrix<MyDouble, 2, 2, 0, 2, 2> >::EigenSolver<Eigen::Matrix<MyDouble, 2, 2, 0, 2,
      2> >' requested here
        Eigen::EigenSolver<Eigen::Matrix<MyDouble, 2, 2>> solver(test);
                                                          ^
/Eigen3/Eigen/src/Core/DenseBase.h:298:14: note: candidate template ignored: could not match 'EigenBase<type-parameter-0-0>' against 'MyDouble'
    Derived& operator-=(const EigenBase<OtherDerived> &other);
             ^
/Eigen3/Eigen/src/Core/MatrixBase.h:161:14: note: candidate template ignored: could not match 'MatrixBase<type-parameter-0-0>' against 'MyDouble'
    Derived& operator-=(const MatrixBase<OtherDerived>& other);
             ^
/Eigen3/Eigen/src/Core/MatrixBase.h:495:46: note: candidate template ignored: could not match 'ArrayBase<type-parameter-0-0>' against 'MyDouble'
    template<typename OtherDerived> Derived& operator-=(const ArrayBase<OtherDerived>& )

Marc Glisse指出我的操作符重载看起来有点奇怪,所以我重写了它们,最初的问题就消失了。我不知道为什么会这样

然后我只遇到了一个问题,即Eigen的
isfinite
函数没有为我的自定义类型定义,所以我继续添加了它的实现(尽管我不确定这是否是一个可靠的实现)

不管怎样,我的代码现在可以编译了。以下是我的代码的修改版本:

#include <iostream>
#include <cmath>
#include <complex>

#include <Eigen/Dense>

class MyDouble {
    public:
        double value;
        MyDouble() : value() {};
        MyDouble(double val) : value(val) {};

        template<typename T>
            MyDouble& operator+=(T rhs) {
                value = static_cast<double>(value + rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator-=(const T &rhs) {
                value = static_cast<double>(value - rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator*=(T rhs) {
                value = static_cast<double>(value * rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator/=(T rhs) {
                value = static_cast<double>(value / rhs);
                return *this;
            }

        MyDouble operator-() const {
            return -value;
        }

        friend std::ostream& operator<<(std::ostream& out, const MyDouble& val) {
            out << val.value << " m";
            return out;
        }

        explicit operator double() {
            return value;
        }
};

#define OVERLOAD_OPERATOR(op,ret) ret operator op(const MyDouble &lhs, const MyDouble &rhs) { \
        return lhs.value op rhs.value; \
    }

OVERLOAD_OPERATOR(+, MyDouble)
OVERLOAD_OPERATOR(-, MyDouble)
OVERLOAD_OPERATOR(*, MyDouble)
OVERLOAD_OPERATOR(/, MyDouble)

OVERLOAD_OPERATOR(>, bool)
OVERLOAD_OPERATOR(<, bool)
OVERLOAD_OPERATOR(>=, bool)
OVERLOAD_OPERATOR(<=, bool)
OVERLOAD_OPERATOR(==, bool)
OVERLOAD_OPERATOR(!=, bool)


MyDouble sqrt(MyDouble val) {
    return std::sqrt(val.value);
}
MyDouble abs(MyDouble val) {
    return std::abs(val.value);
}
MyDouble abs2(MyDouble val) {
    return val * val;
}
bool isfinite(const MyDouble &) { return true; }

namespace Eigen {
    template<> struct NumTraits<MyDouble>
        : NumTraits<double> // permits to get the epsilon, dummy_precision, lowest, highest functions
        {
            typedef MyDouble Real;
            typedef MyDouble NonInteger;
            typedef MyDouble Nested;
            enum {
                IsComplex = 0,
                IsInteger = 0,
                IsSigned = 1,
                RequireInitialization = 0,
                ReadCost = 1,
                AddCost = 3,
                MulCost = 3
            };
        };

    template<typename BinaryOp>
    struct ScalarBinaryOpTraits<MyDouble,double,BinaryOp> { typedef MyDouble ReturnType;  };

    template<typename BinaryOp>
    struct ScalarBinaryOpTraits<double,MyDouble,BinaryOp> { typedef MyDouble ReturnType;  };
}

int main() {
    Eigen::Matrix<MyDouble, 2, 2> test;
    test << 1, 2, 3, 4;

    Eigen::Matrix<double, 2, 2> reference;
    reference << 1, 2, 3, 4;

    MyDouble a = 3;
    a += 2;
    a = 2 + a;
    a = a + 2;
    a -= 2;
    a -= MyDouble(3);

    a = a / a;

    std::complex<MyDouble> complexTest(3,4);
    complexTest *= 2;

    Eigen::EigenSolver<Eigen::Matrix<MyDouble, 2, 2>> solver(test);
    Eigen::EigenSolver<Eigen::Matrix<double, 2, 2>> refSolver(reference);
    std::cout << "MyDouble:" << std::endl;
    std::cout << test.trace() << std::endl;
    std::cout << solver.eigenvalues() << std::endl;
    std::cout << "\nRefernce:" << std::endl;
    std::cout << reference.trace() << std::endl;
    std::cout << refSolver.eigenvalues() << std::endl;
}
#包括
#包括
#包括
#包括
类MyDouble{
公众:
双重价值;
MyDouble():value(){};
MyDouble(double val):值(val){};
模板
MyDouble运算符+=(T rhs){
值=静态施法(值+rhs);
归还*这个;
}
模板
MyDouble和运算符-=(常数T和rhs){
值=静态施法(值-rhs);
归还*这个;
}
模板
MyDouble运算符*=(T rhs){
值=静态施法(值*rhs);
归还*这个;
}
模板
MyDouble&运算符/=(T rhs){
值=静态施法(值/rhs);
归还*这个;
}
MyDouble运算符-()常量{
返回值;
}

friend std::ostream&operator您对运算符的显式专门化看起来很奇怪,被我尝试过的编译器拒绝了。
friend MyDouble运算符+(MyDouble a,MyDouble b){return a.value+b.value;}
更常见。此外,
特征解算器
必须能够处理复杂的问题(在您的情况下,它将尝试实例化
std::complex
)@ggael我尝试实例化
std::complex
,这似乎完美无瑕。您是否考虑了特定的场景,这会有问题?只要
MyDouble
只是
double
的包装器,编写
bool是有限的(const MyDouble&x){return std::isfinite(x.value);}
isfinite
如果(且仅当)
x
为无限或NaN,则应为false。
#include <iostream>
#include <cmath>
#include <complex>

#include <Eigen/Dense>

class MyDouble {
    public:
        double value;
        MyDouble() : value() {};
        MyDouble(double val) : value(val) {};

        template<typename T>
            MyDouble& operator+=(T rhs) {
                value = static_cast<double>(value + rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator-=(const T &rhs) {
                value = static_cast<double>(value - rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator*=(T rhs) {
                value = static_cast<double>(value * rhs);
                return *this;
            }

        template<typename T>
            MyDouble& operator/=(T rhs) {
                value = static_cast<double>(value / rhs);
                return *this;
            }

        MyDouble operator-() const {
            return -value;
        }

        friend std::ostream& operator<<(std::ostream& out, const MyDouble& val) {
            out << val.value << " m";
            return out;
        }

        explicit operator double() {
            return value;
        }
};

#define OVERLOAD_OPERATOR(op,ret) ret operator op(const MyDouble &lhs, const MyDouble &rhs) { \
        return lhs.value op rhs.value; \
    }

OVERLOAD_OPERATOR(+, MyDouble)
OVERLOAD_OPERATOR(-, MyDouble)
OVERLOAD_OPERATOR(*, MyDouble)
OVERLOAD_OPERATOR(/, MyDouble)

OVERLOAD_OPERATOR(>, bool)
OVERLOAD_OPERATOR(<, bool)
OVERLOAD_OPERATOR(>=, bool)
OVERLOAD_OPERATOR(<=, bool)
OVERLOAD_OPERATOR(==, bool)
OVERLOAD_OPERATOR(!=, bool)


MyDouble sqrt(MyDouble val) {
    return std::sqrt(val.value);
}
MyDouble abs(MyDouble val) {
    return std::abs(val.value);
}
MyDouble abs2(MyDouble val) {
    return val * val;
}
bool isfinite(const MyDouble &) { return true; }

namespace Eigen {
    template<> struct NumTraits<MyDouble>
        : NumTraits<double> // permits to get the epsilon, dummy_precision, lowest, highest functions
        {
            typedef MyDouble Real;
            typedef MyDouble NonInteger;
            typedef MyDouble Nested;
            enum {
                IsComplex = 0,
                IsInteger = 0,
                IsSigned = 1,
                RequireInitialization = 0,
                ReadCost = 1,
                AddCost = 3,
                MulCost = 3
            };
        };

    template<typename BinaryOp>
    struct ScalarBinaryOpTraits<MyDouble,double,BinaryOp> { typedef MyDouble ReturnType;  };

    template<typename BinaryOp>
    struct ScalarBinaryOpTraits<double,MyDouble,BinaryOp> { typedef MyDouble ReturnType;  };
}

int main() {
    Eigen::Matrix<MyDouble, 2, 2> test;
    test << 1, 2, 3, 4;

    Eigen::Matrix<double, 2, 2> reference;
    reference << 1, 2, 3, 4;

    MyDouble a = 3;
    a += 2;
    a = 2 + a;
    a = a + 2;
    a -= 2;
    a -= MyDouble(3);

    a = a / a;

    std::complex<MyDouble> complexTest(3,4);
    complexTest *= 2;

    Eigen::EigenSolver<Eigen::Matrix<MyDouble, 2, 2>> solver(test);
    Eigen::EigenSolver<Eigen::Matrix<double, 2, 2>> refSolver(reference);
    std::cout << "MyDouble:" << std::endl;
    std::cout << test.trace() << std::endl;
    std::cout << solver.eigenvalues() << std::endl;
    std::cout << "\nRefernce:" << std::endl;
    std::cout << reference.trace() << std::endl;
    std::cout << refSolver.eigenvalues() << std::endl;
}