dace-rs
Pure Rust implementation of DACE, the Differential Algebra Computational Toolbox.
dace-rs computes with truncated multivariate Taylor polynomials ("differential algebra"): it propagates high-order expansions of arbitrary multivariate functions through arithmetic, elementary-function composition, and full polynomial map inversion, with a configurable cut-off epsilon and truncation order. It is a full rewrite of DACE 2.1 in safe Rust — no C toolchain at build time, no unsafe code in the computation kernels.
English | 简体中文
Contents
Why dace-rs
The existing dace crate is a C-binding wrapper around the upstream library: it requires a C toolchain and links the C core. dace-rs is an independent pure-Rust implementation of the same algorithms and numerics, verified coefficient-for-coefficient against the C reference (see Parity Methodology). It adds Rust-native ergonomics:
- operator traits (
Add/Sub/Mul/Div/Neg+ assignments) forDa × Da,Da × f64,f64 × Da; - values survive re-initialization (each
Dakeeps its context; C purges everything); - recoverable failures return
Result, domain misuse panics with the C error code, informational degradation goes through thelogcrate — no sticky error state, noexit(1).
Quickstart
use Da;
See examples/quickstart.rs for a map-iteration example, and the crate documentation for the full API.
Platform Support
All dependencies are pure Rust; there is no build.rs and no C toolchain requirement.
| Target | CI |
|---|---|
| Linux x86-64 | ubuntu-latest |
| Linux aarch64 | ubuntu-24.04-arm |
| Windows x86-64 | windows-latest |
| Windows aarch64 | windows-11-arm |
Arithmetic kernels use a fixed accumulation order and default floating-point settings (no fast-math, no FMA contraction), so results are bit-identical across the four platforms; only scalar transcendentals (f64::sin, ...) may differ by a few ulps between libm implementations.
API Map (C++ → Rust)
| DACE C++ | dace-rs |
|---|---|
DA::DA(var), DA::identity |
Da::variable / [Da::identity] |
DA::cons, DA::linear, DA::gradient |
Da::cons / [Da::linear] / [Da::gradient] |
DA::getCoefficient, setCoefficient |
[Da::get_coefficient] / [Da::set_coefficient] |
DA::deriv, DA::integ, DA::trim |
[Da::deriv] / [Da::integ] / [Da::trim] |
exp, log, sin, tan, asin, ... |
[dace_rs::exp] etc. (free fns) and Da methods |
BesselJFunction etc. |
[dace_rs::bessel_j] etc. |
GammaFunction, PsiFunction |
[dace_rs::gamma] / [dace_rs::psi] |
DA::norm, orderNorm, estimNorm, bound, convRadius |
[Da::norm] etc. |
DA::compile, compiledDA::eval |
Da::compile / CompiledDa::eval / [CompiledDa::eval_da] |
DA::plug, DA::eval |
[Da::plug] / [Da::eval] / [Da::eval_da] |
DA::replaceVariable, scaleVariable, translateVariable |
[Da::replace_variable] etc. |
DA::read/write (blob), operator>>/<< |
[Da::to_blob]/[Da::from_blob], [Display]/[FromStr] |
DASimpleFormatter |
SimpleFormat presets and format_da |
AlgebraicVector<DA>::invert |
DaVector::invert |
Not ported (upstream experimental/off by default): AlgebraicMatrix, dacecompat aliases, the MATLAB interface.
Parity Methodology
The C library has no test suite, so dace-rs is verified against the C reference directly:
- Goldens:
dev/golden/gen.shbuilds the C library and runs a fixed case table (dev/golden/main.c) covering arithmetic, all elementary and special functions, calculus, norms, evaluation, and blob export at(6,3),(20,6), and(6,2)contexts with several constant-term choices. The committedtests/golden/cases.txtis replayed bytests/parity.rsin CI (no C toolchain needed); coefficients agree within rtol1e-10(arithmetic within1e-13, verified bit-identical in many cases). - Bit-level checks during development: the monomial encoding tables, the multiply/inverse kernels, the text format, and the elementary-function layer were compared byte-for-byte against the C library on this machine.
Two upstream C bugs are deliberately not reproduced; both divergences are documented in the rustdoc of the affected functions:
daceReplaceVariableindexes its exponent array with 1-based variable numbers (documented semantics say 1-based replacement; implemented is effectivelyfrom+1 → val·(to+1), a silent no-op forfrom == nvmax). dace-rs implements the documented semantics.dacePowerwith negative powers calls the multiplicative inverse on an aliased result, and the Newton iteration is not aliasing safe; C returns wrong coefficients (C'spow(A,-2)disagrees with C's ownminv(sqr(A))). dace-rs returns the correct value.
License
Apache-2.0. dace-rs is a derivative work of DACE (Copyright 2016 Politecnico di Milano and contributors; Copyright 2014 Dinamica Srl). See LICENSE, NOTICE, and THIRD_PARTY_NOTICES.md.