use core::num::Wrapping;
use core::ops::{Add, Mul};
use core::num::Saturating;
c0nst::c0nst! {
pub c0nst trait Zero: Sized {
fn zero() -> Self;
fn set_zero(&mut self);
fn is_zero(&self) -> bool;
}
}
pub trait ConstZero: Sized {
const ZERO: Self;
}
macro_rules! zero_impl {
($t:ty, $v:expr) => {
c0nst::c0nst! {
c0nst impl Zero for $t {
#[inline]
fn zero() -> $t {
$v
}
#[inline]
fn set_zero(&mut self) {
*self = $v;
}
#[inline]
fn is_zero(&self) -> bool {
*self == $v
}
}
}
impl ConstZero for $t {
const ZERO: Self = $v;
}
};
}
zero_impl!(usize, 0);
zero_impl!(u8, 0);
zero_impl!(u16, 0);
zero_impl!(u32, 0);
zero_impl!(u64, 0);
zero_impl!(u128, 0);
zero_impl!(isize, 0);
zero_impl!(i8, 0);
zero_impl!(i16, 0);
zero_impl!(i32, 0);
zero_impl!(i64, 0);
zero_impl!(i128, 0);
zero_impl!(f32, 0.0);
zero_impl!(f64, 0.0);
c0nst::c0nst! {
c0nst impl<T: [c0nst] Zero> Zero for Wrapping<T>
where
Wrapping<T>: [c0nst] Add<Output = Wrapping<T>>,
{
fn is_zero(&self) -> bool {
self.0.is_zero()
}
fn set_zero(&mut self) {
self.0.set_zero();
}
fn zero() -> Self {
Wrapping(T::zero())
}
}
}
impl<T: ConstZero> ConstZero for Wrapping<T>
where
Wrapping<T>: Add<Output = Wrapping<T>>,
{
const ZERO: Self = Wrapping(T::ZERO);
}
c0nst::c0nst! {
c0nst impl<T: [c0nst] Zero> Zero for Saturating<T>
where
Saturating<T>: [c0nst] Add<Output = Saturating<T>>,
{
fn is_zero(&self) -> bool {
self.0.is_zero()
}
fn set_zero(&mut self) {
self.0.set_zero();
}
fn zero() -> Self {
Saturating(T::zero())
}
}
}
impl<T: ConstZero> ConstZero for Saturating<T>
where
Saturating<T>: Add<Output = Saturating<T>>,
{
const ZERO: Self = Saturating(T::ZERO);
}
c0nst::c0nst! {
pub c0nst trait One: Sized {
fn one() -> Self;
fn set_one(&mut self);
fn is_one(&self) -> bool;
}
}
pub trait ConstOne: Sized {
const ONE: Self;
}
macro_rules! one_impl {
($t:ty, $v:expr) => {
c0nst::c0nst! {
c0nst impl One for $t {
#[inline]
fn one() -> $t {
$v
}
#[inline]
fn set_one(&mut self) {
*self = $v;
}
#[inline]
fn is_one(&self) -> bool {
*self == $v
}
}
}
impl ConstOne for $t {
const ONE: Self = $v;
}
};
}
one_impl!(usize, 1);
one_impl!(u8, 1);
one_impl!(u16, 1);
one_impl!(u32, 1);
one_impl!(u64, 1);
one_impl!(u128, 1);
one_impl!(isize, 1);
one_impl!(i8, 1);
one_impl!(i16, 1);
one_impl!(i32, 1);
one_impl!(i64, 1);
one_impl!(i128, 1);
one_impl!(f32, 1.0);
one_impl!(f64, 1.0);
c0nst::c0nst! {
c0nst impl<T: [c0nst] One> One for Wrapping<T>
where
Wrapping<T>: [c0nst] Mul<Output = Wrapping<T>>,
{
fn set_one(&mut self) {
self.0.set_one();
}
fn one() -> Self {
Wrapping(T::one())
}
fn is_one(&self) -> bool {
self.0.is_one()
}
}
}
impl<T: ConstOne> ConstOne for Wrapping<T>
where
Wrapping<T>: Mul<Output = Wrapping<T>>,
{
const ONE: Self = Wrapping(T::ONE);
}
c0nst::c0nst! {
c0nst impl<T: [c0nst] One> One for Saturating<T>
where
Saturating<T>: [c0nst] Mul<Output = Saturating<T>>,
{
fn set_one(&mut self) {
self.0.set_one();
}
fn one() -> Self {
Saturating(T::one())
}
fn is_one(&self) -> bool {
self.0.is_one()
}
}
}
impl<T: ConstOne> ConstOne for Saturating<T>
where
Saturating<T>: Mul<Output = Saturating<T>>,
{
const ONE: Self = Saturating(T::ONE);
}
c0nst::c0nst! {
#[inline(always)]
pub c0nst fn zero<T: [c0nst] Zero>() -> T {
Zero::zero()
}
}
c0nst::c0nst! {
#[inline(always)]
pub c0nst fn one<T: [c0nst] One>() -> T {
One::one()
}
}
#[test]
fn wrapping_identities() {
macro_rules! test_wrapping_identities {
($($t:ty)+) => {
$(
assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero());
assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero());
)+
};
}
test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
}
#[test]
fn wrapping_is_zero() {
fn require_zero<T: Zero>(_: &T) {}
require_zero(&Wrapping(42));
}
#[test]
fn wrapping_is_one() {
fn require_one<T: One>(_: &T) {}
require_one(&Wrapping(42));
}
#[test]
fn saturating_identities() {
macro_rules! test_saturating_identities {
($($t:ty)+) => {
$(
assert_eq!(zero::<$t>(), zero::<Saturating<$t>>().0);
assert_eq!(one::<$t>(), one::<Saturating<$t>>().0);
assert_eq!((0 as $t).is_zero(), Saturating(0 as $t).is_zero());
assert_eq!((1 as $t).is_zero(), Saturating(1 as $t).is_zero());
)+
};
}
test_saturating_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
}
#[test]
fn saturating_is_zero() {
fn require_zero<T: Zero>(_: &T) {}
require_zero(&Saturating(42));
}
#[test]
fn saturating_is_one() {
fn require_one<T: One>(_: &T) {}
require_one(&Saturating(42));
}