rust-num / num-traits

Numeric traits for generic mathematics in Rust
Apache License 2.0
732 stars 135 forks source link

Shouldn't abs_sub work for all Ord + Sub + Zero? #157

Closed therealbnut closed 4 years ago

therealbnut commented 4 years ago

Hey, I wanted to take the absolute difference between two numbers, but I couldn't with num_traits. It seems like you should be able to. Is there any reason why not?

fn abs_sub<T: Ord + Sub + Zero>(lhs: &T, rhs: &T) -> T {
  if lhs < rhs {
    rhs - lhs
  } else {
    lhs - rhs
  }
}
cuviper commented 4 years ago

You could write something generic like that, although note that Ord will exclude all floating point. For the function you wrote, you'd need where T: PartialOrd, for<'a> &'a T: Sub<&'b T, Output = T>.

But for num-traits, that helper is specifically associated with Signed, a common convention throughout the crate. It also doesn't work quite how you're expecting:

Returns zero if x is less than or equal to y, otherwise the difference between x and y is returned.

This corresponds to fdim, aligned with std's deprecated inherent method of floats.

Deprecated since 1.10.0: you probably meant (self - other).abs(): this operation is (self - other).max(0.0) except that abs_sub also propagates NaNs (also known as fdim in C). If you truly need the positive difference, consider using that expression or the C function fdim, depending on how you wish to handle NaN (please consider filing an issue describing your use-case too).

We should probably just deprecate it in num-traits too... see also #120.

therealbnut commented 4 years ago

Oh cool, thanks for the historic context and clarification. I’m happy to close this and use my implementation as it works where I need it :)