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
//! Masked-tail coverage for the cosine kernels.
//!
//! Every cosine kernel processes whole blocks and then a remainder: the
//! AVX-512 2-acc consumes 32 f32 per iteration, the 4-acc 64, the 8-acc 128.
//! A dimension that is an exact multiple of the stride never enters the tail
//! at all — `end_main == end_ptr` and the masked-load branch is dead. A bug
//! that drops or double-counts one tail element silently corrupts every
//! distance at that dimension.
//!
//! `cosine_fused_tests.rs` sizes are `[16, 32, 64, 128, 256, 384, 512, 768,
//! 1024]`. Every one above 512 is an exact multiple of its kernel's stride
//! (512 and 768 of 64; 1024 of 128), so neither the 4-acc nor the 8-acc tail
//! ran. `hamming_jaccard_tests.rs` already has the right shape for this — its
//! `THRESHOLD_DIMS` carries 1023/1024/1025 — and cosine had no equivalent.
//!
//! Two further reasons the gap was invisible:
//!
//! - `internal_bench_tests.rs` does test 767/768/769 against a scalar
//! reference at 1e-5, which would have caught a 4-acc tail bug. It is gated
//! behind the `internal-bench` feature, which no CI job enables, so it never
//! runs. (It also stops at 1536 = 12 x 128, so it never reached the 8-acc
//! tail either.)
//! - A `cosine_similarity_native(&a, &a)` assertion cannot detect a dropped
//! element *at any tolerance*: dropping element k removes `a_k^2` from the
//! dot product and from both norms, and `(S - a_k^2) / (S - a_k^2)` is still
//! 1.0. Identical-vector tests are not tail coverage. See
//! [`self_similarity_cannot_detect_a_dropped_tail_element`].
//!
//! The reference here is [`scalar::cosine_scalar`] — the same formula without
//! the vectorization, which is what the kernels are supposed to reproduce.
use ;
/// Tolerance between the dispatched kernel and the scalar reference.
///
/// The same 1e-5 `internal_bench_tests.rs` already holds these kernels to at
/// dims 769 and 1536. It is tight enough to see a dropped tail element by a
/// wide margin: at dim 1025 dropping one element moves the cosine by ~1.7e-4
/// median, an order of magnitude above this bound. `cosine_fused_tests.rs`
/// uses 5e-3, which is looser than the effect it would need to detect.
const TOLERANCE: f32 = 1e-5;
/// Dimensions chosen so that every kernel's remainder branch actually runs.
///
/// | dim | kernel | why |
/// |---|---|---|
/// | 17, 49 | AVX-512 2-acc | `rem0 = 16`, second masked load at `base + 16` |
/// | 100 | AVX-512 2-acc | `rem0 = 4`, partial mask, `rem1 = 0` |
/// | 511 | AVX-512 2-acc | widest 2-acc remainder |
/// | 513 | AVX-512 4-acc | main loop to 512, masked tail of 1 |
/// | 575 | AVX-512 4-acc | three 16-chunks then a 15-wide mask |
/// | 769 | AVX-512 4-acc | main loop to 768, masked tail of 1 |
/// | 1025 | AVX-512 8-acc | main loop to 1024, masked tail of 1 |
/// | 1151 | AVX-512 8-acc | seven 16-chunks then a 15-wide mask |
/// | 1279 | AVX-512 8-acc | 1152 main + 127 remainder |
///
/// The exact multiples (512, 768, 1024, 1536, 2048) are kept as controls: they
/// skip the tail entirely, so a failure there is a main-loop bug, not a tail
/// bug, and the pair localizes which one broke.
const TAIL_DIMS: & = &;
/// Distinct, non-degenerate vectors.
///
/// Deliberately not `a == b`, not orthogonal, and not mostly zero: each of
/// those makes the cosine insensitive to a dropped element regardless of
/// tolerance. Irrational-ish phases keep every element contributing.
/// The dispatched kernel must equal the scalar reference at every dimension
/// that reaches a masked tail.
/// The tail must carry its elements, not silently drop them.
///
/// Comparing dimension `n` against dimension `n - 1` on the same prefix data
/// isolates the tail: if the kernel skipped its last element the two would
/// agree, and they must not, because the extra element changes the cosine.
/// This catches a dropped tail element even if the scalar reference were
/// wrong in the same way.
/// Why identical-vector assertions are not tail coverage.
///
/// This is a demonstration, not a defect: for `a == b` the kernel computes
/// `dot = norm_a_sq = norm_b_sq = S`, so omitting element k gives
/// `(S - a_k^2) / sqrt((S - a_k^2)^2)` — still 1.0. Truncating the vector
/// stands in for the omission: a `cosine(&a, &a)` assertion passes at BOTH
/// lengths, so it cannot tell them apart and is blind to a dropped tail
/// element at any tolerance. That is why the tests above use distinct
/// vectors.
///
/// The two results are not bit-identical — `S / sqrt(S * S)` lands within an
/// ulp or two of 1.0 and the ulp differs with the accumulation order — so the
/// point is made the way a real test would make it: both satisfy the same
/// `≈ 1.0` assertion.
/// The tolerance the fused-cosine suite uses is looser than what it must catch.
///
/// `cosine_fused_tests.rs` compares against a scalar reference at `5e-3`.
/// Dropping one element at these dimensions moves the cosine by roughly
/// `1/dim`, so at dim 1025 the effect is ~1.7e-4 — two orders of magnitude
/// *below* that tolerance and therefore invisible. This pins the arithmetic
/// so the constant cannot be loosened back without the reason being restated.