Registered Member
|
Hello
Thank you for your convinient library. There're Matrix types which consist of complex number in Eigen2 such as MatrixXcf, MatrixXcd. I defined complex matrix of long double type: typedef Matrix<complex<long double>, Eigen::Dynamic, Eigen::Dynamic> MatrixXcld; When I use adjoint or conjugate function, it occurs error: How do I solve it? Thank you. |
Moderator
|
this is because complex<long double> is not natively supported.
To support it you have to specialize a couple of math functions and the NumTraits<> class. Have a look at the files Eigen/src/Core/MathFunctions.h and NumTraits.h, copy/paste the blocks for complex<double> and adapt them for your needs. Note that you have to do that in the Eigen namespace. You can also have a look at this page: http://eigen.tuxfamily.org/dox/Customiz ... ScalarType |
Registered Member
|
Thank you for your reply.
I wrote the definitions for complex<long double> as in the following. But I need put it in "MathFunctions.h" (getting rid of namespace Eigen). Or It occurs error when I define it in the top of my program. I don't understand why. I'd like to put it in the top of my program. Please tell me the solution. I needn't write NumTraits<>, because there's template NumTraits class for general "typename _Real" in "NumTraits.h". namespace Eigen { /*************************** *** complex<long double> *** ****************************/ template<> inline long double precision<std::complex<long double> >() { return precision<long double>(); } template<> inline long double machine_epsilon<std::complex<long double> >() { return machine_epsilon<long double>(); } inline long double ei_real(const std::complex<long double>& x) { return std::real(x); } inline long double ei_imag(const std::complex<long double>& x) { return std::imag(x); } inline std::complex<long double> ei_conj(const std::complex<long double>& x) { return std::conj(x); } inline long double ei_abs(const std::complex<long double>& x) { return std::abs(x); } inline long double ei_abs2(const std::complex<long double>& x) { return std::norm(x); } inline std::complex<long double> ei_exp(std::complex<long double> x) { return std::exp(x); } inline std::complex<long double> ei_sin(std::complex<long double> x) { return std::sin(x); } inline std::complex<long double> ei_cos(std::complex<long double> x) { return std::cos(x); } inline std::complex<long double> ei_atan2(std::complex<long double>, std::complex<long double>) { ei_assert(false); return 0; } template<> inline std::complex<long double> ei_random() { return std::complex<long double>(ei_random<long double>(), ei_random<long double>()); } inline bool ei_isMuchSmallerThan(const std::complex<long double>& a, const std::complex<long double>& b, long double prec = precision<long double>()) { return ei_abs2(a) <= ei_abs2(b) * prec * prec; } inline bool ei_isMuchSmallerThan(const std::complex<long double>& a, long double b, long double prec = precision<long double>()) { return ei_abs2(a) <= ei_abs2(b) * prec * prec; } inline bool ei_isApprox(const std::complex<long double>& a, const std::complex<long double>& b, long double prec = precision<long double>()) { return ei_isApprox(ei_real(a), ei_real(b), prec) && ei_isApprox(ei_imag(a), ei_imag(b), prec); } // ei_isApproxOrLessThan wouldn't make sense for complex numbers } // end of namespace Eigen |
Moderator
|
here if I #include <Eigen/Core> and next copy/paste your piece of code, it works just fine. Are you sure you #included Eigen/Core *before* specializing for complex<long double> ?
|
Registered Member
|
Thank you for your reply again.
I included Eigen/Core before definitions for complex<long double> as the following: #include <stdio.h> #include <stdlib.h> #include <iostream> #include <iomanip> #include <cmath> #include <complex> #include <Eigen/Array> #include <Eigen/Core> #include <Eigen/LU> // import most common Eigen types USING_PART_OF_NAMESPACE_EIGEN using namespace std; namespace Eigen { /* template<> struct NumTraits<std::complex<long double> > { typedef long double Real; typedef std::complex<long double> FloatingPoint; enum { IsComplex = 1, HasFloatingPoint = NumTraits<Real>::HasFloatingPoint, ReadCost = 2, AddCost = 2 * NumTraits<Real>::AddCost, MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost }; }; */ /**************************** /*** complex<long double> *** /****************************/ template<> inline long double precision<std::complex<long double> >() { return precision<long double>(); } template<> inline long double machine_epsilon<std::complex<long double> >() { return machine_epsilon<long double>(); } inline long double ei_real(const std::complex<long double>& x) { return std::real(x); } inline long double ei_imag(const std::complex<long double>& x) { return std::imag(x); } inline std::complex<long double> ei_conj(const std::complex<long double>& x) { return std::conj(x); } inline long double ei_abs(const std::complex<long double>& x) { return std::abs(x); } inline long double ei_abs2(const std::complex<long double>& x) { return std::norm(x); } inline std::complex<long double> ei_exp(std::complex<long double> x) { return std::exp(x); } inline std::complex<long double> ei_sin(std::complex<long double> x) { return std::sin(x); } inline std::complex<long double> ei_cos(std::complex<long double> x) { return std::cos(x); } inline std::complex<long double> ei_atan2(std::complex<long double>, std::complex<long double>) { ei_assert(false); return 0; } template<> inline std::complex<long double> ei_random() { return std::complex<long double>(ei_random<long double>(), ei_random<long double>()); } inline bool ei_isMuchSmallerThan(const std::complex<long double>& a, const std::complex<long double>& b, long double prec = precision<long double>()) { return ei_abs2(a) <= ei_abs2(b) * prec * prec; } inline bool ei_isMuchSmallerThan(const std::complex<long double>& a, long double b, long double prec = precision<long double>()) { return ei_abs2(a) <= ei_abs2(b) * prec * prec; } inline bool ei_isApprox(const std::complex<long double>& a, const std::complex<long double>& b, long double prec = precision<long double>()) { return ei_isApprox(ei_real(a), ei_real(b), prec) && ei_isApprox(ei_imag(a), ei_imag(b), prec); } // ei_isApproxOrLessThan wouldn't make sense for complex numbers } typedef Matrix<complex<long double>, Eigen::Dynamic, Eigen::Dynamic> MatrixXcld; typedef Matrix<complex<long double>, Eigen::Dynamic, 1> VectorXcld; int main(void) { MatrixXcld U(2,2); U(0,0) = complex<long double>(1,0); U(0,1) = complex<long double>(0,-1); U(1,0) = complex<long double>(0,1); U(1,1) = complex<long double>(1,0); cout << U.conjugate(); // it occurs error! } I got the following error. Compiler can't find Eigen::ei_conj(const std::complex<long double>&), although I defined it in Eigen namespace. Could you give me the reason? test6.cpp:79: instantiated from here ..../eigen/Eigen/src/Core/Functors.h:204: error: no matching function for call to ‘ei_conj(const std::complex<long double>&)’ ..../eigen/Eigen/src/Core/MathFunctions.h:56: note: candidates are: int Eigen::ei_conj(int) ..../eigen/Eigen/src/Core/MathFunctions.h:97: note: float Eigen::ei_conj(float) ..../eigen/Eigen/src/Core/MathFunctions.h:145: note: double Eigen::ei_conj(double) ..../eigen/Eigen/src/Core/MathFunctions.h:192: note: std::complex<float> Eigen::ei_conj(const std::complex<float>&) ..../eigen/Eigen/src/Core/MathFunctions.h:227: note: std::complex<double> Eigen::ei_conj(const std::complex<double>&) ..../eigen/Eigen/src/Core/MathFunctions.h:263: note: long double Eigen::ei_conj(long double) |
Moderator
|
sorry, because of some weird name lookup rules of the C++ standard, you have to define the overloads in the same namespace as the type (so here std). The template function specialization still have to be defined in the Eigen namespace:
|
Registered Member
|
Registered users: abc72656, Bing [Bot], daret, Google [Bot], Sogou [Bot], Yahoo [Bot]