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 library is named after 算木 (sangi), the wooden calculation rods used in Japanese wasan mathematics; the sangi digit seven, , happens to mirror the shape of the letter π.
| Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| Sangi |
Digits 1–5 stack vertical rods; 6–9 add a horizontal rod — the same structure later inherited by the Japanese soroban. Zero was represented by an empty cell.
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.05.23a.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-05-23 | Tensor released |
| 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 |