Skip to content

Tips for avoiding errors in nimbleFunction programming and compilation (DSL)

Christopher Paciorek edited this page Mar 9, 2019 · 12 revisions

Chapters 11-15 of the NIMBLE manual describe how to program in NIMBLE: how to write nimbleFunctions using the NIMBLE language (NIMBLE DSL).

Writing nimbleFunction run code is similar to programming in R, but because nimbleFunctions are compiled to C++, there are some limitations on what can be done in run code.

Here we document some of the syntax that does NOT work in nimbleFunction run code and work-arounds in each case.

Syntax that doesn't work Alternative syntax to accomplish this
Use of distribution parameterizations other than those in Section 11.2.4 of the manual Manually reparameterize to one of the parameterizations in Section 11.2.4
Reverse indexing such as 2:1 Manually write a loop such as for(i in 1:L) { index[i] <- L+1-i }
is.na() and is.nan() are not vectorized Write a for loop
is.na() does not work with logical or integer type NA values passed from R Use as.numeric in R to convert to numeric type
model[[nodes]] and model[[nodes[i]]] do not work when nodes indicates more than one nodes or variables Use values(model, nodes) or values(model, nodes[i])
node <- nodes[i]; model[[node]] does not work Use values(model, nodes) or values(model, nodes[i])
node <- nodes[i]; values(model, node) does not work Avoid working with temporary variables involving node names; instead establish the node variables in setup code
model$values(nodes) does not work Use values(model, nodes)
values(model, nodes)[i] <<- foo does not work Use a temporary variable, e.g., tmp <- values(model, nodes); tmp[i] <- foo; values(model, nodes) <<- tmp
values(model,node) <<- some_scalar_value does not work because values() expects a vector Use values(model, node) <- c(some_scalar_value)
Changing the type of a variable within a run function, e.g., a <- 3; a <- numeric(5) Use distinct variable names
Indexing (e.g., x[1]) into a length-one vector defined using numeric(1), integer(1), or logical(1) Define a length-two vector and only use the first element: x <- numeric(2); x[1]

Some additional details to be aware of:

  • values(model, node) and values(model, nodes[i]) returns a vector, not a scalar, even when node is a scalar node
  • matrix operations such as A %*% b returns a one-column matrix when b is a vector
  • nimNumeric(1) ends up be treated as a scalar in the generated C++ so if you need it as a vector, use nimNumeric(2). You can just not use the 2nd element.
Clone this wiki locally