glmbayesCore

GitHub release (latest by date) License: GPL-2 GitHub Workflow Status

glmbayesCore is the compiled sampling engine that powers the glmbayes ecosystem. It holds the C++/OpenCL envelope samplers, the family-function infrastructure, and the R-level prior and simulation interfaces that downstream packages depend on. End users should install glmbayes rather than this package directly.

The relationship to the broader ecosystem parallels how StanHeaders / rstan serve as the compiled backbone for rstanarm: glmbayesCore is the infrastructure layer; glmbayes and the in-development lmebayes are the user-facing packages built on top of it.

Current staging note. This tree currently ships the iid GLM/LM envelope engine used by glmbayes. Mixed-model (LMM/GLMM / two-block) engines are still part of the long-term glmbayesCore API and are under active development in the temporary lmebayesCore fork (consumed by lmebayes). Think of lmebayesCore as a development holding package: features return here gradually once the iid backend is stable (CRAN / glmbayes re-import path).


Package Ecosystem

Target architecture (after mixed-model reintegration):

                ┌─────────────────────────────────────────┐
                │           End-user packages             │
                │   glmbayes  ·  lmebayes  ·  (others)    │
                └──────────────────┬──────────────────────┘
                                   │ Imports / LinkingTo
                ┌──────────────────▼──────────────────────┐
                │              glmbayesCore               │
                │  iid GLM/LM · LMM/GLMM · OpenCL         │
                │  pfamily · simfunctions · rglmb/rlmb    │
                └──────────────────┬──────────────────────┘
                                   │ Imports
                ┌──────────────────▼──────────────────────┐
                │   opencltools  ·  nmathopencl            │
                │   Rcpp · RcppArmadillo · RcppParallel   │
                └─────────────────────────────────────────┘

Temporary staging (today): glmbayesglmbayesCore (iid); lmebayeslmebayesCore (full fork including mixed-model stack). The fork collapses back into glmbayesCore as features are merged.

glmbayes adds the formula interface (glmb(), lmb()), MCMC diagnostics, and the full suite of S3 methods that mirror base-R’s lm() / glm().

lmebayes (in development) extends the engine to linear / generalized linear mixed-effects models (lmerb(), glmerb()).


What Is Inside glmbayesCore

C++ sampling engine (src/)

The core is organized under the glmbayes:: namespace:

Sub-namespace Key files Role
glmbayes::fam famfuncs.h, famfuncs_*.cpp Negative log-posterior (f2) and gradient (f3) for gaussian, poisson, binomial, Gamma
glmbayes::env EnvelopeBuild*.cpp, EnvelopeEval.cpp, EnvelopeSort.cpp, EnvelopeSize.cpp, Set_Grid.cpp, Set_LogP.cpp Piecewise-exponential envelope construction (Nygren & Nygren, 2006)
glmbayes::sim rNormalGLM.cpp, rIndepNormalGammaReg.cpp, rNormalGammaReg.cpp, rNormalReg.cpp, rGammaGamma.cpp, rGammaGaussian.cpp Posterior samplers
glmbayes::rng rng_utils.cpp Thread-safe RNG wrappers for parallel sampling
glmbayes::progress progress_utils.cpp Optional progress bar support

Export wrappers in export_wrappers.cpp and kernel_wrappers.cpp expose selected entry points to R via Rcpp.

OpenCL kernels (inst/cl/)

For systems with an OpenCL-capable device, envelope construction can be offloaded to the GPU. The inst/cl/ tree contains family/link f2/f3 kernels, an OpenCL port of R Mathlib probability functions, and shim headers. Kernel loading for exploration uses opencltools; runtime GPU assembly uses kernel_loader.cpp and kernel_runners.cpp.

R-level infrastructure (R/)

File Role
pfamily.R Prior-family constructors (dNormal, dNormal_Gamma, dIndependent_Normal_Gamma, dGamma, dBeta) and the pfamily() generic
prior.R Prior_Setup(), Prior_Check(), and helper utilities for default hyperparameters
simfunction.R Low-level simulation functions (rNormal_reg, rNormalGamma_reg, rindepNormalGamma_reg, rGamma_reg, …) and the simfunction() introspection generic
simulationpipeline.R glmbfamfunc(), envelope R exports, standardized samplers
rglmb.R / rlmb.R Matrix-input samplers — the primary R-level interface for glmbayes
envelopeorchestrator.R R orchestration of multi-step envelope building and optional GPU dispatch
compute_gaussian_prior.R Gaussian-specific prior calibration utilities

