Closed
Description
Should num include a trait for upcasting / widening? I.e. all numerical casts that can be performed with no loss of information. Or is this more appropriate for a separate crate?
Here's a graph of the allowed upcasts: http://i.imgur.com/foiXWWS.png (not including self loops).
scratch impl follows
/// A trait for promotion of smaller numeric type into larger that
/// still allow the same range of values, without loss of information.
///
/// See discussion about this concept here:
/// https://internals.rust-lang.org/t/implicit-widening-polymorphic-indexing-and-similar-ideas/1141
///
/// ## Examples
///
/// ```
/// use upcastnum::Upcast;
///
/// fn add1<T: Upcast<i32>>(x: T) -> i32 {
/// x.upcast() + 1
/// }
///
/// assert_eq!(add1(1i32), 2);
/// assert_eq!(add1(1i8), 2);
/// assert_eq!(add1(1u8), 2);
/// assert_eq!(add1(1i16), 2);
/// ```
pub trait Upcast<T> {
fn upcast(self) -> T;
}
/// Convenience to be able to type-qualify upcasting directly on the method call.
///
/// ## Examples
///
/// ```
/// use upcastnum::UpcastTo;
/// let x = 1.upcast_to::<f64>() + 2.upcast_to::<f64>();
/// assert_eq!(x, 3.);
/// ```
pub trait UpcastTo {
#[inline(always)]
fn upcast_to<T>(self) -> T where Self: Sized + Upcast<T> {
self.upcast()
}
}
impl<T> UpcastTo for T { }
macro_rules! upcast {
($from: ty => $to: ty) => {
impl Upcast<$to> for $from {
#[inline(always)]
fn upcast(self) -> $to { self as $to }
}
}
}
upcast!(i8 => i8);
upcast!(i8 => i16);
upcast!(i8 => i32);
upcast!(i8 => i64);
upcast!(u8 => u8);
upcast!(u8 => u16);
upcast!(u8 => u32);
upcast!(u8 => u64);
upcast!(u8 => i16);
upcast!(u8 => i32);
upcast!(u8 => i64);
upcast!(i16 => i16);
upcast!(i16 => i32);
upcast!(i16 => i64);
upcast!(u16 => u16);
upcast!(u16 => u32);
upcast!(u16 => u64);
upcast!(u16 => i32);
upcast!(u16 => i64);
upcast!(i32 => i32);
upcast!(i32 => i64);
upcast!(u32 => u32);
upcast!(u32 => u64);
upcast!(u32 => i64);
upcast!(i64 => i64);
upcast!(u64 => u64);
// floating point
upcast!(f32 => f32);
upcast!(f32 => f64);
upcast!(f64 => f64);
upcast!(i8 => f32);
upcast!(i8 => f64);
upcast!(u8 => f32);
upcast!(u8 => f64);
upcast!(i16 => f32);
upcast!(i16 => f64);
upcast!(u16 => f32);
upcast!(u16 => f64);
upcast!(i32 => f64);
upcast!(u32 => f64);
Metadata
Metadata
Assignees
Labels
No labels