Armadillo join_cols() compile error

2.3k views Asked by At

I'm trying my hand at doing some simple convex programming with Armadillo, but I might be getting lost in the syntax (or installation).

I have the following:

int M, N; // these are initialised to > 0 values.
vec X;
vec B = ones<vec>(M); // some vector. It's not actually this, but I include this for clarity

X = join_cols<vec>(zeros<vec>(2*N),join_cols<vec>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

And it gives me the compile error:

../L1ConvexSolver.cpp:326:94: error: no matching function for call to ‘join_cols(arma::enable_if2<true, const arma::eOp<arma::eGlue<arma::eOp<arma::Col<double>, arma::eop_abs>, arma::Col<double>, arma::eglue_plus>, arma::eop_scalar_times> >::result, arma::enable_if2<true, const arma::eOp<arma::eGlue<arma::eOp<arma::Col<double>, arma::eop_abs>, arma::Col<double>, arma::eglue_minus>, arma::eop_scalar_times> >::result)’
../L1ConvexSolver.cpp:326:94: note: candidate is:
../../Libraries/armadillo-3.910.1/include/armadillo_bits/fn_join.hpp:17:1: note: template<class T1, class T2> const arma::Glue<T1, T2, arma::glue_join> arma::join_cols(const arma::Base<typename T1::elem_type, T1>&, const arma::Base<typename T1::elem_type, T2>&)

I am getting similar errors elsewhere. I'm also trying to use sp_mat (or SpMat) with inv() or solve() with no dice. In fact, nothing seems to work apart from element acces and basic arithmetic. Do I have an installation issue or is my syntax just wrong?

I'm running it all on Ubuntu 12.04.

EDIT:

Building on Rudolfs' answer, it seems that I was ignoring some of the errors that were given!

It seems that the following works:

X = join_cols<mat>(vec(zeros<vec>(2*N)),join_cols<mat>(vec((abs(B)+B)*0.5),vec((abs(B)-B)*0.5)));

But this doesn't:

X = join_cols<mat>(zeros<vec>(2*N),join_cols<mat>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

And the reason is that Armadillo does internal optimisations that can rearrange expressions in a pre-compilation step, but because of that and the fact that join_cols() did not have enough prototypes to cope with all of the glue statements (scalar mult, vector addition, etc) it was failing before Armadillo could preprocess. At least, that's my over-simplified view.

2

There are 2 answers

3
Rudolfs Bundulis On BEST ANSWER

Are you sure you can call the join on vectors? At least looking at the documentation and given a fast look at the function definition it seems that it works on mat objects, since this code compiles fine:

mat m1, m2;
mat m3 = join_cols<mat>(m1, m2);

also

vec v1, v2;
vec v3 = join_cols<mat>(v1, v2);

works. I'd suggest you try the second example to see if the results are correct, maybe the library is not sure how to interpret a vector in a column join operation. But since vec is just a subclass of mat (logically a matrix with one row) i'd guess it works.

0
mtall On

You don't need to have the template specification when using join_cols(). For example, you don't need to do join_cols< vec >(X). Simply do join_cols(X) without the < vec >. Similar for abs< vec >(X): use abs(X) instead.

The reason the ones< vec > and zeros< vec > functions need the template specification is to tell the compiler what type of object is being generated, as it can't work it out simply from the input argument (which is just an integer specifying the length). In contrast, join_cols() and abs() already know the input type (ie. vectors and matrices).

In summary, instead of

X = join_cols<vec>(zeros<vec>(2*N),join_cols<vec>((abs<vec>(B)+B)*0.5,(abs<vec>(B)-B)*0.5));

do this:

X = join_cols(zeros<vec>(2*N),join_cols((abs(B)+B)*0.5,(abs(B)-B)*0.5));