Architecture: How pfamilies Route to Simulation Functions

A pfamily object is a self-contained prior specification. Every constructor bundles the hyperparameters into a prior_list and embeds a simfun function pointer. When rglmb() draws samples, it calls pfamily$simfun(y, x, prior_list, family, ...) — there is no internal switch on prior type.

rglmb(y, x, pfamily = dNormal(...), family = poisson())
          │
          └─► pfamily$simfun  ──►  rNormal_reg()
                                       │
                              family == gaussian?
                              ├── Yes ──► conjugate multivariate normal draw
                              └── No  ──► envelope sampling (Nygren & Nygren, 2006)
                                              │
                                              └──► rNormalGLM (C++)
pfamily constructor Embedded simfun Posterior path
dNormal() rNormal_reg() Conjugate MVN draw (Gaussian); subgradient envelope sampling (other families)
dNormal_Gamma() rNormalGamma_reg() Conjugate Normal-Gamma draw (Gaussian only)
dIndependent_Normal_Gamma() rindepNormalGamma_reg() Joint coefficient + dispersion envelope (Gaussian; non-conjugate)
dGamma(Inv_Dispersion = TRUE) rGamma_reg() Gamma prior on inverse dispersion
dGamma(Inv_Dispersion = FALSE) rGamma_Conjugate_reg() Conjugate Gamma–Poisson or Gamma–Gamma (intercept-only, identity link)
dBeta() rBeta_reg() Conjugate Beta–Binomial (intercept-only, identity link)

Prior_Setup() fits an auxiliary GLM and returns calibrated hyperparameters on the same scale as the design matrix.


Architecture: How Simulation Functions Route to C++ Samplers

rNormal_reg()

rNormal_reg(y, x, prior_list, family, ...)
       │
  family$family == "gaussian"?
  ├── Yes ──► direct MVN draw via backsolve / Cholesky
  └── No  ──► EnvelopeOrchestrator (R)
                   ├── EnvelopeBuild (C++)
                   └── rNormalGLM (C++)   [accept-reject; optional OpenCL envelope]

rindepNormalGamma_reg()

rindepNormalGamma_reg(y, x, prior_list, ...)
       │
       └──► rIndepNormalGammaReg (C++)
                   ├── EnvelopeBuild_Ind_Normal_Gamma per dispersion grid point
                   └── joint accept-reject over (beta, dispersion)

rGamma_reg()

rGamma_reg(y, x, prior_list, family, ...)
       │
  family$family == "gaussian"?
  ├── Yes ──► rGammaGaussian (C++)
  └── No  ──► rGammaGamma (C++)

Architecture: How rglmb() Orchestrates a Draw

rglmb() validates the family × pfamily combination and delegates sampling to the simfun embedded in the pfamily object. In glmbayes, glmb() and lmb() wrap rglmb() / rlmb() with formula parsing.

rglmb(y, x, family = poisson(), pfamily = dNormal(mu, Sigma), n = 1000)
  │
  ├─ 1. Resolve family
  ├─ 2. Unpack pfamily (okfamilies, plinks, prior_list, simfun)
  ├─ 3. Validate combination
  ├─ 4. outlist ← simfun(...)
  └─ 5. Post-process → class c("rglmb", "glmb", "glm", "lm")

Adding a new prior family requires a new pfamily constructor and simulation function — not changes to rglmb() itself.


Function overview

Symbols below are exported from glmbayesCore today (iid path). End users typically load glmbayes (or lmebayes for mixed models). Mixed-model exports temporarily ship from lmebayesCore and will return here.

Shared with glmbayes (iid GLM / LM)

Retain as glmbayes re-exports

Function Role
Prior_Setup(), Prior_Check() Default prior calibration and prior predictive checks
pfamily(), dNormal(), dNormal_Gamma(), dIndependent_Normal_Gamma(), dGamma(), dBeta() Prior-family constructors
multi_prior_setup(), multi_rlmb() Multi-response Gaussian prior setup / LM sampler
rglmb(), rlmb() Matrix-level Bayesian GLM / LM samplers
diagnose_glmbayes() OpenCL / GPU diagnostic report

