xad-rs
Exact automatic differentiation for Rust. Forward and reverse mode, first and second order, with name-keyed gradient readback for quant-finance workloads. No finite-difference error, no symbolic manipulation — just the chain rule, applied to your program as it runs.
Unofficial Rust port of the C++ XAD library. Not affiliated with the upstream project.
Documentation
- Theory — derivations and decision-tree guidance:
docs/README.md. - API — generated rustdoc: docs.rs/xad-rs.
- Examples — runnable, cross-checked against analytic answers:
examples/.
[]
= "0.8"
MSRV: Rust 1.85 (edition 2024).
How it works
Write your numerical code once against the trait Real.
Instantiate it at the call site against the concrete mode that matches your
problem shape — f64 for no-AD, Jet1 for one directional derivative, Jet1Vec
for a full gradient in one forward pass, AReal + Tape for a gradient over many
inputs, Jet2/Jet2Vec for second order.
use *;
let v_passive = quadratic; // primal, no AD
let v_jet1 = quadratic; // forward, 1st order
let v_jet2 = quadratic; // forward, 1st + 2nd
// Reverse mode: build inside an active Tape (see below).
Pick a mode
| Your problem | Mode | Read more |
|---|---|---|
| Just the value, no derivatives | f64 |
01 — AD as a discipline |
| One input direction, any number of outputs | Jet1<T> |
02 — Forward mode & dual numbers |
| Full gradient in one forward pass (n small) | Jet1Vec |
02 — Forward mode & dual numbers |
| Full gradient, n ≫ 4 inputs, scalar output | Tape + AReal<T> |
03 — Reverse mode & taped adjoints |
| Gamma / diagonal Hessian along one direction | Jet2<T> |
04 — Second-order & k-jets |
| Full n × n Hessian, n ≲ 50 | Jet2Vec via compute_full_hessian |
04 — Second-order & k-jets |
| Greeks by name (delta, vega, ...) instead of by index | Any mode's Named* variant |
05 — Named variables & quant use cases |
Reverse mode breaks even with forward around n ≈ 4 inputs. For n ≫ 4 (e.g. a 30-input swap pricer), reverse is dramatically faster.
Real is implemented for f64, AReal<f64>, Jet1<f64>, and Jet2<f64>.
Jet1Vec / Jet2Vec lack the impl because the trait's From<f64> requires
knowing the tangent length; use them directly when you want a full gradient or
Hessian in one pass.
By mode — quick recipes
Reverse (gradient via tape)
use ;
let mut tape = new;
tape.activate;
let mut x = new;
let mut y = new;
register_input;
register_input;
// f(x, y) = x^2 * y + sin(x)
let mut f = & * &y + sin;
register_output;
f.set_adjoint;
tape.compute_adjoints;
assert!;
assert_eq!;
Forward (full gradient in one pass)
use Jet1Vec;
let = ;
let f = & * &y; // x^2 * y
assert_eq!; // df/dx = 2xy
assert_eq!; // df/dy = x^2
Second order (gamma along one direction)
use Jet2;
let x = variable;
let y = x * x * x; // x^3
assert_eq!; // 3x^2
assert_eq!; // 6x
For the full dense Hessian in one pass, use Jet2Vec via compute_full_hessian
(see examples/hessian.rs and the chapter 04 cost
model).
Named (greeks by name)
Forward, declare-and-scope:
use ;
let mut ft = new;
let spot_h = ft.declare_jet1vec;
let strike_h = ft.declare_jet1vec;
let scope: = ft.into_scope;
let spot = scope.jet1vec;
let strike = scope.jet1vec;
let ratio = spot / strike;
assert!;
Reverse, with a name-keyed gradient as an IndexMap:
use NamedTape;
let mut tape = new;
let x = tape.input;
let y = tape.input;
let _registry = tape.freeze;
let f = & * &y + x.sin;
let grad = tape.gradient;
assert!;
assert!;
Composite Jacobian / Hessian helpers
use ;
// f: R^2 -> R^2, f(x, y) = [x*y, x + y]
let _jac = compute_jacobian_rev;
// g: R^2 -> R, g(x, y) = x^2 * y + y^3
let _hess = compute_hessian;
For the exact Hessian (machine precision, one forward pass instead of n reverse
sweeps), reach for compute_full_hessian — it returns a NamedHessian with the
value, gradient, and full ndarray::Array2<f64> Hessian.
Examples
Run with cargo run --release --example <name>.
| Example | What it demonstrates |
|---|---|
swap_pricer.rs |
30-input IRS DV01 and gamma via reverse, Jet1Vec, and Jet2 |
fx_option.rs |
Garman–Kohlhagen FX option greeks, three AD modes cross-checked against analytic |
fixed_rate_bond.rs |
YTM, duration, convexity |
jacobian.rs |
4×4 Jacobian via reverse mode |
hessian.rs |
4×4 Hessian via compute_full_hessian with analytic cross-check |
adjoint_first_order.rs |
Full 4-input gradient in one reverse sweep |
fwd_adj_second_order.rs |
Forward-over-adjoint: gradient + Hessian row via Jet2Vec |
License
AGPL-3.0-or-later, matching the upstream XAD project. See LICENSE.md.
Acknowledgements
- The C++ XAD library — architectural inspiration and source of the financial examples.
- QuantLibAAD — the XAD-instrumented QuantLib build; reference for the AAD-on-quant-finance patterns the financial examples in this crate are modelled after.
num-traits,indexmap, andndarrayfor the underlying primitives.