use crate::Exponent;
use crate::Uint;
pub trait Bits {
const BITS: Exponent;
fn bit_width(&self) -> Exponent;
fn bit(&self, index: Exponent) -> bool;
}
macro_rules! impl_bits_for_uint {
($($uint: ty), *) => {
$(impl Bits for $uint {
const BITS: Exponent = Self::BITS as Exponent;
#[inline]
fn bit_width(&self) -> Exponent {
(Self::BITS - self.leading_zeros()) as Exponent
}
#[inline]
fn bit(&self, index: Exponent) -> bool {
self & (1 << index) != 0
}
})*
};
}
impl_bits_for_uint!(u8, u16, u32, u64, u128, usize);
impl<const N: usize, const B: usize, const OM: u8> Bits for Uint<N, B, OM> {
const BITS: Exponent = Self::BITS;
#[inline]
fn bit_width(&self) -> Exponent {
Self::bit_width(*self)
}
#[inline]
fn bit(&self, index: Exponent) -> bool {
Self::bit(&self, index)
}
}
pub trait Zero: Sized + PartialEq {
const ZERO: Self;
#[inline]
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
pub trait One: Sized + PartialEq {
const ONE: Self;
}
macro_rules! impl_zero_for_int {
($($int: ty), *) => {
$(impl Zero for $int {
const ZERO: Self = 0;
})*
};
}
impl_zero_for_int!(u8, u16, u32, u64, u128, usize);
macro_rules! impl_one_for_int {
($($uint: ty), *) => {
$(impl One for $uint {
const ONE: Self = 1;
})*
};
}
impl_one_for_int!(
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
);
impl<const N: usize, const B: usize, const OM: u8> Zero for Uint<N, B, OM> {
const ZERO: Self = Self::ZERO;
}
impl<const N: usize, const B: usize, const OM: u8> One for Uint<N, B, OM> {
const ONE: Self = Self::ONE;
}
#[inline(always)]
pub const fn tuple_to_option<T: Copy>((int, overflow): (T, bool)) -> Option<T> {
if overflow { None } else { Some(int) }
}
macro_rules! ok {
{ $e: expr } => {
match $e {
Ok(v) => Some(v),
Err(_) => None,
}
};
}
pub(crate) use ok;
macro_rules! full_op_impl {
(<$(const $C: ident : $CType: ty), +> $OpTrait: ident, $AssignTrait: ident, $rhs: ty, $op: ident, $assign: ident for $int: ty) => {
impl<$(const $C: $CType), +> $OpTrait<&$rhs> for $int {
type Output = $int;
#[inline]
fn $op(self, rhs: &$rhs) -> Self::Output {
$OpTrait::<$rhs>::$op(self, *rhs)
}
}
impl<$(const $C: $CType), +> $OpTrait<&$rhs> for &$int {
type Output = $int;
#[inline]
fn $op(self, rhs: &$rhs) -> Self::Output {
$OpTrait::<$rhs>::$op(*self, *rhs)
}
}
impl<$(const $C: $CType), +> $OpTrait<$rhs> for &$int {
type Output = $int;
#[inline]
fn $op(self, rhs: $rhs) -> Self::Output {
$OpTrait::<$rhs>::$op(*self, rhs)
}
}
impl<$(const $C: $CType), +> $AssignTrait<$rhs> for $int {
#[inline]
fn $assign(&mut self, rhs: $rhs) {
*self = $OpTrait::$op(*self, rhs);
}
}
impl<$(const $C: $CType), +> $AssignTrait<&$rhs> for $int {
#[inline]
fn $assign(&mut self, rhs: &$rhs) {
self.$assign(*rhs);
}
}
}
}
pub(crate) use full_op_impl;