pub trait SortOrder {
const IS_ASCENDING: bool;
// Required methods
fn first<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>;
fn last<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>;
fn vector_first<V: NumericVector>(a: V, b: V) -> V;
fn vector_last<V: NumericVector>(a: V, b: V) -> V;
// Provided methods
fn last_value<V: NumericVector>() -> V { ... }
fn first_value<V: NumericVector>() -> V { ... }
}Expand description
The direction a comparator points, as a compile-time parameter.
Implementors are zero-sized markers (Ascending, Descending) selected
with turbofish - R::sort_by::<Descending>(v). Both methods must be a
consistent pair: first and last are the two halves of one
compare-exchange, so for any a, b the multiset {first(a,b), last(a,b)}
must equal {a, b}, and first(a,b) must not come after last(a,b) under
the order. Violating that does not just misorder - it duplicates and drops
values, because a network never re-reads what it overwrote.
Deliberately only these two methods. They are the whole of what a network
needs; the padding sentinels (a value that sorts after everything, for
filling a partial register) and the members a partition-based sort would want
(compare, prev_value) get added when something calls them.
Required Associated Constants§
Sourceconst IS_ASCENDING: bool
const IS_ASCENDING: bool
Whether this order is smallest-first.
Must agree with first and last - it
is the same fact stated a second way, and nothing checks that the two
statements match.
It exists because the scalar fallback
(sort_any, used
by any register with no network for its lane count) sorts elements
through PartialOrd, where the register-level first/last cannot
reach. Rather than widen this trait with a scalar comparator pair used by
one slow path, that path sorts ascending and reverses on this flag. The
cost is one permute on a body that is already quadratic.
Required Methods§
Sourcefn first<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>
fn first<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>
The value that belongs at the lower index of a comparator pair.
Named for the position rather than for min, because the two stop
coinciding as soon as the order is anything but ascending.
Sourcefn last<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>
fn last<R: NumericRegister>(a: Storage<R>, b: Storage<R>) -> Storage<R>
The value that belongs at the higher index of a comparator pair.
Sourcefn vector_first<V: NumericVector>(a: V, b: V) -> V
fn vector_first<V: NumericVector>(a: V, b: V) -> V
first at the vector layer.
A second pair rather than one generic over both layers because
NumericVector has no associated register type to route through (only
its float/signed/unsigned sub-traits do), and Storage<R> is a
projection, so no helper trait can cover both. Keeping the pairs on one
trait is what stops a marker from meaning ascending at one layer and
descending at the other.
Sourcefn vector_last<V: NumericVector>(a: V, b: V) -> V
fn vector_last<V: NumericVector>(a: V, b: V) -> V
last at the vector layer.
Provided Methods§
Sourcefn last_value<V: NumericVector>() -> V
fn last_value<V: NumericVector>() -> V
A value that sorts after every real input under this order - the padding sentinel.
Filling the unused lanes of a partial register with this lets a fixed
network sort a run shorter than the register: the sentinels sort to the
tail and are never stored back. Ascending wants the order maximum
(+inf for floats, not MAX); descending wants the order minimum, which
is why this lives on the order rather than on the register.
NaN is not covered. No value sorts past NaN because NaN is unordered,
so a float sort must remove NaN before the network runs - see
thermite_sort. Padding with +inf alongside a NaN in the data gives a
backend-dependent result, since min/max NaN semantics legitimately
differ across ISAs (the differential suite carries a Tol::ExactOrNan
for precisely this).
Sourcefn first_value<V: NumericVector>() -> V
fn first_value<V: NumericVector>() -> V
A value that sorts before every real input under this order. The
mirror of last_value; same NaN caveat.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".