num-traits
num-traits copied to clipboard
Add `trait UnsignedAbs`
All signed rust integer types has an unsgined_abs function, e.g. (-7_i32).unsigned_abs() == 7_u32, which is there to correctly handle i32::MIN (which cannot be negated as a i32).
I suggest we ~either add this to PrimInt (returning identify for unsigned integers), or~ add a new UnsignedAbs trait for this.
I'd be happy to make a PR if this sounds good.
I think it will have to be a separate trait, especially because it needs an associated type for the unsigned return.
I fear that associated type will also make this a bear to actually use in generic code though. Have you experimented with a local trait doing this?
You are right that a separate trait makes most sense.
I tried this in a real world example, and it works great:
pub trait UnsignedAbs {
/// An unsigned type which is large enough to hold the absolute value of `Self`.
type Unsigned;
/// Computes the absolute value of `self` without any wrapping or panicking.
fn unsigned_abs(self) -> Self::Unsigned;
}
impl UnsignedAbs for i64 {
type Unsigned = u64;
fn unsigned_abs(self) -> Self::Unsigned {
self.unsigned_abs()
}
}
impl UnsignedAbs for isize {
type Unsigned = usize;
fn unsigned_abs(self) -> Self::Unsigned {
self.unsigned_abs()
}
}
/// Pretty format a signed number by using thousands separators for readability.
pub fn format_int<Int>(number: Int) -> String
where
Int: Display + PartialOrd + num_traits::Zero + UnsignedAbs,
Int::Unsigned: Display + num_traits::Unsigned,
{
if number < Int::zero() {
format!("-{}", format_uint(number.unsigned_abs()))
} else {
add_thousands_separators(&number.to_string())
}
}
/// Pretty format an unsigned integer by using thousands separators for readability
#[allow(clippy::needless_pass_by_value)]
pub fn format_uint<Uint>(number: Uint) -> String
where
Uint: Display + num_traits::Unsigned,
{
add_thousands_separators(&number.to_string())
}
/// Add thousands separators to a number, every three steps,
/// counting from the last character.
fn add_thousands_separators(number: &str) -> String {
…
}
I think it should probably take &self for consistency, especially compared to Signed::abs.
Hi 👋 Is anyone still looking into this? I'd be happy to pick it up if you'd be open to it. This is what I've got based on the prior discussion in this issue: https://github.com/rust-num/num-traits/pull/366
Would it fit in well with the existing code?