简体   繁体   中英

C++ armadillo sparse matrix type conversion

I want to add two sparse armadillo matrices of arbitrary (different) type with operator+ , eg

SpMat<double> M1(2,2);
SpMat<cx_double> M2(2,2);

// ..fill both matrices

cout<<M1 + M2<<endl;

Upon compiling, the compiler complains that operator+ is not defined for those types.

When doing the same with DENSE matrices, armadillo automatically promotes the double matrix to a complex one, performs the addition and prints a complex result matrix.

There is a corresponding template for this operator in operator_plus.hpp in the include dir for adding two sparse objects, possibly of different type (at least the template definition suggests that), but it seems to only work when both operands are of the same type. The actual compiler message for the above code is the following

operator_plus.hpp:164:1: note: template<class T1, class T2> typename arma::enable_if2<((arma::is_arma_sparse_type<T1>::value && arma::is_arma_sparse_type<T2>::value) && arma::is_same_type<typename T1::elem_type, typename T2::elem_type>::value), arma::SpGlue<T1, T2, arma::spglue_plus> >::result arma::operator+(const T1&, const T2&)
operator_plus.hpp:164:1: note:   template argument deduction/substitution failed:
operator_plus.hpp:164:1: error: no type named ‘result’ in ‘struct arma::enable_if2<false, arma::SpGlue<arma::SpMat<double>, arma::SpMat<std::complex<double> >, arma::spglue_plus> >’

Any ideas? Is it possible that this feature is just not implemented yet? Thanks!

It seems the addition of two sparse matrices of different types has not been implemented yet (using current newest release 6.400.3). I reckon the below also answers this question .

Armadillo uses the SFINAE technique to exclude function templates from the possible list of overloaded candidates for operator+ (and many other functions/operators too) that don't fit, to be left with only the desired candidate upon evaluating the template parameters.

The candidate we want here is the one adding two sparse matrices. It has the following signature

template<typename T1, typename T2>
inline arma_hot
typename enable_if2
<
(is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
 SpGlue<T1,T2,spglue_plus>
>::result
operator+(const T1& x,const T2& y)

enable_if2 is a template struct defined in restrictors.hpp and works very much the same way as std::enable_if : if the first template parameter of enable_if (in the above declaration the long boolean expression) evaluates to true, enable_if has a member of the same type as the second template parameter (in this case SpGlue<T1,T2,spglue_plus> ).

That means that this candidate is only valid, if the boolean expression evaluates to true, otherwise it is also discarded from the list of possible candidates. As you can see, the boolean expression also contains the part

is_same_type<typename T1::elem_type, typename T2::elem_type>::value

which of course evaluates to false if T1 and T2 are not the same, enable_if2 thus has no member enable_if2::result and the function is removed from the candidate list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM