use crate::*;
pub trait Signed {
type SignMapped;
type BitSignMapped;
type BoolMapped;
fn sign(&self) -> Self::SignMapped;
fn bit_sign(&self) -> Self::BitSignMapped;
fn is_positive(&self) -> Self::BoolMapped;
fn is_negative(&self) -> Self::BoolMapped;
fn is_zero(&self) -> Self::BoolMapped;
fn is_bin_positive(&self) -> Self::BoolMapped;
fn is_bin_negative(&self) -> Self::BoolMapped;
}
pub trait Positive: Signed {
fn abs(self) -> Self;
}
pub trait Negative: Signed {
fn neg_abs(self) -> Self;
}
pub trait Zero: Signed {
fn zero() -> Self;
}
pub trait NotPositive: Signed {}
pub trait NotNegative: Signed {}
pub trait NotZero: Signed {}
pub trait AlwaysPositive: Positive + NotNegative + NotZero {}
pub trait AlwaysNegative: Negative + NotPositive + NotZero {}
pub trait AlwaysZero: Zero + NotPositive + NotNegative {}
pub trait PositiveOrZero: NotNegative + Zero + Positive {}
pub trait NegativeOrZero: Negative + Zero + NotPositive {}
pub trait PositiveOrNegative: Negative + NotZero + Positive {}
pub trait FullySigned: Negative + Zero + Positive {}
impl<T: Positive + NotNegative + NotZero> AlwaysPositive for T {}
impl<T: Negative + NotPositive + NotZero> AlwaysNegative for T {}
impl<T: Zero + NotPositive + NotNegative> AlwaysZero for T {}
impl<T: Positive + Zero + NotNegative> PositiveOrZero for T {}
impl<T: Negative + Zero + NotPositive> NegativeOrZero for T {}
impl<T: Positive + Negative + NotZero> PositiveOrNegative for T {}
impl<T: Positive + Negative + Zero> FullySigned for T {}
pub trait Signum: Signed {
fn signumt(self) -> Self;
fn bin_signum(self) -> Self;
}
macro_rules! uint_impl {
($type:ident) => {
impl Signed for $type {
type SignMapped = Sign;
type BitSignMapped = BitSign;
type BoolMapped = bool;
fn sign(&self) -> Sign {
if *self > 0 {
Sign::Positive
} else {
Sign::Zero
}
}
fn bit_sign(&self) -> BitSign {
BitSign::Positive
}
fn is_positive(&self) -> Self::BoolMapped {
*self != 0
}
fn is_negative(&self) -> Self::BoolMapped {
false
}
fn is_zero(&self) -> Self::BoolMapped {
*self == 0
}
fn is_bin_positive(&self) -> Self::BoolMapped {
true
}
fn is_bin_negative(&self) -> Self::BoolMapped {
false
}
}
impl Positive for $type {
fn abs(self) -> Self {
self
}
}
impl Zero for $type {
fn zero() -> Self {
0
}
}
impl NotNegative for $type {}
impl Signum for $type {
fn signumt(self) -> Self {
(self != 0) as $type
}
fn bin_signum(self) -> Self {
1
}
}
};
}
uint_impl!(u8);
uint_impl!(u16);
uint_impl!(u32);
uint_impl!(u64);
uint_impl!(u128);
uint_impl!(usize);
macro_rules! sint_impl {
($type:ident) => {
impl Signed for $type {
type SignMapped = Sign;
type BitSignMapped = BitSign;
type BoolMapped = bool;
fn sign(&self) -> Sign {
if *self > 0 {
Sign::Positive
} else if *self == 0 {
Sign::Zero
} else {
Sign::Negative
}
}
fn bit_sign(&self) -> BitSign {
if *self >= 0 {
BitSign::Positive
} else {
BitSign::Negative
}
}
fn is_positive(&self) -> Self::BoolMapped {
*self > 0
}
fn is_negative(&self) -> Self::BoolMapped {
*self < 0
}
fn is_zero(&self) -> Self::BoolMapped {
*self == 0
}
fn is_bin_positive(&self) -> Self::BoolMapped {
*self >= 0
}
fn is_bin_negative(&self) -> Self::BoolMapped {
*self < 0
}
}
impl Positive for $type {
fn abs(self) -> Self {
self.abs()
}
}
impl Negative for $type {
fn neg_abs(self) -> Self {
-self.abs()
}
}
impl Zero for $type {
fn zero() -> Self {
0
}
}
impl Signum for $type {
fn signumt(self) -> Self {
self.signum()
}
fn bin_signum(self) -> Self {
if self >= 0 {
1
} else {
-1
}
}
}
};
}
sint_impl!(i8);
sint_impl!(i16);
sint_impl!(i32);
sint_impl!(i64);
sint_impl!(i128);
sint_impl!(isize);
macro_rules! float_impl {
($type:ident) => {
impl Signed for $type {
type SignMapped = Sign;
type BitSignMapped = BitSign;
type BoolMapped = bool;
fn sign(&self) -> Sign {
if *self == 0.0 {
Sign::Zero
} else if *self > 0.0 {
Sign::Positive
} else {
Sign::Negative
}
}
fn bit_sign(&self) -> BitSign {
if self.is_sign_positive() {
BitSign::Positive
} else {
BitSign::Negative
}
}
fn is_positive(&self) -> Self::BoolMapped {
self.is_sign_positive() && *self != 0.0
}
fn is_negative(&self) -> Self::BoolMapped {
self.is_sign_negative() && *self != 0.0
}
fn is_zero(&self) -> Self::BoolMapped {
*self == 0.0
}
fn is_bin_positive(&self) -> Self::BoolMapped {
$type::is_sign_positive(*self)
}
fn is_bin_negative(&self) -> Self::BoolMapped {
$type::is_sign_negative(*self)
}
}
impl Positive for $type {
fn abs(self) -> Self {
self.abs()
}
}
impl Negative for $type {
fn neg_abs(self) -> Self {
-self.abs()
}
}
impl Zero for $type {
fn zero() -> Self {
0.0
}
}
impl Signum for $type {
fn signumt(self) -> Self {
if self == 0.0 {
0.0
} else {
self.signum()
}
}
fn bin_signum(self) -> Self {
$type::signum(self)
}
}
};
}
float_impl!(f32);
float_impl!(f64);