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
//! Thread-local autograd state: tape, GradId generator, and `no_grad` guard.
//!
//! Each thread owns its own [`Tape`] and id counter — no global locks.
//! This mirrors PyTorch's thread-local dispatch model.
use RefCell;
use crateTape;
use crateGradId;
// ---------------------------------------------------------------------------
// Thread-local context
// ---------------------------------------------------------------------------
/// Per-thread autograd bookkeeping.
thread_local!
// ---------------------------------------------------------------------------
// Public API (crate-internal)
// ---------------------------------------------------------------------------
/// Generate a fresh [`GradId`], unique within this thread.
///
/// The counter is monotonically increasing and never resets.
pub
/// Execute `f` with a mutable reference to the active [`Tape`].
///
/// If no tape exists yet, one is lazily created. Returns `None` if
/// `no_grad` is active (recording is suppressed).
pub
/// Take the tape out of the thread-local context, consuming it.
///
/// Returns `None` if no tape exists (no tracked ops were recorded).
/// After this call, the next tracked op will create a fresh tape.
pub
/// Returns `true` if tape recording is currently suppressed by a
/// [`NoGradGuard`].
pub
// ---------------------------------------------------------------------------
// NoGradGuard — RAII suppression of tape recording
// ---------------------------------------------------------------------------
/// RAII guard that suppresses tape recording for the duration of its
/// lifetime.
///
/// Supports nesting: creating a second `NoGradGuard` while one is already
/// active increments the depth counter. Recording resumes only when all
/// guards have been dropped (depth returns to 0).
///
/// # Example
///
/// ```ignore
/// let _guard = no_grad();
/// let y = x.add(&x); // not recorded on the tape
/// // _guard drops here → recording resumes
/// ```
;
/// Create a [`NoGradGuard`] that suppresses autograd tape recording.
///
/// The guard is active until it is dropped. Nesting is supported.