use num::Zero;
use num_complex::Complex;
#[cfg(feature = "decimal")]
use decimal::d128;
pub trait SubsetOf<T>: Sized {
fn to_superset(&self) -> T;
fn from_superset(element: &T) -> Option<Self> {
if Self::is_in_subset(element) {
Some(unsafe { Self::from_superset_unchecked(element) })
} else {
None
}
}
unsafe fn from_superset_unchecked(element: &T) -> Self;
fn is_in_subset(element: &T) -> bool;
}
pub trait SupersetOf<T>: Sized {
fn to_subset(&self) -> Option<T> {
if self.is_in_subset() {
Some(unsafe { self.to_subset_unchecked() })
} else {
None
}
}
fn is_in_subset(&self) -> bool;
unsafe fn to_subset_unchecked(&self) -> T;
fn from_subset(element: &T) -> Self;
}
impl<SS: SubsetOf<SP>, SP> SupersetOf<SS> for SP {
#[inline]
fn to_subset(&self) -> Option<SS> {
SS::from_superset(self)
}
#[inline]
fn is_in_subset(&self) -> bool {
SS::is_in_subset(self)
}
#[inline]
unsafe fn to_subset_unchecked(&self) -> SS {
SS::from_superset_unchecked(self)
}
#[inline]
fn from_subset(element: &SS) -> Self {
element.to_superset()
}
}
macro_rules! impl_subset(
($($subset: ty as $( $superset: ty),+ );* $(;)*) => {
$($(
impl SubsetOf<$superset> for $subset {
#[inline]
fn to_superset(&self) -> $superset {
*self as $superset
}
#[inline]
unsafe fn from_superset_unchecked(element: &$superset) -> $subset {
*element as $subset
}
#[inline]
fn is_in_subset(_: &$superset) -> bool {
true
}
}
)+)*
}
);
impl_subset!(
u8 as u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64;
u16 as u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64;
u32 as u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64;
u64 as u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64;
usize as u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64;
i8 as i8, i16, i32, i64, isize, f32, f64;
i16 as i8, i16, i32, i64, isize, f32, f64;
i32 as i8, i16, i32, i64, isize, f32, f64;
i64 as i8, i16, i32, i64, isize, f32, f64;
isize as i8, i16, i32, i64, isize, f32, f64;
f32 as f32, f64;
f64 as f32, f64;
);
impl<N1, N2: SupersetOf<N1>> SubsetOf<Complex<N2>> for Complex<N1> {
#[inline]
fn to_superset(&self) -> Complex<N2> {
Complex {
re: N2::from_subset(&self.re),
im: N2::from_subset(&self.im),
}
}
#[inline]
unsafe fn from_superset_unchecked(element: &Complex<N2>) -> Complex<N1> {
Complex {
re: element.re.to_subset_unchecked(),
im: element.im.to_subset_unchecked(),
}
}
#[inline]
fn is_in_subset(c: &Complex<N2>) -> bool {
c.re.is_in_subset() && c.im.is_in_subset()
}
}
macro_rules! impl_scalar_subset_of_complex(
($($t: ident),*) => {$(
impl<N2: Zero + SupersetOf<$t>> SubsetOf<Complex<N2>> for $t {
#[inline]
fn to_superset(&self) -> Complex<N2> {
Complex {
re: N2::from_subset(self),
im: N2::zero()
}
}
#[inline]
unsafe fn from_superset_unchecked(element: &Complex<N2>) -> $t {
element.re.to_subset_unchecked()
}
#[inline]
fn is_in_subset(c: &Complex<N2>) -> bool {
c.re.is_in_subset() && c.im.is_zero()
}
}
)*}
);
impl_scalar_subset_of_complex!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
#[cfg(feature = "decimal")]
impl_scalar_subset_of_complex!(d128);