This forum has been archived. All content is frozen. Please use KDE Discuss instead.

complex<long double> type matrix

Tags: None
(comma "," separated)
tacchi
Registered Member
Posts
11
Karma
0

complex<long double> type matrix

Mon Feb 01, 2010 10:49 am
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.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: complex<long double> type matrix

Mon Feb 01, 2010 11:35 am
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
tacchi
Registered Member
Posts
11
Karma
0
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
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: complex<long double> type matrix

Tue Feb 02, 2010 10:43 am
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> ?
tacchi
Registered Member
Posts
11
Karma
0
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)
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
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:

Code: Select all
/****************************
/*** complex<long double> ***
/****************************/

namespace Eigen {

template<> inline long double precision<std::complex<long double> >() { return Eigen::precision<long double>(); }
template<> inline long double machine_epsilon<std::complex<long double> >() { return Eigen::machine_epsilon<long double>(); }
template<> inline std::complex<long double> ei_random()
{
return std::complex<long double>(ei_random<long double>(), ei_random<long double>());
}
}

namespace std {

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; }


inline bool ei_isMuchSmallerThan(const std::complex<long double>& a, const std::complex<long double>& b, long double prec = Eigen::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 = Eigen::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 = Eigen::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
}
tacchi
Registered Member
Posts
11
Karma
0
Thank you.
I solved that problem


Bookmarks



Who is online

Registered users: abc72656, Bing [Bot], daret, Google [Bot], Sogou [Bot], Yahoo [Bot]