This documents describes all language elements that can be compiled to Armadillo flavored C++ code.
armacmp
always compiles functions. Every function needs
to have a return
statement with an optional type
argument.
You can define your inputs using the standard function syntax. By
default paramters are of type type_matrix
. But they can
have other types such as:
type_colvec
- a column vectortype_rowvec
- a row vectortype_scalar_integer
- a single int valuetype_scalar_numeric
- a single double valuetype_scalar_bool
- a single boolean valueAll functions need to return a value using the return
function. The return
function can have an optional return
type argument with return(value, type = type_rowvec())
The package supports only a very limited number of types. For scalar
values these are bool
, int
and
double
. All matrices and vectors are of type
arma::mat/colvec/rowvec
for double matrices,
arma::imat/icolvec/irowvec
for integer matrices and
arma::umat/ucolvec/urowvec
for unsigned integer matrices
(used for indicies).
All operations are performed either on Armadillo types or on scalar types and not on R’s data structures.
The package tries to figure out the correct types of variables and
functions, but you can give type hints. If the package cannot figure out
the type, the C++ type auto
is used which can have suboptimal performance
when used together with Armadillo operations.
%*%
- matrix multiplication translates to the
*
operator on both arma::mat
types and regular
variables/expressions.*
- elementwise multiplication gets translated
to %
for arma::mat
types and to *
otherwise.The following operators are translated to their C++ counter-part.
/
+
-
!
<
>
>=
<=
x ^ y
exp
abs
log
sum
min
max
sqrt
cos
acos
cosh
acosh
sin
asin
sinh
asinh
tan
atan
tanh
atanh
t
chol
diag
QR
svd
solve
ncol
nrow
crossprod
tcrossprod
det
[i, j]
[i, ]
[, j]
[i]
length
cumsum
sort
unique
cumsum
cumprod
pnorm
seq_len
returns a arma::colvec
(note that
is corresponds to a sequence of numerics)a:b
returns an arma::colvec
from
a
to b
(note that is corresponds to a sequence
of numerics)rep.int
returns a arma::colvec
(note that
is corresponds to a sequence of numerics)Currently if/else, for and while loops are supported.
if_clause <- compile(function(X) {
# infers that test needs to be bool (auto)
test <- sum(log(X)) < 10
X_new <- X
if (test) {
X_new <- (t(X) %*% X) + 10
} else if (sum(X) < 10) {
X_new <- t(X) %*% X
} else {
X_new <- (t(X) %*% X) + 10
}
return(X_new)
})
Just make sure all return statements return the same type.
Also if/else
cannot be used as an expression:
For loops are supported:
# currently only seq_len is available to create sequences of ints
x <- seq_len(n)
for (i in x) {
...
}
Example:
You can also define functions within your functions (lambdas).
fun <- compile(function(X) {
square <- function(y) {
return(y^2)
}
Y <- square(X)
return(Y)
})
fun(matrix(1:10))
#> [,1]
#> [1,] 1
#> [2,] 4
#> [3,] 9
#> [4,] 16
#> [5,] 25
#> [6,] 36
#> [7,] 49
#> [8,] 64
#> [9,] 81
#> [10,] 100
Using lambdas it is possible to define recursive functions as well.
is_even <- compile(function(x = type_scalar_numeric()) {
is_even_internal <- function(y = type_scalar_numeric()) {
if (y == 0) return(TRUE)
if (y < 0) return(FALSE)
return(is_even_internal(y - 2), type = type_scalar_logical())
}
return(is_even_internal(x))
})
is_even(5)
#> [1] FALSE
is_even(4)
#> [1] TRUE