Skip to content

Instantly share code, notes, and snippets.

@zommiommy
Last active January 14, 2023 18:43
Show Gist options
  • Save zommiommy/2ce9e6443045f95c3a0c6ea53c8a8d48 to your computer and use it in GitHub Desktop.
Save zommiommy/2ce9e6443045f95c3a0c6ea53c8a8d48 to your computer and use it in GitHub Desktop.
Better num-traits ?
#![deny(unconditional_recursion)]
use core::fmt::{Debug, Display, LowerHex, Binary};
use core::ops::*;
use core::sync::atomic::*;
use core::num::*;
/// Trait of operations possible on both Signed and Unsiged words
pub trait Number: Sized + Send + Sync +
Display + LowerHex +
Default + Debug + Clone + Copy +
PartialOrd + Ord + PartialEq + Eq + Binary +
Add<Output=Self> + AddAssign<Self> +
BitAnd<Output=Self> + BitAndAssign<Self> +
BitOr<Output=Self> + BitOrAssign<Self> +
BitXor<Output=Self> + BitXorAssign<Self> +
Div<Output=Self> + DivAssign<Self> +
Mul<Output=Self> + MulAssign<Self> +
Not<Output=Self> +
Rem<Output=Self> + RemAssign<Self> +
Shl<Output=Self> + ShlAssign<Self> +
Shr<Output=Self> + ShrAssign<Self> +
Sub<Output=Self> + SubAssign<Self> +
{
/// Number of bits in the word
const BITS: u8;
/// Number of bytes in the word
const BYTES: u8;
/// The byte array form of the value = `[u8; Self::BYTES]`
type BytesForm;
/// Zero represented by `Self`
const ZERO: Self;
/// One represented by `Selfs`
const ONE: Self;
/// Minimum value represented by `Self`
const MIN: Self;
/// Maximum value represented by `Self`
const MAX: Self;
/// Get the i-th bit in the word. Valid values: [0, 63]
fn extract_bit(&self, bit: usize) -> bool;
/// Get the bits in range [START; END_BIT) in the word.
/// START valid values: [0, 63]
/// END valid values: [1, 64]
/// START < END!!!
fn extract_bitfield(&self, start_bit: usize, end_bit: usize) -> Self;
/// Checked integer addition. Computes self + rhs, returning None if
/// overflow occurred.
fn checked_add(self, rhs: Self) -> Option<Self>;
/// Checked integer division. Computes self / rhs, returning None
/// if rhs == 0.
fn checked_div(self, rhs: Self) -> Option<Self>;
/// Checked Euclidean division. Computes self.div_euclid(rhs), returning
/// None if rhs == 0.
fn checked_div_euclid(self, rhs: Self) -> Option<Self>;
/// Checked integer multiplication. Computes self * rhs, returning None if
/// overflow occurred.
fn checked_mul(self, rhs: Self) -> Option<Self>;
/// Checked negation. Computes -self, returning None unless self == 0.
/// Note that negating any positive integer will overflow.
fn checked_neg(self) -> Option<Self>;
/// Checked exponentiation. Computes self.pow(exp), returning None if
/// overflow occurred.
fn checked_pow(self, exp: u32) -> Option<Self>;
/// Checked integer remainder. Computes self % rhs, returning None
/// if rhs == 0.
fn checked_rem(self, rhs: Self) -> Option<Self>;
/// Checked Euclidean modulo. Computes self.rem_euclid(rhs), returning None
/// if rhs == 0.
fn checked_rem_euclid(self, rhs: Self) -> Option<Self>;
/// Checked shift left. Computes self << rhs, returning None if rhs is
/// larger than or equal to the number of bits in self.
fn checked_shl(self, rhs: u32) -> Option<Self>;
/// Checked shift right. Computes self >> rhs, returning None if rhs is
/// larger than or equal to the number of bits in self.
fn checked_shr(self, rhs: u32) -> Option<Self>;
/// Checked integer subtraction. Computes self - rhs, returning None if
/// overflow occurred.
fn checked_sub(self, rhs: Self) -> Option<Self>;
/// Returns the number of ones in the binary representation of self.
fn count_ones(self) -> u32;
/// Returns the number of zeros in the binary representation of self.
fn count_zeros(self) -> u32;
/// Performs Euclidean division.
/// Since, for the positive integers, all common definitions of division are
/// equal, this is exactly equal to self / rhs.
fn div_euclid(self, rhs: Self) -> Self;
/// Converts an integer from big endian to the target’s endianness.
/// On big endian this is a no-op. On little endian the bytes are swapped.
fn from_be(rhs: Self) -> Self;
/// Create a native endian integer value from its representation as a byte
/// array in big endian.
fn from_be_bytes(bytes: Self::BytesForm) -> Self;
/// Converts an integer from little endian to the target’s endianness.
/// On little endian this is a no-op. On big endian the bytes are swapped.
fn from_le(rhs: Self) -> Self;
/// Create a native endian integer value from its representation as a byte
/// array in little endian.
fn from_le_bytes(bytes: Self::BytesForm) -> Self;
/// Create a native endian integer value from its memory representation as
/// a byte array in native endianness.
/// As the target platform’s native endianness is used, portable code likely
/// wants to use from_be_bytes or from_le_bytes, as appropriate instead.
fn from_ne_bytes(bytes: Self::BytesForm) -> Self;
/// Returns the number of leading ones in the binary representation of self.
fn leading_ones(self) -> u32;
/// Returns the number of trailing zeros in the binary representation of self.
fn leading_zeros(self) -> u32;
/// Raises self to the power of exp, using exponentiation by squaring.
fn pow(self, exp: u32) -> Self;
/// Calculates the least remainder of self (mod rhs).
/// Since, for the positive integers, all common definitions of division are
/// equal, this is exactly equal to self % rhs.
fn rem_euclid(self, rhs: Self) -> Self;
/// Reverses the order of bits in the integer. The least significant bit
/// becomes the most significant bit, second least-significant bit becomes
/// second most-significant bit, etc.
fn reverse_bits(self) -> Self;
/// Shifts the bits to the left by a specified amount, n, wrapping the t
/// runcated bits to the end of the resulting integer.
/// Please note this isn’t the same operation as the << shifting operator!
fn rotate_left(self, exp: u32) -> Self;
/// Shifts the bits to the right by a specified amount, n, wrapping the
/// truncated bits to the beginning of the resulting integer.
/// Please note this isn’t the same operation as the >> shifting operator!
fn rotate_right(self, exp: u32) -> Self;
/// Saturating integer addition. Computes self + rhs, saturating at the
/// numeric bounds instead of overflowing.
fn saturating_add(self, rhs: Self) -> Self;
/// Saturating integer division. Computes self / rhs, saturating at the
/// numeric bounds instead of overflowing.
fn saturating_div(self, rhs: Self) -> Self;
/// Saturating integer multiplication. Computes self * rhs, saturating at
/// the numeric bounds instead of overflowing.
fn saturating_mul(self, rhs: Self) -> Self;
/// Saturating integer exponentiation. Computes self.pow(exp), saturating
/// at the numeric bounds instead of overflowing.
fn saturating_pow(self, rhs: u32) -> Self;
/// Saturating integer subtraction. Computes self - rhs, saturating at the
/// numeric bounds instead of overflowing.
fn saturating_sub(self, rhs: Self) -> Self;
/// Reverse the byte order of the integer
fn swap_bytes(self) -> Self;
/// Converts self to big endian from the target’s endianness.
/// On big endian this is a no-op. On little endian the bytes are swapped.
fn to_be(self) -> Self;
/// Return the memory representation of this integer as a byte array in
/// big-endian (network) byte order.
fn to_be_bytes(self) -> Self::BytesForm;
/// Converts self to little endian from the target’s endianness.
/// On little endian this is a no-op. On big endian the bytes are swapped.
fn to_le(self) -> Self;
/// Return the memory representation of this integer as a byte array in
/// little-endian byte order.
fn to_le_bytes(self) -> Self::BytesForm;
/// Return the memory representation of this integer as a byte array in
/// native byte order.
/// As the target platform’s native endianness is used, portable code should
/// use to_be_bytes or to_le_bytes, as appropriate, instead.
fn to_ne_bytes(self) -> Self::BytesForm;
/// Returns the number of trailing ones in the binary representation of self.
fn trailing_ones(self) -> u32;
/// Returns the number of trailing zeros in the binary representation of self.
fn trailing_zeros(self) -> u32;
/// Add `self` and `rhs`, returning the result using wrapping arithmetic
fn wrapping_add(self, rhs: Self) -> Self;
/// Wrapping (modular) division. Computes self / rhs. Wrapped division on
/// unsigned types is just normal division. There’s no way wrapping could
/// ever happen. This function exists, so that all operations are accounted
/// for in the wrapping operations.
fn wrapping_div(self, rhs: Self) -> Self;
/// Wrapping Euclidean division. Computes self.div_euclid(rhs). Wrapped
/// division on unsigned types is just normal division. There’s no way
/// wrapping could ever happen. This function exists, so that all operations
/// are accounted for in the wrapping operations. Since, for the positive
/// integers, all common definitions of division are equal, this is exactly
/// equal to self.wrapping_div(rhs).
fn wrapping_div_euclid(self, rhs: Self) -> Self;
/// Wrapping (modular) multiplication. Computes self * rhs, wrapping around
/// at the boundary of the type.
fn wrapping_mul(self, rhs: Self) -> Self;
/// Wrapping (modular) negation. Computes -self, wrapping around at the
/// boundary of the type.
/// Since unsigned types do not have negative equivalents all applications
/// of this function will wrap (except for -0). For values smaller than the
/// corresponding signed type’s maximum the result is the same as casting
/// the corresponding signed value. Any larger values are equivalent to
/// MAX + 1 - (val - MAX - 1) where MAX is the corresponding signed type’s
/// maximum.
fn wrapping_neg(self) -> Self;
/// Wrapping (modular) exponentiation. Computes self.pow(exp), wrapping
/// around at the boundary of the type.
fn wrapping_pow(self, exp: u32) -> Self;
/// Wrapping (modular) remainder. Computes self % rhs. Wrapped remainder
/// calculation on unsigned types is just the regular remainder calculation.
/// There’s no way wrapping could ever happen. This function exists, so
/// that all operations are accounted for in the wrapping operations.
fn wrapping_rem(self, rhs: Self) -> Self;
/// Wrapping Euclidean modulo. Computes self.rem_euclid(rhs). Wrapped modulo
/// calculation on unsigned types is just the regular remainder calculation.
/// There’s no way wrapping could ever happen. This function exists, so that
/// all operations are accounted for in the wrapping operations. Since, for
/// the positive integers, all common definitions of division are equal,
/// this is exactly equal to self.wrapping_rem(rhs).
fn wrapping_rem_euclid(self, rhs: Self) -> Self;
/// Panic-free bitwise shift-left; yields self << mask(rhs), where mask
/// removes any high-order bits of rhs that would cause the shift to exceed
/// the bitwidth of the type.
/// Note that this is not the same as a rotate-left; the RHS of a wrapping
/// shift-left is restricted to the range of the type, rather than the bits
/// shifted out of the LHS being returned to the other end. The primitive
/// integer types all implement a rotate_left function, which may be what
/// you want instead.
fn wrapping_shl(self, rhs: u32) -> Self;
/// Panic-free bitwise shift-right; yields self >> mask(rhs), where mask
/// removes any high-order bits of rhs that would cause the shift to exceed
/// the bitwidth of the type.
/// Note that this is not the same as a rotate-right; the RHS of a wrapping
/// shift-right is restricted to the range of the type, rather than the bits
/// shifted out of the LHS being returned to the other end. The primitive
/// integer types all implement a rotate_right function, which may be what
/// you want instead.
fn wrapping_shr(self, rhs: u32) -> Self;
/// Subtract `self` and `rhs`, returning the result using wrapping
/// arithmetic
fn wrapping_sub(self, rhs: Self) -> Self;
}
pub trait NonZero: Sized {
type BaseType;
/// Creates a non-zero without checking whether the value is non-zero. This
/// results in undefined behaviour if the value is zero.
/// # Safety
/// The value must not be zero.
unsafe fn new_unchecked(n: Self::BaseType) -> Self;
/// Creates a non-zero if the given value is not zero.
fn new(n: Self::BaseType) -> Option<Self>;
/// Returns the value as a primitive type.
fn get(self) -> Self::BaseType;
}
/// Unsigned word
pub trait Word: Number {
/// The signed variant of the word
type SignedWord: SignedWord<UnsignedWord=Self>;
/// The atomically modifiable variant of the word
type AtomicWord: AtomicWord<NonAtomicWord=Self>;
/// The non-zero variant of the word
type NonZeroWord: NonZero<BaseType = Self>;
/// Convert `self` into the signed variant of `Self`
fn to_signed(self) -> Self::SignedWord;
/// Convert `self` into the atomic variant of `Self`
fn to_atomic(self) -> Self::AtomicWord;
#[cfg(feature="atomic_from_mut")]
fn get_mut_slice(this: &mut [Self::Atomic]) -> &mut [Self];
#[cfg(feature="atomic_from_mut")]
fn from_mut_slice(this: &mut [Self]) -> &mut [Self::Atomic];
/// Computes the absolute difference between self and other.
fn abs_diff(self, rhs: Self) -> Self;
/// Logical shift left `self` by `rhs`, returing the result.
/// Overshifting by larget rhan [`Self::BITS`] will result in zero.
fn overflow_shl(self, rhs: Self) -> Self;
/// Logical shift right `self` by `rhs`, returing the result.
/// Overshifting by larget rhan [`Self::BITS`] will result in zero.
fn overflow_shr(self, rhs: Self) -> Self;
/// Arithmetic shift right `self` by `rhs`, returing the result.
/// Overshifting by larger than [`Self::BITS`] will result in either
/// `!0` or `0`, depending on the sign bit of `self`.
fn overflow_sar(self, rhs: Self) -> Self;
/// Interpret `self` as `rhs` bits and sign-extend it to [`Self::BITS`].
fn sign_extend(self, rhs: u32) -> Self;
/// Interpret `self` as `rhs` bits and zero-extend it to [`Self::BITS`].
fn zero_extend(self, rhs: u32) -> Self;
/// Checked addition with a signed integer. Computes self + rhs, returning
/// None if overflow occurred.
fn checked_add_signed(self, rhs: Self::SignedWord) -> Option<Self>;
/// Saturating integer addition. Computes self + rhs, saturating at the
/// numeric bounds instead of overflowing.
fn saturating_add_signed(self, rhs: Self::SignedWord) -> Self;
/// Wrapping (modular) addition with a signed integer. Computes self + rhs,
/// wrapping around at the boundary of the type.
fn wrapping_add_signed(self, rhs: Self::SignedWord) -> Self;
/// Returns the smallest power of two greater than or equal to n.
/// If the next power of two is greater than the type’s maximum value, None
/// is returned, otherwise the power of two is wrapped in Some.
fn checked_next_power_of_two(self) -> Option<Self>;
/// Returns true if and only if self == 2^k for some k.
fn is_power_of_two(self) -> bool;
/// Returns the smallest power of two greater than or equal to self.
/// When return value overflows (i.e., self > (1 << (N-1)) for type uN), it
/// panics in debug mode and the return value is wrapped to 0 in release mode
/// (the only situation in which method can return 0).
fn next_power_of_two(self) -> Self;
}
/// Signed word
pub trait SignedWord: Neg<Output=Self> + Number {
type UnsignedWord: Word<SignedWord = Self>;
/// The non-zero variant of the word
type NonZeroWord: NonZero<BaseType = Self>;
/// Convert `self` into the unsigned variant of `Self`
fn to_unsigned(self) -> Self::UnsignedWord;
/// Computes the absolute value of self.
/// # Overflow behavior
/// The absolute value of Self::MIN cannot be represented as an Self, and a
/// ttempting to calculate it will cause an overflow. This means that code
/// in debug mode will trigger a panic on this case and optimized code will
/// return Self::MIN without a panic.
fn abs(self) -> Self;
/// Checked absolute value. Computes self.abs(), returning None if
/// self == MIN.
fn checked_abs(self) -> Option<Self>;
/// Checked negation. Computes -self, returning None if self == MIN.
fn checked_neg(self) -> Option<Self>;
/// Checked subtraction with an unsigned integer. Computes self - rhs,
/// returning None if overflow occurred.
fn checked_sub_unsigned(self, rhs: Self::UnsignedWord) -> Option<Self>;
/// Saturating addition with an unsigned integer. Computes self + rhs,
/// saturating at the numeric bounds instead of overflowing.
fn saturating_add_unsigned(self, rhs: Self::UnsignedWord) -> Self;
/// Saturating subtraction with an unsigned integer. Computes self - rhs,
/// saturating at the numeric bounds instead of overflowing.
fn saturating_sub_unsigned(self, rhs: Self::UnsignedWord) -> Self;
/// Wrapping (modular) addition with an unsigned integer. Computes
/// self + rhs, wrapping around at the boundary of the type.
fn wrapping_add_unsigned(self, rhs: Self::UnsignedWord) -> Self;
/// Wrapping (modular) subtraction with an unsigned integer. Computes
/// self - rhs, wrapping around at the boundary of the type.
fn wrapping_sub_unsigned(self, rhs: Self::UnsignedWord) -> Self;
/// Computes the absolute difference between self and other.
fn abs_diff(self, rhs: Self) -> Self::UnsignedWord;
}
pub trait AtomicWord: Sized + Send + Sync {
type NonAtomicWord: Word<AtomicWord=Self>;
fn new(value: Self::NonAtomicWord) -> Self;
fn load(&self, order: Ordering) -> Self::NonAtomicWord;
fn store(&self, value: Self::NonAtomicWord, order: Ordering);
fn get_mut(&mut self) -> &mut Self::NonAtomicWord;
fn into_inner(self) -> Self::NonAtomicWord;
#[cfg(feature="atomic_from_mut")]
fn get_mut_slice(this: &mut [Self]) -> &mut [Self::NonAtomicWord];
#[cfg(feature="atomic_from_mut")]
fn from_mut_slice(this: &mut [Self::NonAtomicWord]) -> &mut [Self];
fn compare_exchange(
&self,
current: Self::NonAtomicWord,
new: Self::NonAtomicWord,
success: Ordering,
failure: Ordering,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord>;
fn compare_exchange_weak(
&self,
current: Self::NonAtomicWord,
new: Self::NonAtomicWord,
success: Ordering,
failure: Ordering,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord>;
fn swap(
&self,
new: Self::NonAtomicWord,
order: Ordering,
) -> Self::NonAtomicWord;
fn fetch_add(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_saturating_add(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_and(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_max(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_min(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_nand(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_or(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_sub(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_xor(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord;
fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord>
where
F: FnMut(Self::NonAtomicWord) -> Option<Self::NonAtomicWord>;
}
macro_rules! impl_Number {
($ty:ty) => {
impl Number for $ty {
const BITS: u8 = <$ty>::BITS as _;
const BYTES: u8 = core::mem::size_of::<$ty>() as _;
type BytesForm = [u8; core::mem::size_of::<$ty>()];
const MIN: Self = <$ty>::MIN as _;
const MAX: Self = <$ty>::MAX as _;
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline(always)]
fn extract_bit(&self, bit: usize) -> bool {
debug_assert!(bit < core::mem::size_of::<$ty>() * 8);
let mask: $ty = 1 << bit;
(self & mask) != 0
}
#[inline(always)]
fn extract_bitfield(&self, start_bit: usize, end_bit: usize) -> Self {
debug_assert!(start_bit < end_bit);
debug_assert!(end_bit < core::mem::size_of::<$ty>() * 8);
let n_bits = core::mem::size_of::<$ty>() * 8;
let mask: $ty = <$ty>::MAX >> (n_bits - (end_bit - start_bit));
(self >> start_bit) & mask
}
#[inline(always)]
fn checked_add(self, rhs: Self) -> Option<Self>{self.checked_add(rhs)}
#[inline(always)]
fn checked_div(self, rhs: Self) -> Option<Self>{self.checked_div(rhs)}
#[inline(always)]
fn checked_div_euclid(self, rhs: Self) -> Option<Self>{self.checked_div_euclid(rhs)}
#[inline(always)]
fn checked_mul(self, rhs: Self) -> Option<Self>{self.checked_mul(rhs)}
#[inline(always)]
fn checked_neg(self) -> Option<Self>{self.checked_neg()}
#[inline(always)]
fn checked_pow(self, exp: u32) -> Option<Self>{self.checked_pow(exp)}
#[inline(always)]
fn checked_rem(self, rhs: Self) -> Option<Self>{self.checked_rem(rhs)}
#[inline(always)]
fn checked_rem_euclid(self, rhs: Self) -> Option<Self>{self.checked_rem_euclid(rhs)}
#[inline(always)]
fn checked_shl(self, rhs: u32) -> Option<Self>{self.checked_shl(rhs)}
#[inline(always)]
fn checked_shr(self, rhs: u32) -> Option<Self>{self.checked_shr(rhs)}
#[inline(always)]
fn checked_sub(self, rhs: Self) -> Option<Self>{self.checked_sub(rhs)}
#[inline(always)]
fn count_ones(self) -> u32{self.count_ones()}
#[inline(always)]
fn count_zeros(self) -> u32{self.count_zeros()}
#[inline(always)]
fn div_euclid(self, rhs: Self) -> Self { self.div_euclid(rhs)}
#[inline(always)]
fn from_be(rhs: Self) -> Self {<$ty>::from_be(rhs)}
#[inline(always)]
fn from_be_bytes(bytes: Self::BytesForm) -> Self {<$ty>::from_be_bytes(bytes)}
#[inline(always)]
fn from_le(rhs: Self) -> Self {<$ty>::from_le(rhs)}
#[inline(always)]
fn from_le_bytes(bytes: Self::BytesForm) -> Self {<$ty>::from_le_bytes(bytes)}
#[inline(always)]
fn from_ne_bytes(bytes: Self::BytesForm) -> Self {<$ty>::from_ne_bytes(bytes)}
#[inline(always)]
fn leading_ones(self) -> u32{self.leading_ones()}
#[inline(always)]
fn leading_zeros(self) -> u32{self.leading_zeros()}
#[inline(always)]
fn pow(self, exp: u32) -> Self{self.pow(exp)}
#[inline(always)]
fn rem_euclid(self, rhs: Self) -> Self { self.rem_euclid(rhs)}
#[inline(always)]
fn reverse_bits(self) -> Self{self.reverse_bits()}
#[inline(always)]
fn rotate_left(self, rhs: u32) -> Self { self.rotate_left(rhs)}
#[inline(always)]
fn rotate_right(self, rhs: u32) -> Self { self.rotate_right(rhs)}
#[inline(always)]
fn saturating_add(self, rhs: Self) -> Self { self.saturating_add(rhs)}
#[inline(always)]
fn saturating_div(self, rhs: Self) -> Self { self.saturating_div(rhs)}
#[inline(always)]
fn saturating_mul(self, rhs: Self) -> Self { self.saturating_mul(rhs)}
#[inline(always)]
fn saturating_pow(self, rhs: u32) -> Self { self.saturating_pow(rhs)}
#[inline(always)]
fn saturating_sub(self, rhs: Self) -> Self { self.saturating_sub(rhs)}
#[inline(always)]
fn swap_bytes(self) -> Self{self.swap_bytes()}
#[inline(always)]
fn to_be(self) -> Self{self.to_be()}
#[inline(always)]
fn to_be_bytes(self) -> Self::BytesForm{self.to_be_bytes()}
#[inline(always)]
fn to_le(self) -> Self{self.to_le()}
#[inline(always)]
fn to_le_bytes(self) -> Self::BytesForm{self.to_le_bytes()}
#[inline(always)]
fn to_ne_bytes(self) -> Self::BytesForm{self.to_ne_bytes()}
#[inline(always)]
fn trailing_ones(self) -> u32{self.trailing_ones()}
#[inline(always)]
fn trailing_zeros(self) -> u32{self.trailing_zeros()}
#[inline(always)]
fn wrapping_add(self, rhs: Self) -> Self { self.wrapping_add(rhs)}
#[inline(always)]
fn wrapping_div(self, rhs: Self) -> Self { self.wrapping_div(rhs)}
#[inline(always)]
fn wrapping_div_euclid(self, rhs: Self) -> Self { self.wrapping_div_euclid(rhs)}
#[inline(always)]
fn wrapping_mul(self, rhs: Self) -> Self { self.wrapping_mul(rhs)}
#[inline(always)]
fn wrapping_neg(self) -> Self { self.wrapping_neg()}
#[inline(always)]
fn wrapping_pow(self, exp: u32) -> Self { self.wrapping_pow(exp)}
#[inline(always)]
fn wrapping_rem(self, rhs: Self) -> Self { self.wrapping_rem(rhs)}
#[inline(always)]
fn wrapping_rem_euclid(self, rhs: Self) -> Self { self.wrapping_rem_euclid(rhs)}
#[inline(always)]
fn wrapping_shl(self, exp: u32) -> Self { self.wrapping_shl(exp)}
#[inline(always)]
fn wrapping_shr(self, exp: u32) -> Self { self.wrapping_shr(exp)}
#[inline(always)]
fn wrapping_sub(self, rhs: Self) -> Self { self.wrapping_sub(rhs)}
}
};
}
macro_rules! impl_word {
($ty:ty, $sty:ty, $aty:ty, $saty:ty, $nzty:ty, $nzsty:ty) => {
impl_Number!($ty);
impl_Number!($sty);
impl Word for $ty {
type SignedWord = $sty;
type AtomicWord = $aty;
type NonZeroWord = $nzty;
#[inline(always)]
fn to_signed(self) -> Self::SignedWord {self as Self::SignedWord}
#[inline(always)]
fn to_atomic(self) -> Self::AtomicWord {Self::AtomicWord::new(self)}
#[cfg(feature="atomic_from_mut")]
#[inline(always)]
fn get_mut_slice(this: &mut [Self::Atomic]) -> &mut [Self]{
<$aty>::get_mut_slice(this)
}
#[cfg(feature="atomic_from_mut")]
#[inline(always)]
fn from_mut_slice(this: &mut [Self]) -> &mut [Self::Atomic]{
<$aty>::from_mut_slice(this)
}
#[inline(always)]
fn abs_diff(self, rhs: Self) -> Self { self.abs_diff(rhs)}
#[inline(always)]
fn checked_next_power_of_two(self) -> Option<Self>{self.checked_next_power_of_two()}
#[inline(always)]
fn overflow_shl(self, rhs: Self) -> Self {
self.checked_shl(rhs.try_into().unwrap_or(1024)).unwrap_or(0)
}
#[inline(always)]
fn overflow_shr(self, rhs: Self) -> Self {
self.checked_shr(rhs.try_into().unwrap_or(1024)).unwrap_or(0)
}
#[inline(always)]
fn overflow_sar(self, rhs: Self) -> Self {
let shift_amount = core::cmp::min(rhs, Self::BITS as Self - 1);
((self as Self::SignedWord) >> shift_amount) as Self
}
#[inline(always)]
fn sign_extend(self, rhs: u32) -> Self {
let shift_amount = Self::BITS as u32 - rhs;
(((self << shift_amount) as Self::SignedWord) >> shift_amount) as Self
}
#[inline(always)]
fn zero_extend(self, rhs: u32) -> Self {
let shift_amount = Self::BITS as u32 - rhs;
(self << shift_amount) >> shift_amount
}
#[inline(always)]
fn checked_add_signed(self, rhs: Self::SignedWord) -> Option<Self>{self.checked_add_signed(rhs)}
#[inline(always)]
fn saturating_add_signed(self, rhs: Self::SignedWord) -> Self{self.saturating_add_signed(rhs)}
#[inline(always)]
fn wrapping_add_signed(self, rhs: Self::SignedWord) -> Self{self.wrapping_add_signed(rhs)}
#[inline(always)]
fn is_power_of_two(self) -> bool{self.is_power_of_two()}
#[inline(always)]
fn next_power_of_two(self) -> Self{self.next_power_of_two()}
}
impl SignedWord for $sty {
type UnsignedWord = $ty;
type NonZeroWord = $nzsty;
#[inline(always)]
fn to_unsigned(self) -> Self::UnsignedWord {self as Self::UnsignedWord}
#[inline(always)]
fn abs(self) -> Self { self.abs()}
#[inline(always)]
fn checked_abs(self) -> Option<Self> { self.checked_abs()}
#[inline(always)]
fn checked_neg(self) -> Option<Self> { self.checked_neg()}
#[inline(always)]
fn checked_sub_unsigned(self, rhs: Self::UnsignedWord) -> Option<Self> { self.checked_sub_unsigned(rhs)}
#[inline(always)]
fn saturating_add_unsigned(self, rhs: Self::UnsignedWord) -> Self {self.saturating_add_unsigned(rhs)}
#[inline(always)]
fn saturating_sub_unsigned(self, rhs: Self::UnsignedWord) -> Self {self.saturating_sub_unsigned(rhs)}
#[inline(always)]
fn wrapping_add_unsigned(self, rhs: Self::UnsignedWord) -> Self {self.wrapping_add_unsigned(rhs)}
#[inline(always)]
fn wrapping_sub_unsigned(self, rhs: Self::UnsignedWord) -> Self {self.wrapping_sub_unsigned(rhs)}
#[inline(always)]
fn abs_diff(self, rhs: Self) -> Self::UnsignedWord { self.abs_diff(rhs)}
}
impl AtomicWord for $aty {
type NonAtomicWord = $ty;
#[inline(always)]
fn new(value: Self::NonAtomicWord) -> Self {
<$aty>::new(value)
}
#[inline(always)]
fn load(&self, order: Ordering) -> Self::NonAtomicWord {
<$aty>::load(self, order)
}
#[inline(always)]
fn store(&self, value: Self::NonAtomicWord, order: Ordering) {
<$aty>::store(self, value, order)
}
#[inline(always)]
fn get_mut(&mut self) -> &mut Self::NonAtomicWord {
<$aty>::get_mut(self)
}
#[inline(always)]
fn into_inner(self) -> Self::NonAtomicWord {
<$aty>::into_inner(self)
}
#[cfg(feature="atomic_from_mut")]
#[inline(always)]
fn get_mut_slice(this: &mut [Self]) -> &mut [Self::NonAtomicWord]{
<$aty>::get_mut_slice(this)
}
#[cfg(feature="atomic_from_mut")]
#[inline(always)]
fn from_mut_slice(this: &mut [Self::NonAtomicWord]) -> &mut [Self]{
<$aty>::from_mut_slice(this)
}
#[inline(always)]
fn compare_exchange(
&self,
current: Self::NonAtomicWord,
new: Self::NonAtomicWord,
success: Ordering,
failure: Ordering,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord> {
<$aty>::compare_exchange(
self,
current,
new,
success,
failure,
)
}
#[inline(always)]
fn compare_exchange_weak(
&self,
current: Self::NonAtomicWord,
new: Self::NonAtomicWord,
success: Ordering,
failure: Ordering,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord>{
<$aty>::compare_exchange_weak(
self,
current,
new,
success,
failure,
)
}
#[inline(always)]
fn swap(
&self,
new: Self::NonAtomicWord,
order: Ordering,
) -> Self::NonAtomicWord{
<$aty>::swap(
self,
new,
order,
)
}
#[inline(always)]
fn fetch_add(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_add(self, value, order)
}
#[inline(always)]
fn fetch_saturating_add(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
let mut base = <$aty>::load(self, order);
loop {
let new = base.saturating_add(value);
let res = <$aty>::compare_exchange_weak(
self,
base,
new,
order,
order,
);
match res {
Ok(val) => {return val},
Err(val) => {
base = val;
}
}
}
}
#[inline(always)]
fn fetch_and(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_and(self, value, order)
}
#[inline(always)]
fn fetch_max(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_max(self, value, order)
}
#[inline(always)]
fn fetch_min(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_min(self, value, order)
}
#[inline(always)]
fn fetch_nand(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_nand(self, value, order)
}
#[inline(always)]
fn fetch_or(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_or(self, value, order)
}
#[inline(always)]
fn fetch_sub(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_sub(self, value, order)
}
#[inline(always)]
fn fetch_xor(&self, value: Self::NonAtomicWord, order: Ordering) -> Self::NonAtomicWord{
<$aty>::fetch_xor(self, value, order)
}
#[inline(always)]
fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F,
) -> Result<Self::NonAtomicWord, Self::NonAtomicWord>
where
F: FnMut(Self::NonAtomicWord) -> Option<Self::NonAtomicWord> {
<$aty>::fetch_update(self, set_order, fetch_order, f)
}
}
impl NonZero for $nzty {
type BaseType = $ty;
unsafe fn new_unchecked(n: Self::BaseType) -> Self {
<$nzty>::new_unchecked(n)
}
fn new(n: Self::BaseType) -> Option<Self>{
<$nzty>::new(n)
}
fn get(self) -> Self::BaseType{
<$nzty>::get(self)
}
}
impl NonZero for $nzsty {
type BaseType = $sty;
unsafe fn new_unchecked(n: Self::BaseType) -> Self {
<$nzsty>::new_unchecked(n)
}
fn new(n: Self::BaseType) -> Option<Self>{
<$nzsty>::new(n)
}
fn get(self) -> Self::BaseType{
<$nzsty>::get(self)
}
}
};
}
impl_word!(u8, i8, AtomicU8, AtomicI8, NonZeroU8, NonZeroI8);
impl_word!(u16, i16, AtomicU16, AtomicI16, NonZeroU16, NonZeroI16);
impl_word!(u32, i32, AtomicU32, AtomicI32, NonZeroU32, NonZeroI32);
impl_word!(u64, i64, AtomicU64, AtomicI64, NonZeroU64, NonZeroI64);
impl_word!(usize, isize, AtomicUsize, AtomicIsize, NonZeroUsize, NonZeroIsize);
//impl_word!(u128, i128, AtomicU128, AtomicI128);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment