[Rcpp-devel] Working with indicators in Armadillo

Conrad S conradsand.arma at gmail.com
Tue Feb 26 04:54:17 CET 2013


On Sun, Feb 24, 2013 at 6:33 AM, Simon Zehnder <szehnder at uni-bonn.de> wrote:
>   1 arma::mat repS = arma::repmat(S, 1, K);
>   2 arma::mat compM = arma::ones(S.n_rows, K);
>   3 arma::rowvec par_post(K);
>   4
>   5 for(unsigned int k = 0; k < K; ++k) {
>   6               compM.col(k) = compM.col(k) * (k + 1);
>   7 }
>   8
>   9 arma::umat ind = (repS == compM);
> 10 par_post = sum(ind);

There is a performance issue on line 6.  I'll get back to this.

First, the source of the compilation error is a type mismatch.  The
result of sum(ind) is a "umat" (with one row) while par_post has the
type "rowvec".

"umat" is a shorthand (typedef) for Mat<uword>, where uword is an
unsigned integer type.
"rowvec" is a typedef for Row<double>, which in effect is Mat<double>
(albeit with one row).

So the underlying element type for the two Mat objects is different:
one is uword, and the other is double. As such, you have a type
mismatch.

You can use the conv_to() function to convert the result of sum() to
be compatible with rowvec, eg.
par_post = conv_to<rowvec>::from(sum(ind)).
Alternatively, you can multiply sum(ind) by 1.0 which should then
convert it to a compatible time.

About the performance issue on line 6.  Your code will run much
quicker if you change it from:
   compM.col(k) = compM.col(k) * (k + 1);
to:
   compM.col(k) *= (k + 1);

In the former, Armadillo aliasing detector will indicate that one of
the inputs is an alias of the output, and that one of the inputs is a
submatrix.  When using submatrices, detecting safe/non-destructive
aliasing is hard to do (difficult and tedious to code) so Armadillo
will currently make a copy of compM.col(k) before assigning the result
to compM.col(k).  You can avoid this by using the *= operator.


More information about the Rcpp-devel mailing list