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
//! Reverse-mode automatic differentiation via an Adept-style tape.
//!
//! [`Reverse<F>`] is a lightweight variable (12 bytes for f64, `Copy`) that records
//! operations on a thread-local tape. Best suited for functions with many inputs and
//! few outputs, such as computing gradients.
use std::fmt::{self, Display};
use crate::tape::CONSTANT;
use crate::Float;
/// Reverse-mode AD variable.
///
/// Just a value and a tape index — 12 bytes for `f64`. `Copy` because the
/// tape lives in a thread-local, not inside this struct.
#[derive(Clone, Copy, Debug)]
pub struct Reverse<F: Float> {
pub(crate) value: F,
pub(crate) index: u32,
}
impl<F: Float> Reverse<F> {
/// Create a constant (not tracked on tape).
#[inline]
pub fn constant(value: F) -> Self {
Reverse {
value,
index: CONSTANT,
}
}
/// Create a reverse variable from a tape allocation.
/// Typically only used internally by the API layer and tests.
#[inline]
pub fn from_tape(value: F, index: u32) -> Self {
Reverse { value, index }
}
/// Get the tape index (for advanced usage / testing).
#[inline]
pub fn index(&self) -> u32 {
self.index
}
}
impl<F: Float> Display for Reverse<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
impl<F: Float> Default for Reverse<F> {
fn default() -> Self {
Reverse::constant(F::zero())
}
}