strided_basic/nan_select.rs
1//! NaN-propagating elementwise selects shared by the ordinary binary kernels
2//! and the fused interpreter.
3//!
4//! The ordinary erased binary maximum/minimum
5//! ([`crate::erased`]-adjacent `ErasedZipOp::Maximum`/`Minimum` in
6//! `strided-kernel`) and the fused `FusedOp::Maximum`/`Minimum` must agree on
7//! IEEE value propagation. Both call these helpers so the two definitions
8//! cannot drift. The exact contract, pinned by
9//! `strided-kernel/tests/erased_elementwise_kernels.rs` and the fused
10//! differential tests:
11//!
12//! - any NaN operand yields the canonical NaN of the dtype;
13//! - ties, including `+0.0` against `-0.0`, return `lhs`.
14//!
15//! The select is written without a short-circuit `||` so a chunk loop lowers
16//! to compare-and-blend rather than a data-dependent branch.
17
18/// NaN-propagating elementwise maximum for real floats.
19///
20/// ```
21/// use strided_basic::nan_propagating_maximum;
22/// assert!(nan_propagating_maximum(f64::NAN, 1.0).is_nan());
23/// assert!(nan_propagating_maximum(1.0f32, f32::NAN).is_nan());
24/// // Ties keep `lhs`.
25/// assert_eq!(nan_propagating_maximum(0.0f64, -0.0).to_bits(), 0.0f64.to_bits());
26/// ```
27#[inline(always)]
28pub fn nan_propagating_maximum<T: num_traits::Float>(lhs: T, rhs: T) -> T {
29 let picked = if lhs >= rhs { lhs } else { rhs };
30 if lhs.is_nan() | rhs.is_nan() {
31 T::nan()
32 } else {
33 picked
34 }
35}
36
37/// NaN-propagating elementwise minimum for real floats.
38///
39/// ```
40/// use strided_basic::nan_propagating_minimum;
41/// assert!(nan_propagating_minimum(f64::NAN, 1.0).is_nan());
42/// assert!(nan_propagating_minimum(1.0f32, f32::NAN).is_nan());
43/// // Ties keep `lhs`.
44/// assert_eq!(nan_propagating_minimum(-0.0f64, 0.0).to_bits(), (-0.0f64).to_bits());
45/// ```
46#[inline(always)]
47pub fn nan_propagating_minimum<T: num_traits::Float>(lhs: T, rhs: T) -> T {
48 let picked = if lhs <= rhs { lhs } else { rhs };
49 if lhs.is_nan() | rhs.is_nan() {
50 T::nan()
51 } else {
52 picked
53 }
54}