High-performance molecular integral library for quantum chemistry.
A standalone Rust library for evaluating one-electron and two-electron molecular integrals over Gaussian-type orbitals. Designed to outperform libcint — the de facto standard C library (~60,500 lines) used by PySCF, Q-Chem, and dozens of quantum chemistry codes — through SIMD batching, const-generic specialization, and unified derivative computation. Compiles to both native and WebAssembly from the same source.
| Capability | libcint | rustint |
|---|---|---|
| SIMD | Auto-vectorization only | Explicit AVX2/AVX-512/NEON/WASM SIMD128 via trait abstraction |
| Batching | One quartet at a time | N quartets per SIMD operation (Structure-of-Arrays) |
| Derivatives | 3 separate code paths (6,000+ lines) | Unified fused Rys: single pass for base + all derivative orders |
| Specialization | Common Lisp code generation (570 functions) | Rust const generics: compiler monomorphization |
| WebAssembly | Not supported | Native wasm32 target, same source |
| Memory safety | Manual C pointers | Rust ownership + arena allocators, zero undefined behavior |
| Screening | Binary Schwarz threshold | Multi-level: Schwarz + density-weighted + distance-based |
| Threading | External (caller must parallelize) | Built-in Rayon with WASM-aware fallback |
rustint v0.1 is the production integral engine of IQCP, a browser-based quantum chemistry application (RHF/LDA/B3LYP energies, analytic gradients and Hessians, harmonic frequencies, IR/Raman intensities) validated against PySCF 2.11.0. The library provides:
- One-electron integrals: overlap, kinetic, nuclear attraction — values, first derivatives, and second derivatives (Cartesian and spherical)
- Two-electron integrals: ERIs via Rys quadrature with const-generic specialization, first derivatives (fused Rys), and second derivatives
- Direct Fock builds: J/K matrices with 8-fold permutational symmetry, multi-level screening, and built-in Rayon threading
- GTO evaluation on grids: values and gradients for DFT quadrature
- Dipole and electric-field perturbation integrals (length gauge)
- SIMD backends: AVX2, AVX-512, NEON, WASM SIMD128, scalar — selected by feature flag, with lane-wise bit-identity tests across backends
- WebAssembly: the same source compiles to wasm32 (including a deterministic relaxed-FMA build used by IQCP in production)
Element coverage H–Ar, angular momentum through g functions (L ≤ 4 via const-generic fast paths, higher L via runtime fallback).
crates/
rustint/ Core library — public API, all integral algorithms
rustint-ffi/ C-ABI wrapper for non-Rust callers
Const-generic angular momentum specialization — The compiler monomorphizes
shell_eri_kernel<LA, LB, LC, LD>into specialized functions with stack-allocated VRR tables and compile-time loop bounds. A static dispatch table maps runtime angular momentum values to these specialized kernels, replacing libcint's Common Lisp code generator.SIMD batching — Structure-of-Arrays layout processes N shell quartets simultaneously per SIMD operation (4 for AVX2, 8 for AVX-512, 2 for WASM SIMD128). Abstracted behind a
SimdF64trait for portability across platforms.Fused Rys derivatives — Single VRR pass at extended angular momentum (L + 2*DERIV_ORDER) produces base integrals and all derivative orders simultaneously. Replaces libcint's 3 separate passes for base/gradient/Hessian integrals.
Multi-level screening — Schwarz bounds (always) + density-weighted screening (during SCF) + distance-based Gaussian decay (extended systems). Reduces redundant integral computation by 30-60%.
Arena allocator — Thread-local bump allocator for scratch space in hot paths. O(1) allocation and reset, zero system allocator calls during integral evaluation.
| Module | Purpose |
|---|---|
boys.rs | Boys function F_m(T): series, recurrence, asymptotic regimes |
rys.rs | Rys quadrature roots and weights via Chebyshev/Stieltjes algorithm |
basis.rs | Shell, Nucleus, BasisSet types |
one_electron/ | Overlap, kinetic, nuclear attraction (Obara-Saika), 1e derivatives |
two_electron/ | ERIs, const-generic kernels, batched SIMD, VRR, HTR, fused Rys |
simd/ | SimdF64 trait + backends (AVX2, AVX-512, NEON, WASM, scalar) |
screening.rs | Multi-level integral screening engine |
arena.rs | Thread-local bump allocator |
use rustint::{Shell,Nucleus,BasisSet, n_cart};// Compute overlap integrals for a shell pairshell_overlap(&shell_i,&shell_j,&mut out);// Compute electron repulsion integrals for a shell quartetshell_eri(&shell_a,&shell_b,&shell_c,&shell_d,&mut out);// Compute ERI gradients (fused Rys — single pass)shell_eri_grad(&shell_a,&shell_b,&shell_c,&shell_d,&mut grad_out);// Full overlap matrix for a basis setlet s_matrix = overlap_matrix(&basis);// Full ERI tensor with screening and parallelismlet eri = eri_tensor(&basis,&config);cargo add rustint-qcThe crates.io package is named rustint-qc (the bare rustint name is held
by an unrelated project), but the library target is rustint — so code
imports are unchanged:
use rustint::{Shell, shell_eri};Note: the PySCF golden-test data (~55 MB) ships in this GitHub repository but is excluded from the crates.io package to respect the registry size limit; see Golden test data.
use rustint::{Shell,Nucleus,BasisSet, n_cart, n_sph};// Define a hydrogen 1s shell (STO-3G)let h1s = Shell{l:0,center:[0.0,0.0,0.0],exponents:vec![3.42525091,0.62391373,0.16885540],coefficients:vec![0.15432897,0.53532814,0.44463454],atom_idx:0,};// Angular momentum component countsassert_eq!(n_cart(0),1);// s-shell: 1 Cartesian componentassert_eq!(n_cart(1),3);// p-shell: 3 (px, py, pz)assert_eq!(n_cart(2),6);// d-shell: 6 (xx, xy, xz, yy, yz, zz)// Build a basis set (auto-computes n_basis)let basis = BasisSet::new(vec![h1s],vec![Nucleus{
charge:1.0,
position:[0.0,0.0,0.0],}]);assert_eq!(basis.n_basis,1);Validated against PySCF 2.11.0 and mpmath reference values with strict, non-negotiable tolerances. Worst measured deviations:
| Quantity | Tolerance | Measured (worst case) |
|---|---|---|
| Boys function F_m(T) | 1e-15 relative | 5.1e-15 (m=50), 2.2e-15 typical |
| Rys quadrature moments (n=1-20) | 1e-14 / 1e-13 | ~1e-16 (machine eps) |
| Overlap integrals | 1e-14 absolute | 2.2e-16 |
| Kinetic integrals | 1e-14 absolute | 3.6e-15 |
| Nuclear attraction (Rys) | 1e-13 absolute | 1.1e-13 (CH4/cc-pVDZ, at the PySCF precision floor) |
| Two-electron ERIs | 1e-12 absolute | 1.3e-13 ((dd |
| 1st-derivative integrals (S, T, V, ERI) | 1e-10 absolute | <= 5.7e-15 |
| 2nd-derivative 1e integrals (S'', T'', V'') | 1e-12 absolute | 16/17 PySCF golden cells strict-pass; 1 cell at the measured f64 architectural floor (2.1e-11, C6H6/cc-pVDZ V'' — propagates to <= 0.5 cm^-1 in frequencies) |
| 2nd-derivative ERIs | 1e-12 absolute | full archetype matrix vs PySCF |
| Dipole integrals | 1e-12 absolute | 5.7e-15 (C6H6/cc-pVDZ) |
| Field perturbation +E.r | 1e-12 absolute | 2.8e-17 |
| GTO grid evaluation (value/gradient) | 1e-12 absolute | 8.9e-16 / 3.6e-15 |
| SIMD backend bit-identity | 0 ULP lane-wise | 0 deviations (Scalar vs AVX2 vs AVX-512, ~10^5 lane checks) |
Cross-backend reductions (reduce_sum) differ by tree shape as mathematically
required; everything upstream of the first cross-lane operation is bit-identical
across backends by test.
Measured against libcint (the reference C library used by PySCF) on Xeon Silver 4314: rustint's cached scalar ERI path is competitive to faster per shell class, the fused-Rys derivative kernels avoid libcint's multiple passes, and the threaded Fock builder reaches parallel efficiency η(8) ≈ 0.87–0.93 on H₂O/C₆H₆ cc-pVDZ. In-browser (WASM), rustint powers interactive SCF at sizes up to caffeine/6-31++G** (312 basis functions) via integral-direct Fock builds. Detailed, reproducible benchmark methodology ships with the IQCP publication material.
cargo test passes out of the box: reference data (PySCF 2.11.0 golden
files) ships in crates/rustint/tests/golden/ for all but 11 large files
(>10 MB each) that are excluded to keep the repository lean. Tests that
need an absent large golden print a SKIP line and pass gracefully; the
files can be regenerated with the PySCF scripts in scripts/ (see
crates/rustint/tests/golden/README.md).
[features]
default = ["simd-auto"]
simd-auto = [] # Compile-time SIMD detection (default)avx2 = [] # Force AVX2 (f64x4, 4 lanes)avx512 = [] # Force AVX-512 (f64x8, 8 lanes)neon = [] # Force ARM NEON (f64x2, 2 lanes)wasm-simd = [] # Force WASM SIMD128 (f64x2, 2 lanes)wasm-simd-relaxed = [] # WASM relaxed-SIMD FMA build (deterministic; used by IQCP)max-l-4 = [] # Limit to L<=4 (81 dispatch entries, smaller binary)max-l-6 = [] # Limit to L<=6 (2,401 dispatch entries)# Default: MAX_L=8 (6,561 dispatch entries)parallel = [] # Enable Rayon multi-threadingserde = [] # Enable Shell/BasisSet serializationno_std = [] # no_std + alloc compatibilitydev-fast = [] # (dev only) Shrink const-generic ERI dispatch from L<=4 (625 kernels)# to L<=2 (81 kernels) to cut cold release compile time# from ≥102 min to 20 s (≥308× speedup). Incompatible with# max-l-4 and max-l-6. DO NOT ship release artifacts with this.| Platform | SIMD Backend | Threading |
|---|---|---|
| Linux x86_64 | AVX2 / AVX-512 | Rayon |
| macOS x86_64 | AVX2 | Rayon |
| macOS ARM64 (Apple Silicon) | NEON | Rayon |
| Windows x86_64 | AVX2 / AVX-512 | Rayon |
| WebAssembly | SIMD128 / scalar | Single-threaded |
# Native build
cargo build --workspace
# WASM target
cargo build -p rustint-qc --target wasm32-unknown-unknown
# With features
cargo build -p rustint-qc --features "parallel,serde"# Run tests
cargo test --workspace
# Run benchmarks (when available)
cargo bench --workspaceThe default wasm build is single-threaded and builds on stable. Browser
multi-threading (the _parallel drivers, e.g. fock_hessian_contract_parallel)
is backed by wasm-bindgen-rayon (Web
Workers + SharedArrayBuffer). It requires nightly + atomics + build-std
and a cross-origin-isolated host page (COOP: same-origin,
COEP: require-corp):
RUSTFLAGS="-C target-feature=+atomics,+bulk-memory,+mutable-globals,+simd128" \
rustup run nightly \
wasm-pack build crates/rustint --release --target web \
--features "parallel,wasm-simd" -- -Z build-std=panic_abort,stdCall await initThreadPool(n) once from JS before any _parallel driver runs.
Full recipe (build flags, JS init, COOP/COEP headers, headless test):
docs/wasm-threading.md.
Minimal by design:
| Dependency | Purpose | Required |
|---|---|---|
wide | Portable SIMD (f64x4, f64x2) | Yes |
libm | Pure-Rust math (exp, erf, sqrt) for no_std/WASM | Yes |
thiserror | Error derive macros | Yes |
rayon | Multi-threading | Optional (parallel feature) |
wasm-bindgen-rayon | Browser threading (Web Workers + SharedArrayBuffer) | Optional (parallel feature, wasm32-only) |
serde | Serialization | Optional (serde feature) |
No nalgebra, no ndarray — callers provide flat &[f64] slices.
| Paper | Topic |
|---|---|
| Shavitt (1963) | Boys function evaluation |
| Dupuis, Rys & King (1976) | Rys quadrature for molecular integrals |
| Obara & Saika (1986) | Recurrence relations for 1e integrals |
| Head-Gordon & Pople (1988) | HGP algorithm for 2e integrals |
| McMurchie & Davidson (1978) | Alternative recurrence scheme |
Algorithms are cross-validated against established open reference implementations, including libcint (C), SIMINT (C), libint2 (C++), GauXC (C++), gbasis (Python), libgtoint (C/Fortran), and Intception (C), with numerical reference values from PySCF and mpmath.
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
rustint is currently developed as a solo project by ExaPsi. Contributions may be accepted after the v0.1.0 release.