C++23 solver suite for numerical linear algebra, ODE/PDE integration, Fourier transforms, and statistical simulation.
Direct solvers, Krylov methods, eigen/SVD routines, finite-difference operators, FFTs, and Monte Carlo kernels with custom implementations plus optional BLAS/LAPACK/LAPACKE, FFTW3, OpenMP, CUDA, and MPI backends.
Link the library target from CMake. The target requires a C++23 compiler.
include(FetchContent)
FetchContent_Declare(
numerics
GIT_REPOSITORY https://github.com/AdityaDendukuri/numerics
GIT_TAG main
)
FetchContent_MakeAvailable(numerics)
target_link_libraries(my_app PRIVATE numerics)
Installed use:
find_package(numerics REQUIRED)
target_link_libraries(my_app PRIVATE numerics::numerics)
Optional system packages: BLAS/LAPACK/LAPACKE or MKL, FFTW3, OpenMP, CUDA, and MPI.
#include <numerics.hpp>
int main() {
const double sigma = 10.0, rho = 28.0, beta = 8.0 / 3.0;
auto lorenz = [&](double, const num::Vector& s, num::Vector& ds) {
ds[0] = sigma * (s[1] - s[0]);
ds[1] = s[0] * (rho - s[2]) - s[1];
ds[2] = s[0] * s[1] - beta * s[2];
};
num::Series xz;
auto observer = [&](double, const num::Vector& y) {
xz.store(y[0], y[2]);
};
num::solve(
num::ODEProblem{lorenz, {1.0, 0.0, 0.0}, 0.0, 50.0},
num::RK45{.rtol = 1e-8, .atol = 1e-10, .max_steps = 2000000},
observer);
num::plt::plot(xz);
num::plt::title("Lorenz attractor (sigma=10, rho=28, beta=8/3)");
num::plt::xlabel("x");
num::plt::ylabel("z");
num::plt::savefig("lorenz.png");
}
num::solve + num::RK45#include <numerics.hpp>
#include <cmath>
#include <numbers>
int main() {
constexpr int N = 1024;
constexpr double fs = 1000.0;
constexpr double pi = std::numbers::pi;
num::Vector x(N);
for (int i = 0; i < N; ++i)
x[i] = std::sin(2.0 * pi * 50.0 * i / fs)
+ 0.5 * std::sin(2.0 * pi * 120.0 * i / fs);
num::CVector X(N / 2 + 1);
num::spectral::rfft(x, X);
num::Series signal, spectrum;
for (int i = 0; i < 100; ++i)
signal.store(i / fs * 1000.0, x[i]);
for (num::idx k = 0; k < X.size(); ++k)
spectrum.store(k * fs / N, std::abs(X[k]));
num::plt::subplot(2, 1);
num::plt::plot(signal);
num::plt::title("Signal: 50 Hz + 0.5 * 120 Hz");
num::plt::xlabel("time (ms)"); num::plt::ylabel("amplitude");
num::plt::next();
num::plt::plot(spectrum);
num::plt::title("FFT power spectrum");
num::plt::xlabel("frequency (Hz)"); num::plt::ylabel("|X[k]|");
num::plt::savefig("fft_demo.png");
}
num::spectral::rfft; peaks at 50 Hz and 120 Hz#include <numerics.hpp>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <random>
#include <vector>
int main() {
constexpr int N = 64;
constexpr int NN = N * N;
num::PBCLattice2D nbr(N);
std::vector<double> spins(NN);
std::mt19937 rng(42);
num::Series curve;
for (double T = 0.5; T <= 4.01; T += 0.1) {
std::fill(spins.begin(), spins.end(), 1.0);
double beta = 1.0 / T;
auto accept = [&](int i) {
double ns = spins[nbr.up[i]] + spins[nbr.dn[i]]
+ spins[nbr.lt[i]] + spins[nbr.rt[i]];
return num::markov::boltzmann_accept(2.0*spins[i]*ns, beta);
};
auto flip = [&](int i) { spins[i] = -spins[i]; };
auto measure = [&]() {
return std::abs(std::accumulate(spins.begin(), spins.end(), 0.0) / NN);
};
double m = num::solve(
num::MCMCProblem{accept, flip, NN},
num::Metropolis{.equilibration = 2000, .measurements = 500},
measure, rng);
curve.store(T, m);
}
num::plt::plot(curve);
num::plt::xlabel("T"); num::plt::ylabel("|<m>|");
num::plt::savefig("ising_demo.png");
}
num::solve + num::Metropolis; |m| drops at Tc ≈ 2.27#include <numerics.hpp>
#include <string>
int main() {
constexpr int N = 64;
constexpr double kappa = 1.0, sigma = 0.06, t_end = 0.012;
constexpr double h = 1.0 / (N + 1);
constexpr double dt = 4.0 * h * h;
const int nstep = static_cast<int>(t_end / dt) + 1;
const double coeff = kappa * dt / (h * h);
num::Grid2D grid{N, h};
num::SparseMatrix A = num::pde::backward_euler_matrix(grid, coeff);
num::operators::SparseOp Aop(A);
num::LinearSolver solver = [&](const num::Vector& rhs, num::Vector& x) {
return num::cg(Aop, rhs, x, 1e-8);
};
num::ScalarField2D u0(grid, [=](double x, double y) {
return num::gaussian2d(x, y, 0.5, 0.5, sigma);
});
num::ScalarField2D u = u0;
num::solve(u, num::BackwardEuler{.solver = solver, .dt = dt, .nstep = nstep});
num::plt::subplot(1, 2);
num::plt::heatmap(u0); num::plt::title("t = 0");
num::plt::next();
num::plt::heatmap(u); num::plt::title("t = " + std::to_string(t_end));
num::plt::savefig("heat_demo.png");
}
num::solve + num::BackwardEulerBLAS-style vector operations, reductions, triangular solves, modified Gram-Schmidt, and Arnoldi steps.
Dense vectors and matrices, CSR sparse matrices, band storage, matvec, matmul, dot, axpy, scale, and norms.
Uniform 2D/3D grids, scalar fields, vector fields, coordinate access, flat indexing, and trilinear sampling.
Problem drivers for ODE integration and Monte Carlo sampling: RK45, BackwardEuler, Metropolis, and related tags.
LU with pivoting, QR, Thomas tridiagonal solve, and banded direct solves; LAPACK/LAPACKE paths where enabled.
CG for SPD systems, restarted GMRES for nonsymmetric systems, and stationary Jacobi/Gauss-Seidel iterations.
Power, inverse and Rayleigh iterations, Lanczos projection, Ritz values, and dense symmetric Jacobi sweeps.
Operator arguments for \(y \leftarrow Ax\): dense, sparse, and matrix-free forms used by CG, GMRES, Lanczos, and expv.
Full singular value decomposition and randomized truncated SVD.
Complex FFT/IFFT, real FFT, radix-2 plans, and optional FFTW3 execution.
Quadrature (trapz, Simpson, Gauss-Legendre, Romberg) and root-finding (bisection, Newton, Brent).
Metropolis sweeps, precomputed Boltzmann probabilities, umbrella windows, and acceptance statistics.
Welford online mean/variance, fixed-bin histograms, WHAM reweighting, and integrated autocorrelation time.
Linked-cell neighbor search, Verlet lists with skin radius, periodic lattices, and SPH kernels.
Finite-difference stencils, periodic/Dirichlet Laplacians, backward Euler matrices, ADI diffusion, and DST Poisson solves.
Euler, RK4, adaptive RK45, velocity Verlet, Yoshida4, and backward Euler steps.
SPH, Navier-Stokes projection, TDSE splitting, magnetostatics, Ising Monte Carlo, and N-body gravity.
Backend::blocked dispatch, cache-tiled matmul loop structure, implementation file, and benchmark command.
Scalar micro-kernel shape, diagnostic entry point, and the transition from cache blocking to SIMD.
Backend::simd dispatch, optimized dense-kernel locations, FFT SIMD/FFTW backend examples.
Matrix-free pressure operator, CG backend selection, and projection-step code pattern.
Higher-order grid functions: 2D/3D Laplacians, fiber sweeps for ADI splitting, gradient, divergence, curl on Grid3D.
ScalarField3D, VectorField3D, Poisson solves, gradients, divergence, curl, and \(\mathbf{B}=\nabla\times\mathbf{A}\).
Cubic spline density kernel, Morris viscosity Laplacian, and spiky pressure gradient in 2D/3D.
PBCLattice2D: precomputed periodic-boundary neighbor arrays for 2D square lattices; eliminates modulo in hot paths.
BFS connected-component labeling on square lattices; largest-cluster statistics for Ising nucleation.
boltzmann_accept and make_boltzmann_table: precompute min(1,exp(-βΔE)) for discrete energy sets.
Real signal spectrum, complex round trip, reusable FFT plans, explicit FFT backend calls.
Explicit diffusion, backward Euler sparse CG, ADI diffusion, and Poisson solve examples.
Dirichlet Poisson setup, manufactured sine solution, DST solve, finite-difference reference.
Storage concepts, dense/sparse/callable operators, CG, GMRES, Lanczos, and expv examples.
Detailed algorithm theory belongs in the companion scientific-computing notes; this site focuses on numerics API examples and implementation notes.
Generated by cmake --build build --target report. Includes build metadata, test results, and throughput tables by routine family.