From thermite
Documents Thermite, a generic ISA-portable Rust SIMD library, and its companion crates (special functions, autodiff, compensated arithmetic, SDF, geometry). Useful when adding Thermite as a dependency or writing SIMD kernels generic over vector types.
How this skill is triggered — by the user, by Claude, or both
Slash command
/thermite:thermiteThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Thermite is a pure-Rust SIMD abstraction library. You write a function **once**,
Thermite is a pure-Rust SIMD abstraction library. You write a function once,
generic over a trait hierarchy (GenericVector -> NumericVector -> FloatVector,
plus math traits), and it compiles to optimal code for every backend (SSE2,
SSE4.2, AVX2, WASM SIMD128, scalar, and an experimental SPIR-V GPU path) at every
lane count. The same generic function also runs on composite vector types --
Dual (forward-mode autodiff), Compensated (double-double precision), and
others -- with zero changes, because those types implement the same traits.
This skill is for developers who add Thermite as a dependency to their own
crate. It documents the core thermite crate plus the companion crates you can
pull in alongside it. File paths in the sub-files (e.g. crates/thermite/src/...)
point into the Thermite source so you can read the authoritative implementation;
they are references, not files in your own project.
This skill is the source of truth for using Thermite, second only to the code itself. Everything in it was verified against the current source. If any prose ever disagrees with the code, trust the code (and fix the skill).
Thermite is not on crates.io yet (core is 0.2.0-beta.0; the companion
crates are publish = false). Depend on it via git:
[dependencies]
# Core SIMD library. Default features are fine for most users; see the table below.
thermite = { git = "https://github.com/raygon-renderer/thermite" }
# Optional companion crates (each is a separate dependency; all currently git-only):
thermite-special = { git = "https://github.com/raygon-renderer/thermite" } # erf, gamma, activations, Lambert W, ...
thermite-dual = { git = "https://github.com/raygon-renderer/thermite" } # forward-mode autodiff (Dual)
thermite-compensated = { git = "https://github.com/raygon-renderer/thermite" } # double-double precision (Compensated)
thermite-sdf = { git = "https://github.com/raygon-renderer/thermite" } # signed-distance fields
thermite-geometry = { git = "https://github.com/raygon-renderer/thermite" } # SoA Vector/Point/Ray/Bounds/Matrix
Only add the companions you use. thermite-dual, thermite-compensated, and
thermite-sdf already depend on thermite transitively, so you don't need to
list thermite separately unless you name its types directly (you usually do).
Toolchain: core Thermite works on stable Rust (MSRV 1.95, edition 2024).
You do not need nightly for normal use. The optional nightly feature unlocks
nightly-only paths (smarter const splat via core_intrinsics/const_eval_select,
wasm64 SIMD, the experimental SPIR-V backend) and, if enabled, requires a
nightly compiler (it compile_error!s otherwise). The FFI crate is the one place
that needs nightly -- see references/ffi.md.
thermite)Default features are document_registers, bitvec, avx2-f16c. The crate is
no_std by default. User-relevant flags:
| Feature | Default | What it does |
|---|---|---|
std | off | Enables std (e.g. fmt in panicking paths, num-traits/std). Turn on if you build for a std target and want those; leave off for no_std. |
bitvec | on | Enables bitvec integration for masks (dep:bitvec). |
avx2-f16c | on | Assume f16c whenever AVX2 is present (true for all AVX2 CPUs); enables half-precision conversion intrinsics in the AVX2 backend with no extra runtime check. x86 only. |
partial-ord | off | Implements PartialOrd for Vector (only meaningful when all lanes share the order). |
strict_ieee754 | off | Follow IEEE-754 as closely as possible: implies preserve_denormals + disable_fast_fma. Significantly slower; only if you need spec-exact denormals/NaN/min-max behavior. |
preserve_denormals | off | Keep denormals (required for strict IEEE-754); slower on denormal-heavy data. |
ignore_denormals | off | Flush/ignore denormals by default; slight overhead to fix them, usually cheaper than operating on them. |
disable_fast_fma | off | Use exact (but very slow) scalar libm::fma instead of the accurate emulated fast FMA on non-FMA backends. Only for bitwise-identical FMA results. |
disable_dispatch | off | Replace runtime ISA dispatch with #[inline(always)]. Bloats code and can be very slow unless everything inlines -- advanced use only. |
nightly | off | Unlocks nightly-only code paths (see toolchain note); requires a nightly compiler. |
wasm | off | Use the wasm32/wasm64 SIMD128 backend. |
neon | off | ARM NEON backend. |
avx512-tier1..4 | off | Opt into AVX-512 backend tiers (tier4 is cutting-edge; each tier implies the lower ones). |
spirv | off | Experimental SPIR-V GPU backend (implies nightly). |
A common setup for a std application that wants strict numerics:
thermite = { git = "...", features = ["std"] }. To go fully no_std, add
default-features = false and re-enable just what you need.
One generic function, run on a scalar lane, native-width SIMD, Dual (autodiff),
and Compensated (double-double) -- the whole thesis on one screen. Drop this into
a binary that depends on thermite, thermite-dual, and thermite-compensated:
use thermite::prelude::*;
use thermite::math::TranscendentalMath;
use thermite_dual::AutoDiff;
use thermite_compensated::Compensated;
// Written ONCE, over trait bounds -- no backend, lane count, or element type named.
fn gaussian<V: FloatVector + TranscendentalMath>(x: V) -> V { (-(x * x)).exp() }
type V = Vector<f64>;
fn main() {
// 1. Scalar (1-lane) backend -- no dispatch needed.
let s = gaussian(V::splat(0.5)).extract::<0>(); // 0.7788007830714049
// 2. Native-width SIMD -- runtime-dispatched to the best ISA for this CPU.
let simd = thermite::dispatch_dyn!(for<S> || -> f32 {
gaussian(f32xN::splat(0.5)).extract::<0>()
}); // ~0.77880079 (f32)
// 3. Dual<V, N>: the SAME fn now returns value AND gradient.
// d/dx e^{-x^2} = -2x e^{-x^2}.
let r = gaussian.ad([V::splat(0.5)]);
let value = r.re.extract::<0>(); // 0.7788007830714049
let dydx = r.dual[0].extract::<0>(); // -0.7788007830714049
// 4. Compensated<V>: the SAME fn carried in double-double precision.
let hi = gaussian(Compensated::<V>::new(V::splat(0.5)))
.value().extract::<0>(); // 0.7788007830714049
println!("{s} {simd} {value} {dydx} {hi}");
}
gaussian is never edited between cases -- the type you instantiate it with
decides whether you get plain SIMD, a derivative, or extra precision. (The values
in the comments were checked against this exact code.) See
references/generic-programming.md for the
mechanics and references/composite-types.md for
how Dual/Compensated plug in.
Constrain on traits, never on a concrete backend or width:
use thermite::prelude::*;
use thermite::math::TranscendentalMath; // math trait names need an explicit import
// Works on ANY backend, ANY lane count, ANY float element -- and on Dual,
// Compensated, etc. The caller picks the concrete type.
fn gaussian<V: FloatVector + TranscendentalMath>(x: V) -> V {
(-(x * x)).exp()
}
gaussian(Vector::<f64>::splat(0.5)) runs scalar; the same function under
dispatch_dyn! runs at AVX2 width; gaussian.ad([V::splat(0.5)]) returns the
value and its derivative. See
references/generic-programming.md -- the
single most important file here.
use thermite::prelude::*; // Vector, Mask, the *Vector traits, SimdSlice
use thermite::math::{TranscendentalMath, RealMath, CoreMath, SpatialMath}; // to NAME math traits in bounds
a + b a - b a * b a / b -a // NumericVector / SignedVector ops
a & b a | b a ^ b !a // BitwiseVector
a << n a >> n // BitshiftVector
let m = a.cmp_lt(b); m.select(a, b) // PartialOrdVector -> Mask, branchless select
v.sqrt() v.exp() v.sin() a.mul_adde(b, c) // FloatVector + math + estimating-FMA
v.sqrt_c(mask) a.add_c(mask, b) // masked variants: mask is the FIRST arg
You compile and test all of this as part of your own crate -- a normal
cargo build / cargo test once Thermite is in your [dependencies]. There is
no separate build step for the library.
Core usage:
*Vector bounds; associated types (V::Element, V::Mask, V::LANES, ...); how the same code runs on scalar, SIMD, and composite types; common bound recipes; pitfalls.GenericVector ... FloatVector tree, every trait, its supertraits and associated types, and which methods live where.GenericVector/NumericVector/FloatVector (construction, lanes, memory, gather/scatter, cast, interleave, reductions, FMA), plus the _c/_m/_z masked-variant system.Mask<R>, GenericMask (all/any/select/bitmask), mask casting, and zz/nz helpers.CoreMath, TranscendentalMath, SpatialMath, RealMath, FloatMath), the _p::<P>() policy system and presets, ScalarMath for bare f32/f64, FloatConsts, FMA semantics, and the algorithms module.SimdSlice: aligned / try-aligned / unaligned / streaming), alignment, and the #[dispatch] / dispatch_dyn! ISA macros.Composite & companion crates:
Dual<V, N> (autodiff) and Compensated<V> (double-double) implement the vector traits by delegating to an inner V, so generic code differentiates / error-tracks for free. Nesting (Dual<Compensated<V>>) too.thermite-special: erf, gamma, activations (gelu/swish), Lambert W, elliptic integrals, etc., all generic over any float vector.thermite-sdf: signed-distance primitives, boolean/smooth combinators, transforms, fractals; the SDF/GradientSdf/BoundedSdf traits.thermite-geometry: SoA Vector/Point/Ray/Bounds/Matrix built on the linalg vector traits.thermite-ffi: the C ABI (thermite_init, batch math functions, the Thermite vtable), header generation, and the release-ffi profile.Cross-cutting:
if const capability gating, ILP/critical-path tricks, cancellation-avoidance, scale for SPIR-V, and target_feature codegen gotchas.Simd type hierarchy, and how composites slot in. It explains why the API is shaped this way and demystifies the trickier type errors. Only the lowest level (per-ISA register impls) is contributor-only.f32/f64 do not implement FloatVector. Wrap a scalar in
Vector::<f64>::splat(x) (or Vector(x)), or use ScalarMath's scalar_-prefixed
methods (x.scalar_sin()). See references/math.md.a.add_c(mask, b), v.sqrt_c(mask),
a.add_m(src, mask, b) (merge: src then mask). Some prose docs show the old
add_c(b, mask) order -- that is wrong.as _): their
methods work, but to write <V: TranscendentalMath> you must
use thermite::math::TranscendentalMath; explicitly.mul_adde (estimating FMA), not mul_add. The non-e form drags in
libm::fma (very slow) on non-FMA backends. See references/performance.md.thermite-dual / thermite-compensated / thermite-special are publish = false
(pre-release). Compensated's FloatVector masked variants are partly todo!().
Treat them as solid-but-WIP.npx claudepluginhub raygon-renderer/thermite --plugin thermiteGenerates OxCaml code and explains extensions to OCaml: modes, stack allocation, unboxed types, kinds, SIMD, zero-alloc, comprehensions. Use with oxcaml compiler for high-performance needs.
Creates generic, type-safe C++ libraries using templates, SFINAE, concepts, and compile-time metaprogramming. Useful for library development requiring compile-time guarantees.
Performs symbolic mathematics in Python: algebraic manipulation, calculus (derivatives, integrals, limits), equation solving, matrix operations, and code generation. Use for exact symbolic results.