sanic provides direct and iterative solvers for linear systems in R, powered by the Eigen C++ library. It supports dense and sparse systems, reusable LU factorizations, eigenvalue and singular value decompositions, and Arnoldi and Lanczos projections.
Install the released version from CRAN or the development version from GitHub:
install.packages("sanic")
# remotes::install_github("nk027/sanic")
install.packages("sanic", repos = c('https://nk027.r-universe.dev', 'https://cloud.r-project.org'))
Use solve2() to select a direct solver automatically: QR for rectangular
input, a Cholesky attempt for symmetric input (with LU fallback), and LU
otherwise.
library(sanic)
A <- matrix(c(4, 1, 1, 3), nrow = 2)
b1 <- c(1, 2)
b2 <- c(3, 4)
x <- solve2(A, b1)
x
# [,1]
# [1,] 0.09090909
# [2,] 0.63636364
For repeated LU solves with the same matrix, compute the factorization once:
f <- factorize_lu(A)
x1 <- solve(f, b1)
x2 <- solve(f, b2)
cbind(x1, x2)
Factors are session-local and must be recreated from the original matrix after saving/loading or when moving to another R process.
Call solve_lu(), solve_qr(), or solve_chol() directly to choose a method
explicitly. For iterative solves, use solve_cg() and select the method explicitly. The default is BiCGSTAB; for classic conjugate gradient use:
x_cg <- solve_cg(sparsify(A), b1, type = "CG", tol = 1e-10)
max(abs(A %*% x_cg - b1))
Classic CG requires a symmetric positive definite matrix. Iterative methods offer preconditioners and convergence controls.
Use eigen2() for eigenvalue decompositions and svd2() for singular value
decompositions of dense matrices. For large sparse matrices, arnoldi() and
lanczos() construct smaller Krylov projections.
Set iter below the matrix dimension to build a smaller projection.
The pivoting options below refer to dense methods; sparse methods use their own pivoting and ordering schemes. For Cholesky, positive definite input is a safe starting point for both LLT and LDLT.
| Solver | Function | Notes | Sparse support | Reference |
|---|---|---|---|---|
| LU decomposition | solve_lu() |
Partial or full pivoting | Yes | 1, 2, 3 |
| Householder QR | solve_qr() |
Column, full, or no pivoting; rectangular least squares | Yes | 1, 2, 3, 4 |
| Cholesky decomposition | solve_chol() |
LDLT by default; LLT with pivot = 0
|
Yes | 1, 2, 3, 4 |
| Iterative Krylov methods | solve_cg() |
BiCGSTAB (default); LSCG for least squares; CG for symmetric positive definite systems; preconditioners available | Only¹ | 1, 2, 3 |
¹ Sparse matrices are used internally; dense inputs are converted.
| Method | Function | Notes | Sparse support | Reference |
|---|---|---|---|---|
| Eigenvalue decomposition | eigen2() |
General square and symmetric matrices | No | 1, 2 |
| Singular value decomposition | svd2() |
Divide-and-conquer SVD for large problems; Jacobi SVD for small problems | No | 1, 2 |
| Arnoldi iteration | arnoldi() |
Hessenberg projection; uses Lanczos for symmetric matrices | Only¹ | 1 |
| Lanczos algorithm | lanczos() |
Tridiagonal projection for symmetric matrices | Only¹ | 1 |
¹ Sparse matrices are used internally; dense inputs are converted.
To cite sanic, please use:
Kuschnig, N. (2026). sanic: Solving Ax = b Nimbly in C++ (R package version 0.0.2). https://CRAN.R-project.org/package=sanic
BibTeX:
@Manual{sanic,
title = {{sanic}: Solving {A}x = b Nimbly in {C++}},
author = {Nikolas Kuschnig},
year = {2026},
note = {R package version 0.0.2},
url = {https://CRAN.R-project.org/package=sanic}
}
See LICENSE for package licensing and third-party attribution, including the MPL-2.0 header adapted from Eigen and Spectra.