SIMD-accelerated tensor operations and numerical optimization for high-performance robotics applications.
See TODO.md for the complete development plan and current progress.
Optinum is a header-only C++20 library that combines SIMD-accelerated tensor operations with numerical optimization algorithms, specifically designed for applications requiring real-time performance and deterministic behavior.
The library provides five integrated modules:
simd/- SIMD-accelerated operations (SSE/AVX/AVX-512/NEON) with 39 vectorized math functionslina/- Linear algebra (LU, QR, SVD, Cholesky, eigendecomposition, solvers)lie/- Lie groups (SO2, SE2, SO3, SE3, Sim2, Sim3, RxSO2, RxSO3) with batched SIMD operationsopti/- Gradient-based optimization (11 update policies, L-BFGS, Gauss-Newton, Levenberg-Marquardt)meta/- Metaheuristic optimization (PSO, CEM, CMA-ES, DE, GA, SA, MPPI, Lookahead, SWATS)
Key design principles:
- Header-only - Zero compilation, just include and use
- Non-owning views - Zero-copy SIMD operations over existing data
- Real-time friendly - No dynamic allocation in critical paths
- POD-compatible - Easy serialization for ROS2 message passing
- Deterministic - Predictable performance for control loops
Built on top of datapod for POD data ownership. Uses on:: as short namespace alias (enabled by default in examples/tests via -DSHORT_NAMESPACE).
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β APPLICATION LAYER β
β (SLAM, Navigation, Control, Planning) β
ββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β optinum (on::) β
β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββ βββββββββββββββββ β
β βon::meta β βon::opti β βon::lina β β on::lie β β on::simd β β
β β(meta- βββΆβ(gradient βββΆβ(linear βββΆβ(Lie βββΆβ(SIMD views + β β
β βheuristic)β β based) β β algebra)β β groups) β β algorithms) β β
β β β β β β β β β β β β
β ββ’ PSO β ββ’ Adam β ββ’ LU, QR β ββ’ SO2/SO3 β ββ’ pack<T,W> β β
β ββ’ CEM β ββ’ L-BFGS β ββ’ SVD β ββ’ SE2/SE3 β ββ’ 39 math β β
β ββ’ CMA-ES β ββ’ Gauss- β ββ’ Choleskyβ ββ’ Sim2/3 β ββ’ views β β
β ββ’ MPPI β β Newton β ββ’ solve β ββ’ batched β ββ’ algorithms β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββ βββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββ
β wraps (zero-copy)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β datapod (dp::) β
β (POD data storage - owns memory) β
β β
β dp::mat::scalar<T> dp::mat::vector<T,N> dp::mat::matrix<T,R,C> β
β (rank-0) (rank-1) (rank-2) β
β β
ββ’ Serializable for ROS2 β’ Cache-aligned β’ Column-major (BLAS-like) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data flow:
dp::mat::vector<float, N> (owns memory - serializable for ROS2)
β
on::Vector<float, N> (a view over on::simd::pack<float,W>)
β
on::simd::view<W>(dp_vector) (non-owning view - zero copy)
β
on::simd::exp(view) (algorithm layer - generic over view types)
β
on::simd::exp(pack<float,8>) (intrinsic layer - AVX/SSE/NEON)
include(FetchContent)
FetchContent_Declare(
optinum
GIT_REPOSITORY https://codeberg.org/robolibs/optinum
GIT_TAG main
)
FetchContent_MakeAvailable(optinum)
target_link_libraries(your_target PRIVATE optinum)XMake is a modern, fast, and cross-platform build system.
Install XMake:
curl -fsSL https://xmake.io/shget.text | bashAdd to your xmake.lua:
add_requires("optinum")
target("your_target")
set_kind("binary")
add_packages("optinum")
add_files("src/*.cpp")Build:
xmake
xmake runFor the ultimate reproducible development environment:
1. Install Nix (package manager from NixOS):
# Determinate Nix Installer (recommended)
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- installNix - Reproducible, declarative package management
2. Install direnv (automatic environment switching):
sudo apt install direnv
# Add to your shell (~/.bashrc or ~/.zshrc):
eval "$(direnv hook bash)" # or zshdirenv - Load environment variables based on directory
3. Install Devbox (Nix-powered development environments):
curl -fsSL https://get.jetpack.io/devbox | bashDevbox - Portable, isolated dev environments
4. Use the environment:
cd optinum
direnv allow # Allow .envrc (one-time)
# Environment automatically loaded! All dependencies available.
make build # or xmake
make test#include <optinum/optinum.hpp>
void process_sensor_data() {
// State vector: [x, y, theta, vx, vy]
dp::mat::vector<float, 5> state;
dp::mat::matrix<float, 5, 5> covariance;
// Create SIMD views (zero-copy, no allocation)
auto x = on::simd::view<8>(state);
auto P = on::simd::view<8>(covariance);
// SIMD-accelerated operations
on::simd::scale(0.99f, x); // Prediction step
on::simd::axpy(1.0f, sensor_data, x); // Measurement update
// Result already in 'state' - ready for serialization
}#include <optinum/lina/lina.hpp>
void solve_dynamics() {
on::Matrix<double, 6, 6> A; // Dynamics matrix
on::Vector<double, 6> b; // Target state
// Solve Ax = b using LU decomposition (SIMD-accelerated)
auto result = on::lina::try_solve(A, b);
if (result.is_ok()) {
auto x = result.unwrap();
// Apply solution
}
}#include <optinum/lie/lie.hpp>
void transform_points() {
// Create SE3 pose from rotation and translation
on::lie::SE3d pose = on::lie::SE3d::exp({0.1, 0.2, 0.3, 1.0, 2.0, 3.0});
// Transform a point
on::Vector<double, 3> point{1.0, 0.0, 0.0};
auto transformed = pose.act(point);
// Batched operations for point clouds
on::lie::SE3Batch<double, 100> poses; // 100 poses processed in parallel
}#include <optinum/opti/opti.hpp>
void optimize_trajectory() {
// Define objective function
auto objective = [](const auto& x) {
return on::lina::dot(x, x); // Sphere function
};
// Configure Adam optimizer
on::opti::Adam<double> optimizer({
.learning_rate = 0.01,
.beta1 = 0.9,
.beta2 = 0.999
});
on::Vector<double, 10> x; // Initial guess
auto result = optimizer.optimize(objective, x);
}#include <optinum/meta/meta.hpp>
void global_search() {
// CMA-ES for non-convex optimization
on::meta::CMAES<double> optimizer({
.population_size = 50,
.max_iterations = 1000
});
auto result = optimizer.optimize(rastrigin_function, lower_bounds, upper_bounds);
}-
SIMD Math Functions - 39 vectorized functions (exp, log, sin, cos, tanh, sqrt, erf, gamma, hypot)
auto x = on::simd::view<8>(data); // AVX: 8 floats at once on::simd::exp(x); // 7.94x speedup on::simd::tanh(x); // 27.55x speedup
-
Linear Algebra Suite - LU, QR, SVD, Cholesky, eigendecomposition with SIMD-accelerated solvers
auto [L, U, P] = on::lina::lu(A); // LU decomposition with pivoting auto [Q, R] = on::lina::qr(A); // QR decomposition auto [U, S, V] = on::lina::svd(A); // Singular value decomposition
-
Lie Groups - SO2, SE2, SO3, SE3, Sim2, Sim3, RxSO2, RxSO3 with exp/log maps, adjoints, and Jacobians
auto rotation = on::lie::SO3d::exp({0.1, 0.2, 0.3}); auto pose = on::lie::SE3d::from_rotation_translation(rotation, translation);
-
11 Gradient Update Policies - Adam, AdaGrad, AdaDelta, RMSprop, NAdam, AdaBound, Yogi, Nesterov, Momentum, AMSGrad, Vanilla
-
8 Decay Policies - Cosine annealing, exponential, inverse time, linear, polynomial, step, warmup, no decay
-
Quasi-Newton Methods - L-BFGS, Gauss-Newton, Levenberg-Marquardt for nonlinear least squares
-
9 Metaheuristics - PSO, CEM, CMA-ES, DE, GA, SA, MPPI, Lookahead, SWATS for global and black-box optimization
-
Non-Owning Views - Zero-copy SIMD operations over
dp::mat::*types -
Type-Safe Error Handling - Uses
dp::Result<T, dp::Error>instead of exceptions -
Platform SIMD Support - Automatic detection: SSE, AVX, AVX-512 (x86), NEON (ARM), scalar fallback
-
Real-Time Characteristics:
- Deterministic SIMD paths (no dynamic dispatch in hot loops)
- Fixed-size containers (compile-time dimensions)
- No hidden allocations (views are non-owning)
- Cache-friendly column-major layout (BLAS/LAPACK compatible)
Optinum uses a consistent error handling approach designed for real-time and embedded systems:
-
Fallible operations use
dp::Result<T, dp::Error>:try_solve(),try_inverse(),try_lstsq(),try_dare()- return Resultsolve(),inverse(),lstsq(),dare()- wrapper that returns zero/identity on error
auto result = on::lina::try_solve(A, b); if (result.is_ok()) { auto x = result.unwrap(); } else { // Handle error: result.error().message() }
-
Bounds checking uses
std::out_of_range(STL convention):at()methods throwstd::out_of_rangeoperator[]does debug-only bounds checking (viaassert)
-
Optimizers use status field in result struct:
OptimizationResult.converged = falseon failureOptimizationResult.statuscontains error message
auto result = optimizer.optimize(objective, x); if (!result.converged) { std::cerr << "Optimization failed: " << result.status << "\n"; }
-
Never use exceptions for recoverable errors in new code - prefer
dp::Resultfor explicit error handling
| Module | Files | Lines | Description |
|---|---|---|---|
simd/ |
92 | ~23,000 | SIMD pack types, views, 39 math functions |
lina/ |
37 | ~5,400 | 7 decompositions, solvers, DARE, Jacobian, Hessian |
lie/ |
22 | ~9,600 | 12 Lie groups, batched SIMD, splines, averaging |
opti/ |
32 | ~5,400 | 11 update policies, 8 decay policies, line search |
meta/ |
10 | ~3,900 | 9 metaheuristics |
Test Status: 104/105 test suites passing (500+ test cases)
MIT License - see LICENSE for details.
Made possible thanks to these amazing projects.
