---
title: "15 - Using SEXP with Armadillo data types"
output:
  litedown::html_format:
    options:
      toc: true
      number_sections: true
vignette: >
  %\VignetteIndexEntry{15 - Using SEXP with Armadillo data types}
  %\VignetteEngine{litedown::vignette}
  %\VignetteEncoding{UTF-8}
editor:
  markdown:
    wrap: sentence
bibliography: ["references.bib"]
---

`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<>)` -> `imat`
- `as_umat(integers_matrix<>)` -> `umat`
- `as_fmat(doubles_matrix<>)` -> `fmat`
- `as_Col(doubles)` -> `Col<double> / vec`
- `as_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)` -> `doubles`
- `as_integers(ivec/uvec)` -> `integers`

Or we can use the generic conversion `cpp4r::as_sexp()`:

- `vec/ivec/uvec/fvec` -> `doubles/integers`
- `mat/imat/umat/fmat` -> `doubles_matrix<> / integers_matrix<>`
- `rowvec/irowvec/urowvec/frowvec` -> `doubles_matrix<> / integers_matrix<>`

Let's use the following function in different ways:

```cpp
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:

```cpp
// 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);
  return as_doubles(ols_fit(X, Y));
}

// 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);
  return cpp4r::as_sexp(ols_fit(X, Y));
}

// 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);
  return cpp4r::as_sexp(ols_fit(X, Y));
}

// 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)));
}
```
