Skip to content

Commit 5de4c30

Browse files
Merge pull request #345 from marius-bughiu/chore/code-review/argsort-alias-doc
docs(RadixSort): scope ArgSort's aliasing exception to the overload that throws it
2 parents 89026ce + 1fc280c commit 5de4c30

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ All notable changes to Celerity are documented here. This project follows [Keep
2828
### Fixed
2929

3030
- `PartialSort.TopK` now throws `ArgumentException` when its `destination` overlaps its `source`, instead of silently returning a wrong answer and writing to the source it documents as untouched. Disjoint slices of one array are still accepted, matching `RadixSort` and `CountingSort`.
31+
- Corrected `RadixSort.ArgSort` XML documentation: only its `ReadOnlySpan<int>` overload rejects `indices` that shares storage with `keys`. Documentation only.
3132
- Eight documentation links pointed at anchors that do not exist: seven `CeleritySet` / `SwissSet` references in `docs/api/collections.md` and one in `CHANGELOG.md`. GitHub deletes `<`, `>` and `,` from a heading without substituting a separator, so `CeleritySet&lt;T, THasher&gt;` anchors as `#celeritysett-thasher`, not the `#celerityset-t-thasher` everyone writes. Closes [#339](https://github.com/marius-bughiu/Celerity/issues/339).
3233

3334
## [2.5.0] - 2026-08-02

src/Celerity.Sorting/RadixSort.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,23 @@ public static void SortWithScratch<TValue>(Span<uint> keys, Span<TValue> values,
154154
/// </summary>
155155
/// <param name="keys">The keys to rank. Not modified.</param>
156156
/// <param name="indices">Receives <c>keys.Length</c> indices into <paramref name="keys"/>, in ascending key order.</param>
157-
/// <exception cref="ArgumentException"><paramref name="indices"/> is shorter than <paramref name="keys"/>, or shares storage with it.</exception>
157+
/// <exception cref="ArgumentException">
158+
/// <paramref name="indices"/> is shorter than <paramref name="keys"/>. For
159+
/// <see cref="ArgSort(ReadOnlySpan{int}, Span{int})"/>, it is also thrown when
160+
/// <paramref name="indices"/> shares storage with <paramref name="keys"/>. See remarks for
161+
/// cross-type aliases.
162+
/// </exception>
158163
/// <remarks>
164+
/// Aliasing is checked only by <see cref="ArgSort(ReadOnlySpan{int}, Span{int})"/> because its
165+
/// <paramref name="keys"/> and <paramref name="indices"/> have the same element type. For the
166+
/// other overloads, making their differently typed spans overlap requires reinterpreting one
167+
/// buffer as another type; that is out-of-contract rather than checked.
168+
/// <para>
159169
/// The point of an argsort is to avoid moving a wide payload: rank once, then gather. This form
160170
/// rents three buffers, so a hot loop that already owns its scratch should copy the keys itself
161171
/// and call <see cref="SortWithScratch{TValue}(Span{uint}, Span{TValue}, Span{uint}, Span{TValue})"/> with
162172
/// an identity index array as the payload — that is exactly what this does.
173+
/// </para>
163174
/// </remarks>
164175
public static void ArgSort(ReadOnlySpan<uint> keys, Span<int> indices)
165176
{

0 commit comments

Comments
 (0)