tgmrf_cpp: User-defined GMRF latent block, compiled C++ backend

View source: R/tgmrf_cpp.R

tgmrf_cppR Documentation

User-defined GMRF latent block, compiled C++ backend

Description

tgmrf_cpp() is the compiled-C++ analogue of tgmrf(). Where tgmrf() takes R closures Q(theta) / prior(theta), tgmrf_cpp() takes a user-written .cpp file that defines the same kernels as templated C++ (so the same source compiles against every AD type tulpa uses). The returned object has the same S3 class as tgmrf() – c("tgmrf", "tulpa_latent_block") – so every downstream consumer (formula parser, inference layers, S3 methods) treats the two paths identically. Only the dispatch on Q(theta) differs: registry-stored function pointer (tgmrf_cpp()) vs Rcpp::Function callback (tgmrf()).

The user .cpp file must include ⁠<tulpa/tgmrf.h>⁠ and call the TULPA_REGISTER_TGMRF(id, Q_fn, mu_fn, log_prior_fn) macro once. See inst/examples/tgmrf_periodic_ar1.cpp for a worked example.

Usage

tgmrf_cpp(
  cpp_file,
  id,
  init,
  mu = NULL,
  graph = NULL,
  bounds = NULL,
  obs_idx = NULL,
  name = NULL,
  cache_dir = tulpa_cache_dir(),
  rebuild = FALSE
)

Arguments

cpp_file

Absolute path to the user's .cpp file. The file is compiled via Rcpp::sourceCpp() with caching keyed on digest::sha256(file_contents) + TULPA_ABI_VERSION so repeated calls with an unchanged source skip the rebuild.

id

Character: the stable id used as the registry key. Must match the first argument of TULPA_REGISTER_TGMRF in the user's .cpp.

init, mu, graph, bounds, obs_idx, name

Same arguments as tgmrf(). init is required and supplies the canonical theta names. mu is currently ignored on the C++ path – the mu kernel registered by TULPA_REGISTER_TGMRF is the source of truth; pass the argument here only to keep call sites symmetric with tgmrf().

cache_dir

Directory for Rcpp's sourceCpp cache. Defaults to a per-user location under tools::R_user_dir("tulpa", "cache").

rebuild

Force a recompile even if the cached DLL is up to date. Default FALSE.

Value

An object of class c("tgmrf", "tulpa_latent_block") with the same fields as tgmrf() plus backend = "cpp" and cpp_id = id. The Q / prior fields are R wrapper closures around the registered C++ kernels, so callers (e.g. NUTS-over-theta) that hold the object can still call block$Q(theta) directly.

See Also

tgmrf() for the R-closure path; latent() for the formula slot that consumes a tgmrf block.

Examples


# Compile the periodic AR(1) block shipped with the package (80 nodes,
# theta = (log sigma, atanh rho)) into a temporary cache, then evaluate
# its registered precision kernel at the initial theta.
cpp_file <- system.file("examples", "tgmrf_periodic_ar1.cpp",
                        package = "tulpa")
blk <- tgmrf_cpp(cpp_file, id = "tgmrf_periodic_ar1",
                 init = c(log_sigma = 0, atanh_rho = atanh(0.5)),
                 name = "periodic_ar1",
                 cache_dir = file.path(tempdir(), "tulpa-cache"))
blk$n_latent
Q <- blk$Q(c(0, atanh(0.5)))
dim(Q)
Q[1:3, 1:3]


tulpa documentation built on Oct. 19, 2026, 5:09 p.m.