sangi
C++23 Comprehensive Math Library
C++23 / LGPL v3 / Zero External Dependenciessangi is a C++23 math library that provides arbitrary-precision arithmetic (Int, Float, Rational), complex numbers, polynomials, matrices, special functions, FFT, and Lie groups within a single unified framework.
The name derives from 算木 (sangi), the wooden calculation rods used in Japanese wasan mathematics from the 8th to 19th century. Mathematicians including Seki Takakazu (1642–1708) employed them in works such as Hatsubi Sanpou (1674) — Japan's indigenous mathematical computing instrument.
Arbitrary Precision
Three core types: Int (integer), Float (floating-point), and Rational. High-speed mpn operations via BMI2/ADX instructions, with a 7-tier multiplication pipeline (Basecase → Karatsuba → Toom-3 → Toom-4 → Toom-6 → Toom-8 → NTT).
NaN / Infinity Safe
NaN and Infinity propagate safely across Int, Float, and Rational. Division by zero never crashes.
C++23 Concepts
Defines 50+ algebraic concepts such as Ring, Field, and VectorSpace. Write type-safe generic algorithms with compile-time guarantees.
80+ Special Functions
Bessel, Airy, Gamma, Zeta, elliptic integrals, hypergeometric functions, and more.
Available for double, Complex<double>, and Float (arbitrary precision).
Numerical Algorithms
Linear algebra (LU/QR/SVD), root-finding, interpolation, and FFT.
Combine freely with arbitrary-precision types, e.g. Matrix<Float>.
Lie Groups / Algebras
SO(2), SE(2), SO(3), SE(3) with exp/log, Jacobians, and adjoint representations. Left-perturbation model (GTSAM convention).
API Reference
Core Types (Numeric)
Algebraic Structures (Header-Only)
Algorithm Modules (Header-Only)
Algorithm Details
In-depth explanations of the algorithms used internally. Covers thresholds, computational complexity, and design rationale.
Linear Algebra
Root Finding
Optimization
Polynomials
Spectral Transforms
Multi-precision Arithmetic
Integer
Rational
Complex
Floating Point
Demos
Working examples using sangi features. Includes source code — build and run locally.
Examples
Int — Arbitrary-Precision Integer
#include <math/core/mp/Int.hpp>
#include <iostream>
using namespace sangi;
int main() {
Int a("123456789012345678901234567890");
Int b("987654321098765432109876543210");
std::cout << "a + b = " << a + b << std::endl;
std::cout << "a * b = " << a * b << std::endl;
std::cout << "gcd = " << gcd(a, b) << std::endl;
// Primality test (Miller-Rabin)
Int p("170141183460469231731687303715884105727"); // 2^127 - 1
std::cout << p << " is prime: " << std::boolalpha
<< isProbablePrime(p) << std::endl;
// NaN/Infinity safe propagation
Int zero;
Int nan = Int(1) / zero;
std::cout << "1/0 = " << nan << std::endl; // NaN
}
Float — Arbitrary-Precision Floating-Point
#include <math/core/mp/Float.hpp>
#include <iostream>
using namespace sangi;
int main() {
int prec = 50; // 50-digit precision
Float::setDefaultPrecision(prec);
// Mathematical constants (thread-local cached; instant on subsequent calls)
Float pi = Float::pi(prec); // π to 50 digits (Chudnovsky)
// Transcendental functions
Float y = exp(pi, prec); // e^π
Float z = log(y, prec); // log(e^π) = π
std::cout << "exp(pi) = " << y.toDecimalString(prec) << std::endl;
std::cout << "log(exp(pi)) = " << z.toDecimalString(prec) << std::endl;
// Trigonometric functions
Float s = sin(pi / Float(6, prec), prec); // sin(π/6) = 0.5
std::cout << "sin(pi/6) = " << s.toDecimalString(20) << std::endl;
}
Rational — Arbitrary-Precision Rational Number
#include <math/core/mp/Rational.hpp>
#include <iostream>
using namespace sangi;
int main() {
Rational a(1, 3); // 1/3
Rational b(1, 6); // 1/6
Rational sum = a + b;
std::cout << "1/3 + 1/6 = " << sum << std::endl; // 1/2 (auto-reduced)
Rational product = a * b;
std::cout << "1/3 * 1/6 = " << product << std::endl; // 1/18
// Combine with arbitrary-precision integers
Rational big(Int("1000000000000000000"), Int("3"));
std::cout << big << std::endl;
}
Complex — Complex Numbers
#include <math/core/Complex.hpp>
#include <iostream>
using namespace sangi;
using namespace sangi::literals;
int main() {
Complex<double> z(3.0, 4.0);
std::cout << "z = " << z << std::endl; // (3, 4)
std::cout << "|z| = " << abs(z) << std::endl; // 5
std::cout << "arg = " << arg(z) << std::endl; // 0.9273
std::cout << "conj = " << conj(z) << std::endl; // (3, -4)
// Euler's formula: e^(i*pi) = -1
auto euler = exp(Complex<double>(0, std::numbers::pi));
std::cout << "e^(i*pi) = " << euler << std::endl; // (-1, 0)
// User-defined literal
auto w = 2.0 + 3.0_i;
std::cout << "w*w = " << w * w << std::endl; // (-5, 12)
}
Vector — Numeric Vector
#include <math/core/vector.hpp>
#include <iostream>
using namespace sangi;
int main() {
Vector<double> a{1.0, 2.0, 3.0};
Vector<double> b{4.0, 5.0, 6.0};
// Expression templates: no temporaries until assignment
Vector<double> c = 2.0 * a + b;
std::cout << "dot(a, b) = " << dot(a, b) << std::endl; // 32
std::cout << "norm(a) = " << norm(a) << std::endl; // 3.74166
// 3D cross product (StaticVector)
StaticVector<double, 3> i{1, 0, 0}, j{0, 1, 0};
auto k = cross(i, j); // [0, 0, 1]
}
Matrix — Dense Matrix
#include <math/core/matrix.hpp>
#include <math/core/mp/Rational.hpp>
#include <math/linalg/decomposition.hpp>
#include <iostream>
using namespace sangi;
using namespace sangi::algorithms;
int main() {
// Matrix operations
Matrix<double> A({{2, 1, -1}, {-3, -1, 2}, {-2, 1, 2}});
Vector<double> b({8, -11, -3});
auto x = lu_solve(A, b); // x = {2, 3, -1}
// operator^: transpose, inverse, power
auto At = A ^ 'T'; // transpose
auto Ainv = A ^ (-1); // inverse
auto A3 = A ^ 3; // A*A*A
// Exact inverse with Rational
Matrix<Rational> H(3, 3);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
H(i, j) = Rational(1, i + j + 1); // Hilbert matrix
auto Hinv = lu_inverse(H); // all integer entries (exact)
auto I = H * Hinv; // exactly identity
}
LinAlg — Linear Algebra
#include <math/core/matrix.hpp>
#include <math/linalg/decomposition.hpp>
#include <math/linalg/eigenvalues.hpp>
#include <iostream>
using namespace sangi;
using namespace sangi::algorithms;
int main() {
Matrix<double> A({{4, 1, 1}, {1, 3, 0}, {1, 0, 2}});
// SVD decomposition
auto [U, sigma, Vt] = svd_decomposition(A);
// Symmetric eigenvalues
auto [evals, evecs] = eigen_symmetric(A);
// Gaussian elimination (pivot strategy selection)
Vector<double> b({6, 4, 3});
auto x = gaussian_elimination(A, b, PivotStrategy::Full);
// Bareiss: integer determinant (division-free)
Matrix<int> M({{1, 2, 3}, {4, 5, 6}, {7, 8, 10}});
auto det = bareiss_determinant(M); // -3
}
Polynomial — Polynomial
#include <math/core/polynomial.hpp>
#include <iostream>
using namespace sangi;
int main() {
// x^2 - 1 = (x-1)(x+1)
Polynomial<double> p({-1, 0, 1}); // -1 + 0x + x^2
Polynomial<double> q({1, 1}); // 1 + x
auto [quot, rem] = p.divmod(q);
std::cout << "quot = " << quot << std::endl; // -1 + x
std::cout << "rem = " << rem << std::endl; // 0
// Differentiation and integration
auto dp = p.derivative(); // 2x
auto ip = p.integral(); // -x + x^3/3
// Root finding (all complex roots)
auto roots = findAllRoots(p); // {-1, 1}
}
FFT — Fast Fourier Transform
#include <math/fft/fft.hpp>
#include <math/fft/fft_utils.hpp>
#include <iostream>
using namespace sangi;
int main() {
// Complex FFT (in-place)
std::vector<Complex<double>> data = {1, 2, 3, 4};
FFT<Complex<double>>::fft(data); // forward
FFT<Complex<double>>::ifft(data); // inverse (recovers original)
// Real FFT (N -> N/2+1 complex spectrum)
std::vector<double> signal = {1, 0, -1, 0, 1, 0, -1, 0};
auto spectrum = RealFFT<double>::fft(signal);
auto amp = amplitude_spectrum<double>(spectrum);
// Polynomial multiplication (convolution)
std::vector<double> a = {1, 2, 3}, b = {4, 5};
auto c = RealFFT<double>::convolve(a, b); // {4, 13, 22, 15}
}
Roots — Root-Finding Algorithms
#include <math/roots/roots.hpp>
#include <math/core/polynomial.hpp>
#include <iostream>
using namespace sangi;
int main() {
// Brent's method: root of f(x) = x^3 - 2 (= ∛2)
auto f = [](double x) { return x * x * x - 2.0; };
double root = brentRoot(f, 1.0, 2.0);
std::cout << "cbrt(2) = " << root << std::endl; // 1.25992...
// Newton's method: root of f(x) = sin(x) - 0.5
auto g = [](double x) { return std::sin(x) - 0.5; };
auto dg = [](double x) { return std::cos(x); };
double r2 = newtonRoot(g, dg, 0.5);
std::cout << "arcsin(0.5) = " << r2 << std::endl; // π/6
// All complex roots of a polynomial (Aberth-Ehrlich)
Polynomial<double> p({6, -5, 1}); // x^2 - 5x + 6 = (x-2)(x-3)
auto roots = findAllRoots(p);
for (auto& z : roots)
std::cout << z << std::endl; // 2, 3
}
Optimization — Optimization
#include <math/optimization/optimization_nd.hpp>
#include <iostream>
using namespace sangi;
int main() {
using V = Vector<double>;
using M = Matrix<double>;
// BFGS minimization of the Rosenbrock function
auto f = [](const V& x) { return (1-x[0])*(1-x[0]) + 100*(x[1]-x[0]*x[0])*(x[1]-x[0]*x[0]); };
auto df = [](const V& x) {
return V{-2*(1-x[0]) - 400*x[0]*(x[1]-x[0]*x[0]),
200*(x[1]-x[0]*x[0])};
};
auto result = bfgs_minimize<double, V, M>(f, df, V{-1, -1});
std::cout << "min at " << result.point << std::endl; // [1, 1]
std::cout << "f(min) = " << result.value << std::endl; // ~0
}
Build
Requirements
- 64-bit OS (x86_64 / AArch64)
- CMake 3.20 or later
Supported Compilers
| Compiler | Minimum Version | ASM Optimization | Status |
|---|---|---|---|
| MSVC (Visual Studio 2022) | 17.6+ | MASM (AVX2 + BMI2 + ADX) | Tested |
| GCC | 14+ | GAS (AVX2 + BMI2 + ADX) | Tested |
| Clang | 17+ | GAS (AVX2 + BMI2 + ADX) | Tested |
Supported Platforms and Performance
sangi requires a 64-bit (x86_64 / AArch64) environment.
The internal arbitrary-precision arithmetic relies on 64-bit limbs and 128-bit wide multiplication (_umul128 / __uint128_t), so 32-bit platforms are not supported.
The following hardware features are automatically utilized when available:
| Fast Path | Enabled When | Fallback |
|---|---|---|
| AVX2 NTT Butterfly | AVX2-capable CPU (Intel Haswell+ / AMD Zen+) | Scalar Montgomery NTT |
| MULX/ADCX/ADOX mpn Primitives |
BMI2 + ADX CPU, x64 (Windows: MASM / Linux: GAS) | C++ generic implementation |
| NTT Parallelization | NTT length ≥ 4096 (auto-detected) | Single-threaded |
- Windows x64 + AVX2: All fast paths enabled. Best performance.
- Linux x64 + AVX2: GAS assembly (BMI2 + ADX) + AVX2 NTT enabled. Performance on par with Windows.
- ARM / Apple Silicon: AVX2 and ASM both disabled. All features work via
__uint128_t-based C++ implementation. Estimated 2-3x slower than x64 ASM.
Download
Download the source code and build with CMake.
Download sangi-source-2026.04.28.zip
You can also browse individual files from the source listing.
Antivirus False Positive Warning
Executables built from source may be falsely flagged as malware by antivirus software.
sangi_int.lib contains modular exponentiation (Montgomery multiplication) and MASM assembly kernels,
which are statically linked into your executable.
Quarantine happens silently and may be reported with a delay, making it appear as though the build failed and no exe was generated. If blocked, add your build directory to your antivirus exclusion list.
Other cryptographic and arbitrary-precision libraries such as GMP and OpenSSL are also affected by the same issue.
Building from Source and Running Examples
Windows (MSVC)
cd sangi
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
After building, run the sample programs:
examples\Release\example-int.exe
examples\Release\example-float.exe
examples\Release\example-rational.exe
examples\Release\example-vector.exe
examples\Release\example-matrix.exe
examples\Release\example-linalg.exe
examples\Release\example-precision-showdown.exe
examples\Release\example-mp.exe
examples\Release\example-int-demo.exe
examples\Release\example-float-demo.exe
examples\Release\example-rational-demo.exe
examples\Release\example-vector-demo.exe
examples\Release\example-matrix-demo.exe
examples\Release\example-polynomial.exe
examples\Release\example-polynomial-factorization.exe
examples\Release\example-complex.exe
examples\Release\example-roots.exe
examples\Release\example-optimization.exe
examples\Release\example-fft.exe
Linux (GCC / Clang)
cd sangi
mkdir build && cd build
cmake .. -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_BUILD_TYPE=Release # GCC
# cmake .. -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_BUILD_TYPE=Release # Clang
cmake --build . -j$(nproc)
After building, run the sample programs:
./examples/example-int
./examples/example-float
./examples/example-rational
./examples/example-vector
./examples/example-matrix
./examples/example-linalg
./examples/example-precision-showdown
./examples/example-mp
./examples/example-int-demo
./examples/example-float-demo
./examples/example-rational-demo
./examples/example-vector-demo
./examples/example-matrix-demo
./examples/example-polynomial
./examples/example-polynomial-factorization
./examples/example-complex
./examples/example-roots
./examples/example-optimization
./examples/example-fft
Using sangi in Your Own Code
Once the examples work, try sangi in your own program.
Link the libraries (.lib) generated by the sangi build:
// myapp.cpp
#include <math/core/mp/Int.hpp>
#include <iostream>
using namespace sangi;
int main() {
Int a = Int::factorial(100);
std::cout << "100! = " << a << std::endl;
}
Windows (MSVC):
cl /std:c++23 /EHsc /utf-8 /I C:\path\to\sangi\include myapp.cpp ^
C:\path\to\sangi\build\lib\Release\sangi_int.lib ^
C:\path\to\sangi\build\lib\Release\sangi_fft.lib
myapp.exe
Linux (GCC / Clang):
g++-14 -std=c++23 -O2 -I sangi/include myapp.cpp \
sangi/build/lib/libsangi_int.a sangi/build/lib/libsangi_fft.a -lpthread -o myapp
./myapp
CMake:
target_include_directories(myapp PRIVATE path/to/sangi/include)
target_link_libraries(myapp PRIVATE
path/to/sangi/build/lib/sangi_int # or libsangi_int.a on Linux
path/to/sangi/build/lib/sangi_fft # required by Int multiplication
path/to/sangi/build/lib/sangi_float # if using Float
)
Release History
| 2026-04-28 | Complex · Optimization released |
| 2026-04-17 | Polynomial · Roots · FFT released |
| 2026-04-10 | Concepts released |
| 2026-04-03 | Matrix · LinAlg released |
| 2026-03-27 | Vector released |
| 2026-03-20 | Rational released |
| 2026-03-13 | Float released |
| 2026-03-02 | Int released |