1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//! # `xad-rs` — Automatic Differentiation for Rust
//!
//! A fast, ergonomic, type-safe automatic differentiation library for
//! Rust. `xad-rs` is an unofficial port of the C++
//! [XAD](https://github.com/auto-differentiation/xad) library by Xcelerit,
//! and ships all four of the canonical AD flavours in a single crate.
//!
//! Automatic differentiation computes derivatives of arbitrary programs
//! **exactly**, to machine precision, without finite-difference error or
//! symbolic manipulation. `xad-rs` is suitable for quantitative finance,
//! optimisation, machine learning, computational physics, and any setting
//! where gradients or Hessians of non-trivial numerical code are needed.
//!
//! ## Picking a mode
//!
//! | Type | Mode | Order | Seeds | Use when |
//! |---|---|---|---|---|
//! | [`FReal<T>`](freal::FReal) | Forward (tangent) | 1st | 1 direction | few inputs, many outputs |
//! | [`Dual`] | Forward, multi-variable | 1st | `n` in one pass | full gradient in one forward sweep |
//! | [`Dual2<T>`](dual2::Dual2) | Forward, second-order | 1st + 2nd | 1 direction | diagonal Hessian / own-gamma |
//! | [`AReal<T>`](areal::AReal) + [`Tape`] | Reverse (adjoint) | 1st | 1 adjoint seed | many inputs, few outputs (gradients of scalar losses) |
//!
//! Reverse mode is the right choice for `f: Rⁿ → R` with `n` larger than a
//! handful (the break-even vs. forward mode sits around `n ≈ 4` in this
//! crate after the April 2026 perf refactor — see `CHANGELOG.md`). Forward
//! mode is the right choice when there are few inputs (1–3) or many
//! outputs relative to inputs.
//!
//! ## Quick start — reverse mode gradient
//!
//! ```
//! use xad_rs::areal::AReal;
//! use xad_rs::tape::Tape;
//! use xad_rs::math;
//!
//! let mut tape = Tape::<f64>::new(true);
//! tape.activate();
//!
//! // f(x, y) = x² · y + sin(x), at (x, y) = (3, 4)
//! let mut x = AReal::new(3.0);
//! let mut y = AReal::new(4.0);
//! AReal::register_input(std::slice::from_mut(&mut x), &mut tape);
//! AReal::register_input(std::slice::from_mut(&mut y), &mut tape);
//!
//! let mut f = &(&x * &x) * &y + math::ad::sin(&x);
//! AReal::register_output(std::slice::from_mut(&mut f), &mut tape);
//! f.set_adjoint(&mut tape, 1.0);
//! tape.compute_adjoints();
//!
//! // ∂f/∂x = 2xy + cos(x) ≈ 23.010
//! // ∂f/∂y = x² = 9.0
//! let dfdx = x.adjoint(&tape);
//! let dfdy = y.adjoint(&tape);
//! assert!((dfdx - (2.0 * 3.0 * 4.0 + 3.0_f64.cos())).abs() < 1e-12);
//! assert!((dfdy - 9.0).abs() < 1e-12);
//! # xad_rs::tape::Tape::<f64>::deactivate_all();
//! ```
//!
//! ## Quick start — forward mode (multi-variable)
//!
//! Seed all inputs in a single `n`-dimensional [`Dual`] and one forward
//! pass yields the whole gradient:
//!
//! ```
//! use xad_rs::dual::Dual;
//!
//! // f(x, y) = x² · y, at (x, y) = (3, 4)
//! let n = 2;
//! let x = Dual::variable(3.0, 0, n);
//! let y = Dual::variable(4.0, 1, n);
//! let f = &(&x * &x) * &y;
//! assert_eq!(f.real(), 36.0);
//! assert_eq!(f.partial(0), 24.0); // ∂f/∂x = 2xy
//! assert_eq!(f.partial(1), 9.0); // ∂f/∂y = x²
//! ```
//!
//! ## Second-order derivatives
//!
//! ```
//! use xad_rs::dual2::Dual2;
//!
//! // f(x) = x³, at x = 2
//! let x: Dual2<f64> = Dual2::variable(2.0);
//! let y = x * x * x;
//! assert_eq!(y.value(), 8.0); // f(x)
//! assert_eq!(y.first_derivative(), 12.0); // 3x²
//! assert_eq!(y.second_derivative(),12.0); // 6x
//! ```
//!
//! ## Crate naming
//!
//! The crate name on crates.io is **`xad-rs`**; the library target is
//! **`xad_rs`** (Cargo rewrites the hyphen to an underscore), which is
//! what you write in `use` statements:
//!
//! ```ignore
//! use xad_rs::areal::AReal;
//! use xad_rs::tape::Tape;
//! ```
//!
//! ## Modules
//!
//! - [`areal`] — reverse-mode active scalar, records on a [`Tape`]
//! - [`dual`] — forward-mode multi-variable dual number
//! - [`dual2`] — forward-mode second-order dual number
//! - [`freal`] — forward-mode single-variable active scalar
//! - [`math`] — AD-aware transcendental functions (`sin`, `exp`, `erf`, …)
//! for every active type, in `math::ad::*` and `math::fwd::*` submodules
//! - [`tape`] — tape data structure and active-tape thread-local slot
//! - [`jacobian`] — convenience `compute_jacobian_rev` / `compute_jacobian_fwd`
//! - [`hessian`] — convenience `compute_hessian` (scalar-valued functions)
//! - [`traits`] — the [`Scalar`] trait bound
//!
//! The [`adj`], [`adjf`], [`fwd`], and [`fwdf`] submodules re-export the
//! C++ XAD-style type aliases (`ActiveType`, `PassiveType`, `TapeType`)
//! to make porting C++ XAD code mechanical.
//!
//! ## Performance
//!
//! See [`CHANGELOG.md`](https://github.com/sercanatalik/xad-rs/blob/master/CHANGELOG.md)
//! for the full write-up of the 8-stage April 2026 perf refactor. Selected
//! numbers on an Apple M4 Pro (Rust 1.92 release):
//!
//! | Workload | Time | Speedup vs. pre-refactor |
//! |---|---:|---:|
//! | Swap pricer, 30-input reverse mode | 1.86 µs | 4.36× |
//! | FX option, 6-input reverse mode | 682 ns | 2.49× |
//! | FX option, 6-input forward `Dual` | 423 ns | 2.16× |
//! | FX option, `Dual2` spot gamma | 23 ns | 1.57× |
//!
//! Reproducible with `cargo bench`. See `benches/operators.rs` and
//! `benches/pricing.rs` for the Criterion harness.
//!
//! ## License
//!
//! `xad-rs` is licensed under the **GNU Affero General Public License
//! v3.0 or later**, matching upstream XAD. See `LICENSE.md` for the full
//! text.
/// String-keyed labeled layer over the existing AD modes.
///
/// Available only with the `labeled` feature enabled.
/// Dense multi-variable second-order forward-mode AD via `Dual2Vec`.
///
/// Available only with the `dual2-vec` feature enabled.
pub use AReal;
pub use Dual;
pub use Dual2;
pub use FReal;
pub use ;
pub use Scalar;
pub use ;
pub use ;
pub use ;
pub use Dual2Vec;
/// Convenience type aliases matching the C++ XAD interface