Re: [eigen] TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other) |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen <eigen@xxxxxxxxxxxxxxxxxxx>
- Subject: Re: [eigen] TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other)
- From: Gael Guennebaud <gael.guennebaud@xxxxxxxxx>
- Date: Mon, 5 Sep 2016 22:42:04 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=Hzvex6S4PCTUGl5Q1W06bjezb0tH0FA2LcWbb5zbSnU=; b=TUXNynzDOWQb9b5p+/khVtuNy6jE6Wn8OliC9HBrk9UjYsCLNX7Ra37oZIm2LnXUmu xghlyEoFvrCGMXiOSfTWCgZK64VXg6jI9qc0qUT0fdeR0jJ2zClTZW7UNDz+rbE3QPQO z1XXAwUnlcj82BBoRFM/JupLGjFA2T2oifzrLBaTxmr1XLapZrtsLQPV25e4oM9mvvPD zWJH6AvGYyOT/5KfRPIPAzbpQqu3yXpJv0OsDIu04ogwLi3X/L/R2PiGoZankGl6XlgO LGqL8o9zDVNqNt4JJlEXCfoj70SCbdHCi0QWw58PK3HbiqCT6UHHH5H5Wdtw2quMF/2P 65pw==
It seems that you also need to specialize:
template<typename T> struct ScalarBinaryOpTraits<MyType< std::complex<T> >,MyType<T> > { typedef MyType< std::complex<T> > ReturnType; };
template<typename T> struct ScalarBinaryOpTraits<MyType<T>,MyType< std::complex<T> > > { typedef MyType< std::complex<T> > ReturnType; };
then proper comparisons for reals, a few mixed real and complex operations (-, *, /), and some -=, /=, *= operators, and everything compiles fine use Eigen's head.
See attached file.
Cheers,
Gael
#include <stdlib.h>
#include <cmath>
#include <complex>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <boost/utility/enable_if.hpp> //needed for enable_if
#include <boost/type_traits/is_complex.hpp>
template<typename T>
class MyType
{
public:
typedef T value_type;
MyType( const T a, const T b ) : za(a), zb(b) {};
MyType( const MyType& a) : za(a.za), zb(a.zb) {};
MyType( const T& z) : za(z), zb(0) {};
MyType( const int z) : za(z), zb(0) {}; //needed for eigen
MyType() {};
template< typename Q = T, class = typename boost::enable_if< boost::is_complex<Q>, typename Q::value_type > >
MyType( const MyType < typename Q::value_type>& a ) {};
const T& z1() const { return za; };
T& z1() { return za; };
const T& z2() const { return zb; };
T& z2() { return zb; };
MyType& operator+=(const T a) { za += a; return *this; }
MyType& operator+=(const MyType a) { za += a.za; zb += a.zb; return *this; }
MyType& operator-=(const T a) { za -= a; return *this; }
MyType& operator-=(const MyType a) { za -= a.za; zb -= a.zb; return *this; }
MyType& operator/=(const T a) { za /= a; return *this; }
MyType& operator/=(const MyType a) { za /= a.za; zb /= a.zb; return *this; }
MyType& operator*=(const T a) { za *= a; return *this; }
MyType& operator*=(const MyType a) { za *= a.za; zb /= a.zb; return *this; }
bool operator!=( const MyType& b ) { return (z1() != b.z1() ) || (z2() != b.z2() ); }
protected:
T za, zb;
};
typedef double TpFloatBase;
typedef std::complex<TpFloatBase> TpComplex;
typedef MyType < TpFloatBase > TpRFloat;
typedef MyType < TpComplex > TpFloat;
///=====================================================
/// Eigen typedefs
///=====================================================
typedef Eigen::Matrix< TpFloat, Eigen::Dynamic, 1> TpVector;
typedef Eigen::Matrix< TpFloat, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> TpMatrix;
typedef Eigen::Array< TpFloat , Eigen::Dynamic, 1> TpArray;
template<class T> MyType<T> operator+(const T a , const MyType<T> b) { return MyType<T>( a + b.z1() , b.z2() );}
template<class T> MyType<T> operator+(const MyType<T> a , const T b) { return MyType<T>( a.z1() + b , a.z2() );}
template<class T> MyType<T> operator+(const MyType<T> a , const MyType<T> b) { return MyType<T>( a.z1() + b.z1() , a.z2() + b.z2() );}
template<class T> MyType<T> operator-(const T a , const MyType<T> b) { return MyType<T>( a - b.z1() , - b.z2() );}
template<class T> MyType<T> operator-(const MyType<T> a ,const T b) { return MyType<T>( a.z1() - b , - a.z2() );}
template<class T> MyType<T> operator-(const MyType<T> a ,const MyType<T> b) { return MyType<T>( a.z1() - b.z1() , a.z2() - b.z2() );}
template<class T> MyType<T> operator*( const T a , const MyType<T> b) { return MyType<T>( a * b.z1() , a*b.z2() ); }
template<class T> MyType<T> operator*( const MyType<T> a , const T b) { return MyType<T>( a.z1() * b , a.z2()*b ); }
template<class T> MyType<T> operator*( const MyType<T> a , const MyType<T> b) { return MyType<T>( a.z1() * b.z1() , a.z2()*b.z2() ) ; }
template<class T> MyType<T> operator/( const MyType<T> a , const MyType<T> b) { return MyType<T>( a.z1() / b.z1() , a.z2() / b.z2() ) ; }
template<class T>
MyType< std::complex<T> > operator-( const MyType< std::complex<T> >& a , const MyType<T>& b)
{
return MyType< std::complex<T> >(a.z1()-b.z1(), a.z2()-b.z2());
}
template<class T>
MyType< std::complex<T> > operator-( const MyType< T >& a , const MyType< std::complex<T> >& b)
{
return MyType< std::complex<T> >(a.z1()-b.z1(), a.z2()-b.z2());
}
template<class T>
MyType< std::complex<T> > operator*( const MyType< std::complex<T> >& a , const MyType<T>& b)
{
return MyType< std::complex<T> >(a.z1()*b.z1(), a.z2()*b.z2());
}
template<class T>
MyType< std::complex<T> > operator*( const MyType< T >& a , const MyType< std::complex<T> >& b)
{
return MyType< std::complex<T> >(a.z1()*b.z1(), a.z2()*b.z2());
}
template<class T>
MyType< std::complex<T> > operator/( const MyType< std::complex<T> >& z , const MyType< std::complex<T> > & q)
{
return MyType< std::complex<T > >( z.z1() / q.z1() , z.z2() / q.z2() );
}
template<class T>
MyType< std::complex<T> > operator/( const MyType< std::complex<T> >& z , const MyType<T>& b)
{
return z / MyType< std::complex<T > >( b.z1() , b.z2() ); ///< Could be optimized
}
template<class T>
MyType< std::complex<T> > operator/( const MyType<T>& a, const MyType< std::complex<T> >& z)
{
return MyType< std::complex<T > >( a.z1() , a.z2() ) / z ; ///< Could be optimized
}
template<class Q>
typename boost::enable_if< boost::is_complex<Q>, MyType<Q> >::type conj( const MyType< Q >& a) { return MyType<Q>( conj( a.z1() ), conj( a.z2() )); };
template<class Q>
typename boost::enable_if< boost::is_complex<Q>, MyType<typename Q::value_type> >::type real( const MyType< Q >& a) { return MyType<typename Q::value_type>( real( a.z1() ), real( a.z2() )); };
template<class Q>
typename boost::enable_if< boost::is_complex<Q>, MyType<typename Q::value_type> >::type imag( const MyType< Q >& a) { return MyType<typename Q::value_type>( imag( a.z1() ), imag( a.z2() )); };
template<class Q>
typename boost::disable_if< boost::is_complex<Q>, MyType<Q> >::type abs(const MyType<Q> a)
{
return (a.z1() == 0 ) ? MyType<Q>( (a.z1() , Q(0) )) : (a.z1() > 0 ) ? a : -a;
};
template<class Q>
typename boost::enable_if< boost::is_complex<Q>, MyType<typename Q::value_type> >::type abs( const MyType< Q >& a) { return MyType<typename Q::value_type>( abs( a.z1() ), abs( a.z2() )); };
template<class T>
bool operator==( const MyType<T>& a, const MyType<T>& b )
{
return (a.z1() == b.z1() ) && (a.z2() == b.z2() );
};
template<class T>
bool operator<( const MyType<T>& a, const MyType<T>& b)
{
return (a.z1() == b.z1()) ? (a.z2()<b.z2()) : (a.z1()<b.z1());
};
template<class T>
bool operator>( const MyType<T>& a, const MyType<T>& b)
{
return (a.z1() == b.z1()) ? (a.z2()>b.z2()) : (a.z1()>b.z1());
};
template<class T>
bool operator<=( const MyType<T>& a, const MyType<T>& b)
{
return (a.z1() == b.z1()) ? (a.z2()<=b.z2()) : (a.z1()<=b.z1());
};
template<class T>
bool operator>=( const MyType<T>& a, const MyType<T>& b)
{
return (a.z1() == b.z1()) ? (a.z2()>=b.z2()) : (a.z1()>=b.z1());
};
template<typename T>
MyType<T> operator-( const MyType<T>& x)
{
return MyType<T>(-(x.z1()), -(x.z2()));
};
template<typename T>
MyType<T> sqrt( const MyType<T>& x)
{
using std::sqrt;
return MyType<T>(sqrt(x.z1()), sqrt(x.z2()));
};
///=====================================================
/// Needed for Eigen IO
///=====================================================
namespace Eigen
{
template<typename T> struct ScalarBinaryOpTraits<MyType< std::complex<T> >,MyType<T> > { typedef MyType< std::complex<T> > ReturnType; };
template<typename T> struct ScalarBinaryOpTraits<MyType<T>,MyType< std::complex<T> > > { typedef MyType< std::complex<T> > ReturnType; };
template<> struct NumTraits<TpFloat> : NumTraits<TpComplex> // permits to get the epsilon, dummy_precision, lowest, highest functions
{
typedef TpRFloat Real;
typedef TpFloat NonInteger;
typedef TpFloat Nested;
static inline Real epsilon() { return TpRFloat( NumTraits<TpFloatBase>::epsilon() ); }
static inline Real dummy_precision() { return TpRFloat( NumTraits<TpFloatBase>::dummy_precision() ); }
};
}
int main( const int argc, const char *argv[] )
{
const int M=2;
TpMatrix H(M,M);
H << 1,2,2,4;
TpMatrix rh0 = H.adjoint(); // o.k.
TpMatrix rho1 = H * H; // o.k.
TpMatrix rho2 = H + H.adjoint(); // o.k.
TpMatrix rho3 = H * H.adjoint(); // o.k., fixed in development branch of eigen.
///-----------------------------------------------
TpRFloat r(1);
TpFloat z(2);
TpFloat q = z / r; // o.k.
TpMatrix A;
TpFloat ca;
TpRFloat a;
ca = a;
A.triangularView<Eigen::Upper>() /= a;
Eigen::SelfAdjointEigenSolver<TpMatrix> eigensolverH;
eigensolverH.compute(H);
return 0;
}