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
// ============================================================================
// Additive attention mask builder (plan 01-01)
// Contract: setfit-encoder-conformance-v1, equation `additive_attention_mask`
// ============================================================================
/// Additive penalty applied to padded key positions.
///
/// A large **finite** negative constant, deliberately not `f32::MIN` and not
/// `f32::NEG_INFINITY`. All-padding rows are rejected before this value is ever
/// used, so every softmax row keeps at least one valid key; `exp(-1e9 - max)`
/// then underflows to exactly `0.0` in f32, giving parity with torch on valid
/// positions without any `-inf` or `NaN` arithmetic to reason about.
pub const NEG_MASK: f32 = -1e9;
/// Build the `[B, 1, 1, S]` additive attention mask for a `[B, S]` binary mask.
///
/// Kept positions get `0.0`; padded positions get [`NEG_MASK`]. The rank-4
/// shape is what lets the mask broadcast over `[B, heads, T, S]` attention
/// scores.
///
/// # This op is deliberately a CONSTANT
///
/// It takes no differentiable input, so the result has `requires_grad == false`
/// and records **no** `grad_fn`. That is not an oversight and not a severed
/// graph: `contracts/setfit-encoder-conformance-v1.yaml` carves this equation
/// out of the general graph-connectivity invariant for exactly this reason.
///
/// The graph-connectivity guarantee for masking lives on `apply_additive_mask`
/// (plan 01-09) — the op that ADDS this constant to the attention scores. That
/// is where a severed edge would actually cost gradient, and that is where the
/// contract puts the obligation.
///
/// # Errors
///
/// * [`OpError::ZeroDimension`] — `batch` or `seq` is 0.
/// * [`OpError::ShapeOverflow`] — `batch * seq` overflows `usize`.
/// * [`OpError::LengthMismatch`] — `mask.len()` is not `batch * seq`.
/// * [`OpError::NonBinaryMaskValue`] — an entry is neither `0` nor `1`. A `2` is
/// never silently treated as "keep".
/// * [`OpError::AllPaddingRow`] — a row has no kept position, which would make
/// the whole softmax row `-1e9` and its denominator meaningless.