#[cfg(nightly)]
mod std_simd;
#[cfg(nightly)]
pub use std_simd::LanesMult;
use core::ops::Shl;
use crate::traits::{NonZeroable, Number};
#[repr(transparent)]
#[derive(Debug, Hash, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub struct NonZeroPow2<N: NonZeroable>(N::NonZeroType);
impl<N: NonZeroable> NonZeroPow2<N>
where
N: Number + Shl<u32, Output = N>,
{
#[inline(always)]
pub fn v2() -> Self {
unsafe { Self::new_unchecked(N::ONE << 1) }
}
#[inline(always)]
pub fn v4() -> Self {
unsafe { Self::new_unchecked(Self::v2().get() << 1) }
}
#[inline(always)]
pub fn v8() -> Self {
unsafe { Self::new_unchecked(Self::v4().get() << 1) }
}
#[inline(always)]
pub fn v16() -> Self {
unsafe { Self::new_unchecked(Self::v8().get() << 1) }
}
#[inline(always)]
pub fn v32() -> Self {
unsafe { Self::new_unchecked(Self::v16().get() << 1) }
}
#[inline(always)]
pub fn v64() -> Self {
unsafe { Self::new_unchecked(Self::v32().get() << 1) }
}
#[inline(always)]
pub fn v128() -> Self {
unsafe { Self::new_unchecked(Self::v64().get() << 1) }
}
}
impl<N: NonZeroable> NonZeroPow2<N> {
#[inline(always)]
pub unsafe fn new_unchecked(value: N) -> Self {
Self(<N::NonZeroType as crate::traits::nonzero::private::NonZero>::new_unchecked(value))
}
#[inline(always)]
pub const unsafe fn from_nonzero_unchecked(value: N::NonZeroType) -> Self {
Self(value)
}
#[inline]
pub fn new(value: N) -> Option<Self> {
(!value.is_zero() && value.is_power_of_two()).then(|| unsafe { Self::new_unchecked(value) })
}
#[inline(always)]
pub fn get(self) -> N {
self.0.into()
}
#[inline(always)]
pub fn get_nonzero(self) -> N::NonZeroType {
self.0
}
}
#[cfg(test)]
mod arbitrary_impl {
use crate::traits::Number;
use super::*;
use core::ops::Shl;
use quickcheck::Arbitrary;
impl<N: NonZeroable + Number> Arbitrary for NonZeroPow2<N>
where
Self: 'static + Clone,
N: Shl<u32, Output = N>,
{
#[inline]
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Self::new((N::ONE << 1) << (u32::arbitrary(g) % (N::BITS - 1))).unwrap()
}
}
}