Phase out of glmbayes (stay in glmbayesCore)

Function Role
compute_gaussian_prior() Internal Gaussian calibration used inside Prior_Setup()
simfunction(), glmbfamfunc() Simulation registry and GLM family pipeline helpers
rNormal_reg(), rNormalGamma_reg(), rindepNormalGamma_reg(), rGamma_reg(), rBeta_reg(), … Low-level simfunction samplers
rNormalGLM_std(), rIndepNormalGammaReg_std(), glmb.wfit(), glmb_Standardize_Model() Standardized envelope path and fitter hooks
EnvelopeBuild(), EnvelopeOrchestrator(), EnvelopeSize(), … Accept–reject envelope machinery
pnorm_ct(), rnorm_ct(), pinvgamma_ct(), rgamma_ct(), … Truncated-distribution C++ callbacks

Planned mixed-model API (temporary lmebayesCore; returns here)

These are part of the long-term glmbayesCore surface for lmebayes. They are not exported from this tree today.

Area Examples
Setup model_setup(), Prior_Setup_lmebayes(), pfamily_list()
Matrix drivers rlmerb(), rglmerb()
Two-block / sweep rGLMM_reg*, rLMM_reg*, rGLMM_sweep(), two_block_*, plot_sweep_history_diag()
Block helpers build_mu_all(), ICM helpers, block_rNormalReg() / block_rNormalGLM()

Typical lmebayes workflow (via lmebayesCore for now): model_setup()Prior_Setup_lmebayes()pfamily_list(ps)lmerb() / glmerb().


Developer Interface Levels

Level 1 — C++ (via LinkingTo)

#include "glmbayesCore/famfuncs.h"
#include "glmbayesCore/Envelopefuncs.h"
#include "glmbayesCore/simfuncs.h"
#include "glmbayesCore/R_interface.h"

Level 2 — R simulation functions

library(glmbayesCore)
fit <- rindepNormalGamma_reg(
  y = y, x = X, n = 2000,
  prior_list = dIndependent_Normal_Gamma(mu, Sigma, shape, rate)$prior_list,
  family = gaussian()
)

Level 3 — rglmb() / rlmb() with pfamily objects

ps  <- Prior_Setup(y, X, family = poisson())
fit <- rglmb(y = y, x = X, n = 1000,
             pfamily = dNormal(mu = ps$mu, Sigma = ps$Sigma),
             family  = poisson())

Installation

GitHub / R-Universe (recommended for developers):

install.packages("glmbayesCore",
                 repos = c("https://cloud.r-project.org",
                           "https://knygren.r-universe.dev"))

From source (required for OpenCL GPU support):

install.packages("glmbayesCore", type = "source",
                 repos = "https://knygren.r-universe.dev")

See Chapter 16 — Large models: GPU acceleration using OpenCL for system-level setup instructions.

Dependencies that must be installed first:

install.packages(c("Rcpp", "RcppArmadillo", "RcppParallel", "MASS", "Rdpack"))
install.packages(c("opencltools", "nmathopencl"),
                 repos = "https://knygren.r-universe.dev")

Extending glmbayesCore

Adding a new pfamily

See inst/ADDING_PFAMILY.md. In summary:

  1. Write a constructor in pfamily.R that builds prior_list and sets simfun.
  2. Implement or reuse a simulation function in simfunction.R.
  3. If a new C++ sampler is needed, add it under src/, register via Rcpp::compileAttributes(), and expose it through export_wrappers.cpp.
  4. For GPU support, add the corresponding f2/f3 OpenCL kernel under inst/cl/src/ and register it in kernel_loader.cpp.

Block Gibbs / mixed-model engines

The orchestrator pattern is intentionally generic: validate a model specification, unpack a routing object, call the embedded simfun, post-process. Mixed-effects drivers in lmebayes (lmerb(), glmerb()) build on two-block Gibbs engines that will return to this package. While those engines are staged in lmebayesCore, architecture notes (ergodicity, rGLMM_sweep / Block1–Block2 call chains, C++ migration plans) live there and will move back with the code.


Key References

A complete bibliography is in inst/REFERENCES.bib.


Future plans


License

GPL-2. See the LICENSE file and inst/COPYRIGHTS for attribution of incorporated R Mathlib sources.