Consider the following C++ code
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export(rng = false)]]
void possible_bug(arma::vec &x, arma::mat const &sig_chol){
if(x.n_elem != sig_chol.n_rows * sig_chol.n_cols)
throw std::runtime_error("boh");
arma::mat x_mat(x.begin(), sig_chol.n_rows, sig_chol.n_rows, false);
x_mat = arma::solve
(arma::trimatu(sig_chol),
arma::solve(arma::trimatu(sig_chol), x_mat).t());
}
I am using Rcpp::sourceCpp()
as this is the easiest way for me to set the example up. With a 3D matrix I get
set.seed(1)
n <- 3L
x <- rnorm(n * n)
sig_chol <- rWishart(1, n, diag(n)) |> drop() |> chol()
x_cp <- x + 0.
possible_bug(x = x_cp, sig_chol)
all.equal(x_cp, x)
#R> [1] "Mean relative difference: 1.000271"
all.equal(x_cp,
solve(sig_chol, t(solve(sig_chol, matrix(x, n)))) |> c())
#R> [1] TRUE
This exactly what I will expect (the input argument is changed as it is used for the memory for the result). It also works with n <- 4L
. However with a 5D matrix I get
set.seed(1)
n <- 5L
x <- rnorm(n * n)
sig_chol <- rWishart(1, n, diag(n)) |> drop() |> chol()
x_cp <- x + 0.
possible_bug(x = x_cp, sig_chol)
all.equal(x_cp, x)
#R> [1] TRUE
all.equal(x_cp,
solve(sig_chol, t(solve(sig_chol, matrix(x, n)))) |> c())
#R> [1] "Mean relative difference: 2.041895"
This is unlike what I would expect (the input argument is not changed).
Are my expectations wrong?
The above is with RcppArmadillo version 0.11.1.1.0. The reason I am posting this is because of a unit test which failed after I upgraded to the new version of RcppArmadillo. I get a consistent and expected behavior with version 0.10.8.1.0.
The difference persists if I remove the arma::trimatu()
calls.
This is an intended change in version 11.1.1. See https://gitlab.com/conradsnicta/armadillo-code/-/issues/210#note_974299524
The way to go is to set strict
to true
in the constructor of arma::mat
and other objects.