Using SEXP with Armadillo data types
as_sexp() allows to pass objects from Armadillo to R
while as_cpp<> allows to pass objects from R to
Armadillo. I prefer to use as_mat(),
as_doubles_matrix(), etc. to be clear about the return
types being used and avoid ambiguity (e.g., as in example 5 below).
To pass data to Armadillo we use:
as_Mat(doubles_matrix<>)->Mat<double>as_Mat(integers_matrix<>) / - as_mat()->Mat<int>as_imat(integers_matrix<>)->imatas_umat(integers_matrix<>)->umatas_fmat(doubles_matrix<>)->fmatas_Col(doubles)->Col<double> / vecas_Col(integers) / as_col()->Col<int>as_uvec(integers)->uvec
To pass data back to R we use:
as_doubles_matrix(mat/fmat)->doubles_matrix<>as_integers_matrix(imat/umat)->integers_matrix<>as_complexes_matrix(cx_mat)->complexes_matrix<>as_doubles(vec)->doublesas_integers(ivec/uvec)->integers
Or we can use the generic conversion
cpp4r::as_sexp():
vec/ivec/uvec/fvec->doubles/integersmat/imat/umat/fmat->doubles_matrix<> / integers_matrix<>rowvec/irowvec/urowvec/frowvec->doubles_matrix<> / integers_matrix<>
Let’s use the following function in different ways:
vec ols_fit(const Mat<double>& X, const Col<double>& Y) {
// QR decomposition
mat Q, R;
qr_econ(Q, R, X);
// Least Squares Problem
vec betas = solve(trimatu(R), Q.t() * Y);
return betas;
}
There are at least five ways to use this function and return the results to R:
// Example 1: vec to doubles()
[[cpp4r::register]] doubles ols_traditional_(const doubles_matrix<>& x,
const doubles& y) {
mat X = as_Mat(x);
vec Y = as_Col(y);
vec result = ols_fit(X, Y);
return as_doubles(result);
}
// Example 2: vec to doubles using as_sexp()
[[cpp4r::register]] doubles ols_simplified_(const doubles_matrix<>& x, const doubles& y) {
mat X = as_mat(x);
vec Y = as_Col(y);
return cpp4r::as_sexp(ols_fit(X, Y));
}
// Example 3: mat to doubles_matrix<> using as_sexp()
[[cpp4r::register]] doubles_matrix<> ols_simplified2_(const doubles_matrix<>& x,
const doubles& y) {
mat X = as_mat(x);
vec Y = as_Col(y);
mat result = ols_fit(X, Y);
return cpp4r::as_sexp(result);
}
// Example 4: vec to doubles using as_sexp()
[[cpp4r::register]] doubles ols_simplified3_(const doubles_matrix<>& x,
const doubles& y) {
mat X = as_mat(x);
vec Y = as_Col(y);
vec result = ols_fit(X, Y);
return cpp4r::as_sexp(result);
}
// Example 4: vec to doubles using as_sexp()
[[cpp4r::register]] doubles ols_simplified4_(const doubles_matrix<>& x,
const doubles& y) {
return cpp4r::as_sexp(ols_fit(as_mat(x), as_col(y)));
}
// Example 5: vec to doubles using as_sexp()
// returns doubles ignoring the doubles_matrix<> output
[[cpp4r::register]] doubles_matrix<> ols_simplified5_(const doubles_matrix<>& x,
const doubles& y) {
return cpp4r::as_sexp(ols_fit(as_mat(x), as_col(y)));
}