simba icon indicating copy to clipboard operation
simba copied to clipboard

`SimdPartialOrd::simd_min()` and `simd_max()` aren't commutative when values aren't comparable

Open arscisca opened this issue 2 years ago • 1 comments

The base assumption is that min(a, b) == min(b, a), and same for max.

This is not true when values are not comparable (= when PartialOrd::partial_cmp would return None) because, in that case, these two methods always return the right hand side.

In other words, a.simd_min(b) == b but b.simd_min(a) == a when a.partial_cmp(b) == None.

This happens, for instance, when comparing a regular f32 and f32::NAN:

let number = 1.0f32;
let nan = f32::NAN;
println!("{}", number.simd_min(nan)); // Prints "NaN"
println!("{}", nan.simd_min(number)); // Prints "1"

This happens because the current implementation of simd_min is the following:

fn simd_min(self, other: Self) -> Self {
    if self <= other {
        self
    } else {
        other
    }
}

and a <= (or any syntax-sugared comparison in general) between two instances PartialOrd where a.partial_ord(&b) returns None is evaluated to false.

arscisca avatar Dec 15 '23 22:12 arscisca

On a side note, all the other comparison methods under SimdPartialOrd will return a bool regardless of whether the values are actually comparable or not. I imagine this is either SIMD requirement or a convenience choice, but at this point isn't the trait behaving more like a SimdOrd which is implemented for PartialOrd types like f32 and f64 for convenience?

arscisca avatar Dec 15 '23 22:12 arscisca