use crate::{
bit::{Bit, B0, B1},
consts::{U0, U1},
private::{
BitDiff, BitDiffOut, Internal, InternalMarker, PrivateAnd, PrivateAndOut, PrivateCmp,
PrivateCmpOut, PrivateLogarithm2, PrivatePow, PrivatePowOut, PrivateSquareRoot, PrivateSub,
PrivateSubOut, PrivateXor, PrivateXorOut, Trim, TrimOut,
},
Add1, Cmp, Double, Equal, Gcd, Gcf, GrEq, Greater, IsGreaterOrEqual, Len, Length, Less, Log2,
Logarithm2, Maximum, Minimum, NonZero, Or, Ord, Pow, Prod, Shleft, Shright, Sqrt, Square,
SquareRoot, Sub1, Sum, ToInt, Zero,
};
use core::ops::{Add, BitAnd, BitOr, BitXor, Mul, Shl, Shr, Sub};
pub use crate::marker_traits::{PowerOfTwo, Unsigned};
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
pub struct UTerm;
impl UTerm {
#[inline]
pub fn new() -> UTerm {
UTerm
}
}
impl Unsigned for UTerm {
const U8: u8 = 0;
const U16: u16 = 0;
const U32: u32 = 0;
const U64: u64 = 0;
#[cfg(feature = "i128")]
const U128: u128 = 0;
const USIZE: usize = 0;
const I8: i8 = 0;
const I16: i16 = 0;
const I32: i32 = 0;
const I64: i64 = 0;
#[cfg(feature = "i128")]
const I128: i128 = 0;
const ISIZE: isize = 0;
#[inline]
fn to_u8() -> u8 {
0
}
#[inline]
fn to_u16() -> u16 {
0
}
#[inline]
fn to_u32() -> u32 {
0
}
#[inline]
fn to_u64() -> u64 {
0
}
#[cfg(feature = "i128")]
#[inline]
fn to_u128() -> u128 {
0
}
#[inline]
fn to_usize() -> usize {
0
}
#[inline]
fn to_i8() -> i8 {
0
}
#[inline]
fn to_i16() -> i16 {
0
}
#[inline]
fn to_i32() -> i32 {
0
}
#[inline]
fn to_i64() -> i64 {
0
}
#[cfg(feature = "i128")]
#[inline]
fn to_i128() -> i128 {
0
}
#[inline]
fn to_isize() -> isize {
0
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
pub struct UInt<U, B> {
pub(crate) msb: U,
pub(crate) lsb: B,
}
impl<U: Unsigned, B: Bit> UInt<U, B> {
#[inline]
pub fn new() -> UInt<U, B> {
UInt::default()
}
}
impl<U: Unsigned, B: Bit> Unsigned for UInt<U, B> {
const U8: u8 = B::U8 | U::U8 << 1;
const U16: u16 = B::U8 as u16 | U::U16 << 1;
const U32: u32 = B::U8 as u32 | U::U32 << 1;
const U64: u64 = B::U8 as u64 | U::U64 << 1;
#[cfg(feature = "i128")]
const U128: u128 = B::U8 as u128 | U::U128 << 1;
const USIZE: usize = B::U8 as usize | U::USIZE << 1;
const I8: i8 = B::U8 as i8 | U::I8 << 1;
const I16: i16 = B::U8 as i16 | U::I16 << 1;
const I32: i32 = B::U8 as i32 | U::I32 << 1;
const I64: i64 = B::U8 as i64 | U::I64 << 1;
#[cfg(feature = "i128")]
const I128: i128 = B::U8 as i128 | U::I128 << 1;
const ISIZE: isize = B::U8 as isize | U::ISIZE << 1;
#[inline]
fn to_u8() -> u8 {
B::to_u8() | U::to_u8() << 1
}
#[inline]
fn to_u16() -> u16 {
u16::from(B::to_u8()) | U::to_u16() << 1
}
#[inline]
fn to_u32() -> u32 {
u32::from(B::to_u8()) | U::to_u32() << 1
}
#[inline]
fn to_u64() -> u64 {
u64::from(B::to_u8()) | U::to_u64() << 1
}
#[cfg(feature = "i128")]
#[inline]
fn to_u128() -> u128 {
u128::from(B::to_u8()) | U::to_u128() << 1
}
#[inline]
fn to_usize() -> usize {
usize::from(B::to_u8()) | U::to_usize() << 1
}
#[inline]
fn to_i8() -> i8 {
B::to_u8() as i8 | U::to_i8() << 1
}
#[inline]
fn to_i16() -> i16 {
i16::from(B::to_u8()) | U::to_i16() << 1
}
#[inline]
fn to_i32() -> i32 {
i32::from(B::to_u8()) | U::to_i32() << 1
}
#[inline]
fn to_i64() -> i64 {
i64::from(B::to_u8()) | U::to_i64() << 1
}
#[cfg(feature = "i128")]
#[inline]
fn to_i128() -> i128 {
i128::from(B::to_u8()) | U::to_i128() << 1
}
#[inline]
fn to_isize() -> isize {
B::to_u8() as isize | U::to_isize() << 1
}
}
impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}
impl Zero for UTerm {}
impl PowerOfTwo for UInt<UTerm, B1> {}
impl<U: Unsigned + PowerOfTwo> PowerOfTwo for UInt<U, B0> {}
impl Len for UTerm {
type Output = U0;
#[inline]
fn len(&self) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Len for UInt<U, B>
where
U: Len,
Length<U>: Add<B1>,
Add1<Length<U>>: Unsigned,
{
type Output = Add1<Length<U>>;
#[inline]
fn len(&self) -> Self::Output {
self.msb.len() + B1
}
}
impl Add<B0> for UTerm {
type Output = UTerm;
#[inline]
fn add(self, _: B0) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Add<B0> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn add(self, _: B0) -> Self::Output {
UInt::new()
}
}
impl Add<B1> for UTerm {
type Output = UInt<UTerm, B1>;
#[inline]
fn add(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned> Add<B1> for UInt<U, B0> {
type Output = UInt<U, B1>;
#[inline]
fn add(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned> Add<B1> for UInt<U, B1>
where
U: Add<B1>,
Add1<U>: Unsigned,
{
type Output = UInt<Add1<U>, B0>;
#[inline]
fn add(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned> Add<U> for UTerm {
type Output = U;
#[inline]
fn add(self, rhs: U) -> Self::Output {
rhs
}
}
impl<U: Unsigned, B: Bit> Add<UTerm> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn add(self, _: UTerm) -> Self::Output {
UInt::new()
}
}
impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: Add<Ur>,
{
type Output = UInt<Sum<Ul, Ur>, B0>;
#[inline]
fn add(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb + rhs.msb,
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: Add<Ur>,
{
type Output = UInt<Sum<Ul, Ur>, B1>;
#[inline]
fn add(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb + rhs.msb,
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: Add<Ur>,
{
type Output = UInt<Sum<Ul, Ur>, B1>;
#[inline]
fn add(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb + rhs.msb,
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> Add<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: Add<Ur>,
Sum<Ul, Ur>: Add<B1>,
{
type Output = UInt<Add1<Sum<Ul, Ur>>, B0>;
#[inline]
fn add(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb + rhs.msb + B1,
lsb: B0,
}
}
}
impl Sub<B0> for UTerm {
type Output = UTerm;
#[inline]
fn sub(self, _: B0) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Sub<B0> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn sub(self, _: B0) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned, B: Bit> Sub<B1> for UInt<UInt<U, B>, B1> {
type Output = UInt<UInt<U, B>, B0>;
#[inline]
fn sub(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl Sub<B1> for UInt<UTerm, B1> {
type Output = UTerm;
#[inline]
fn sub(self, _: B1) -> Self::Output {
UTerm
}
}
impl<U: Unsigned> Sub<B1> for UInt<U, B0>
where
U: Sub<B1>,
Sub1<U>: Unsigned,
{
type Output = UInt<Sub1<U>, B1>;
#[inline]
fn sub(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl Sub<UTerm> for UTerm {
type Output = UTerm;
#[inline]
fn sub(self, _: UTerm) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> Sub<Ur> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: PrivateSub<Ur>,
PrivateSubOut<UInt<Ul, Bl>, Ur>: Trim,
{
type Output = TrimOut<PrivateSubOut<UInt<Ul, Bl>, Ur>>;
#[inline]
fn sub(self, rhs: Ur) -> Self::Output {
self.private_sub(rhs).trim()
}
}
impl<U: Unsigned> PrivateSub<UTerm> for U {
type Output = U;
#[inline]
fn private_sub(self, _: UTerm) -> Self::Output {
self
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: PrivateSub<Ur>,
{
type Output = UInt<PrivateSubOut<Ul, Ur>, B0>;
#[inline]
fn private_sub(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_sub(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: PrivateSub<Ur>,
PrivateSubOut<Ul, Ur>: Sub<B1>,
{
type Output = UInt<Sub1<PrivateSubOut<Ul, Ur>>, B1>;
#[inline]
fn private_sub(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_sub(rhs.msb) - B1,
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: PrivateSub<Ur>,
{
type Output = UInt<PrivateSubOut<Ul, Ur>, B1>;
#[inline]
fn private_sub(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_sub(rhs.msb),
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateSub<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: PrivateSub<Ur>,
{
type Output = UInt<PrivateSubOut<Ul, Ur>, B0>;
#[inline]
fn private_sub(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_sub(rhs.msb),
lsb: B0,
}
}
}
impl<Ur: Unsigned> BitAnd<Ur> for UTerm {
type Output = UTerm;
#[inline]
fn bitand(self, _: Ur) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> BitAnd<Ur> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: PrivateAnd<Ur>,
PrivateAndOut<UInt<Ul, Bl>, Ur>: Trim,
{
type Output = TrimOut<PrivateAndOut<UInt<Ul, Bl>, Ur>>;
#[inline]
fn bitand(self, rhs: Ur) -> Self::Output {
self.private_and(rhs).trim()
}
}
impl<U: Unsigned> PrivateAnd<U> for UTerm {
type Output = UTerm;
#[inline]
fn private_and(self, _: U) -> Self::Output {
UTerm
}
}
impl<B: Bit, U: Unsigned> PrivateAnd<UTerm> for UInt<U, B> {
type Output = UTerm;
#[inline]
fn private_and(self, _: UTerm) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: PrivateAnd<Ur>,
{
type Output = UInt<PrivateAndOut<Ul, Ur>, B0>;
#[inline]
fn private_and(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_and(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: PrivateAnd<Ur>,
{
type Output = UInt<PrivateAndOut<Ul, Ur>, B0>;
#[inline]
fn private_and(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_and(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: PrivateAnd<Ur>,
{
type Output = UInt<PrivateAndOut<Ul, Ur>, B0>;
#[inline]
fn private_and(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_and(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateAnd<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: PrivateAnd<Ur>,
{
type Output = UInt<PrivateAndOut<Ul, Ur>, B1>;
#[inline]
fn private_and(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_and(rhs.msb),
lsb: B1,
}
}
}
impl<U: Unsigned> BitOr<U> for UTerm {
type Output = U;
#[inline]
fn bitor(self, rhs: U) -> Self::Output {
rhs
}
}
impl<B: Bit, U: Unsigned> BitOr<UTerm> for UInt<U, B> {
type Output = Self;
#[inline]
fn bitor(self, _: UTerm) -> Self::Output {
UInt::new()
}
}
impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: BitOr<Ur>,
{
type Output = UInt<<Ul as BitOr<Ur>>::Output, B0>;
#[inline]
fn bitor(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.bitor(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: BitOr<Ur>,
{
type Output = UInt<Or<Ul, Ur>, B1>;
#[inline]
fn bitor(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.bitor(rhs.msb),
lsb: self.lsb.bitor(rhs.lsb),
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: BitOr<Ur>,
{
type Output = UInt<Or<Ul, Ur>, B1>;
#[inline]
fn bitor(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.bitor(rhs.msb),
lsb: self.lsb.bitor(rhs.lsb),
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> BitOr<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: BitOr<Ur>,
{
type Output = UInt<Or<Ul, Ur>, B1>;
#[inline]
fn bitor(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.bitor(rhs.msb),
lsb: self.lsb.bitor(rhs.lsb),
}
}
}
impl<Ur: Unsigned> BitXor<Ur> for UTerm {
type Output = Ur;
#[inline]
fn bitxor(self, rhs: Ur) -> Self::Output {
rhs
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned> BitXor<Ur> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: PrivateXor<Ur>,
PrivateXorOut<UInt<Ul, Bl>, Ur>: Trim,
{
type Output = TrimOut<PrivateXorOut<UInt<Ul, Bl>, Ur>>;
#[inline]
fn bitxor(self, rhs: Ur) -> Self::Output {
self.private_xor(rhs).trim()
}
}
impl<U: Unsigned> PrivateXor<U> for UTerm {
type Output = U;
#[inline]
fn private_xor(self, rhs: U) -> Self::Output {
rhs
}
}
impl<B: Bit, U: Unsigned> PrivateXor<UTerm> for UInt<U, B> {
type Output = Self;
#[inline]
fn private_xor(self, _: UTerm) -> Self::Output {
self
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: PrivateXor<Ur>,
{
type Output = UInt<PrivateXorOut<Ul, Ur>, B0>;
#[inline]
fn private_xor(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_xor(rhs.msb),
lsb: B0,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: PrivateXor<Ur>,
{
type Output = UInt<PrivateXorOut<Ul, Ur>, B1>;
#[inline]
fn private_xor(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_xor(rhs.msb),
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: PrivateXor<Ur>,
{
type Output = UInt<PrivateXorOut<Ul, Ur>, B1>;
#[inline]
fn private_xor(self, rhs: UInt<Ur, B0>) -> Self::Output {
UInt {
msb: self.msb.private_xor(rhs.msb),
lsb: B1,
}
}
}
impl<Ul: Unsigned, Ur: Unsigned> PrivateXor<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: PrivateXor<Ur>,
{
type Output = UInt<PrivateXorOut<Ul, Ur>, B0>;
#[inline]
fn private_xor(self, rhs: UInt<Ur, B1>) -> Self::Output {
UInt {
msb: self.msb.private_xor(rhs.msb),
lsb: B0,
}
}
}
impl Shl<B0> for UTerm {
type Output = UTerm;
#[inline]
fn shl(self, _: B0) -> Self::Output {
UTerm
}
}
impl Shl<B1> for UTerm {
type Output = UTerm;
#[inline]
fn shl(self, _: B1) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Shl<B0> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn shl(self, _: B0) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned, B: Bit> Shl<B1> for UInt<U, B> {
type Output = UInt<UInt<U, B>, B0>;
#[inline]
fn shl(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned, B: Bit> Shl<UTerm> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn shl(self, _: UTerm) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned> Shl<U> for UTerm {
type Output = UTerm;
#[inline]
fn shl(self, _: U) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit, Ur: Unsigned, Br: Bit> Shl<UInt<Ur, Br>> for UInt<U, B>
where
UInt<Ur, Br>: Sub<B1>,
UInt<UInt<U, B>, B0>: Shl<Sub1<UInt<Ur, Br>>>,
{
type Output = Shleft<UInt<UInt<U, B>, B0>, Sub1<UInt<Ur, Br>>>;
#[inline]
fn shl(self, rhs: UInt<Ur, Br>) -> Self::Output {
(UInt { msb: self, lsb: B0 }).shl(rhs - B1)
}
}
impl<U: Unsigned> Shr<U> for UTerm {
type Output = UTerm;
#[inline]
fn shr(self, _: U) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Shr<UTerm> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn shr(self, _: UTerm) -> Self::Output {
UInt::new()
}
}
impl Shr<B0> for UTerm {
type Output = UTerm;
#[inline]
fn shr(self, _: B0) -> Self::Output {
UTerm
}
}
impl Shr<B1> for UTerm {
type Output = UTerm;
#[inline]
fn shr(self, _: B1) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Shr<B0> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn shr(self, _: B0) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned, B: Bit> Shr<B1> for UInt<U, B> {
type Output = U;
#[inline]
fn shr(self, _: B1) -> Self::Output {
self.msb
}
}
impl<U: Unsigned, B: Bit, Ur: Unsigned, Br: Bit> Shr<UInt<Ur, Br>> for UInt<U, B>
where
UInt<Ur, Br>: Sub<B1>,
U: Shr<Sub1<UInt<Ur, Br>>>,
{
type Output = Shright<U, Sub1<UInt<Ur, Br>>>;
#[inline]
fn shr(self, rhs: UInt<Ur, Br>) -> Self::Output {
self.msb.shr(rhs - B1)
}
}
impl<U: Unsigned, B: Bit> Mul<B0> for UInt<U, B> {
type Output = UTerm;
#[inline]
fn mul(self, _: B0) -> Self::Output {
UTerm
}
}
impl Mul<B0> for UTerm {
type Output = UTerm;
#[inline]
fn mul(self, _: B0) -> Self::Output {
UTerm
}
}
impl Mul<B1> for UTerm {
type Output = UTerm;
#[inline]
fn mul(self, _: B1) -> Self::Output {
UTerm
}
}
impl<U: Unsigned, B: Bit> Mul<B1> for UInt<U, B> {
type Output = UInt<U, B>;
#[inline]
fn mul(self, _: B1) -> Self::Output {
UInt::new()
}
}
impl<U: Unsigned, B: Bit> Mul<UTerm> for UInt<U, B> {
type Output = UTerm;
#[inline]
fn mul(self, _: UTerm) -> Self::Output {
UTerm
}
}
impl<U: Unsigned> Mul<U> for UTerm {
type Output = UTerm;
#[inline]
fn mul(self, _: U) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B0>
where
Ul: Mul<UInt<Ur, B>>,
{
type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
#[inline]
fn mul(self, rhs: UInt<Ur, B>) -> Self::Output {
UInt {
msb: self.msb * rhs,
lsb: B0,
}
}
}
impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B1>
where
Ul: Mul<UInt<Ur, B>>,
UInt<Prod<Ul, UInt<Ur, B>>, B0>: Add<UInt<Ur, B>>,
{
type Output = Sum<UInt<Prod<Ul, UInt<Ur, B>>, B0>, UInt<Ur, B>>;
#[inline]
fn mul(self, rhs: UInt<Ur, B>) -> Self::Output {
UInt {
msb: self.msb * rhs,
lsb: B0,
} + rhs
}
}
impl Cmp<UTerm> for UTerm {
type Output = Equal;
#[inline]
fn compare<IM: InternalMarker>(&self, _: &UTerm) -> Self::Output {
Equal
}
}
impl<U: Unsigned, B: Bit> Cmp<UTerm> for UInt<U, B> {
type Output = Greater;
#[inline]
fn compare<IM: InternalMarker>(&self, _: &UTerm) -> Self::Output {
Greater
}
}
impl<U: Unsigned, B: Bit> Cmp<UInt<U, B>> for UTerm {
type Output = Less;
#[inline]
fn compare<IM: InternalMarker>(&self, _: &UInt<U, B>) -> Self::Output {
Less
}
}
impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B0>> for UInt<Ul, B0>
where
Ul: PrivateCmp<Ur, Equal>,
{
type Output = PrivateCmpOut<Ul, Ur, Equal>;
#[inline]
fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B0>) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Equal)
}
}
impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B1>> for UInt<Ul, B1>
where
Ul: PrivateCmp<Ur, Equal>,
{
type Output = PrivateCmpOut<Ul, Ur, Equal>;
#[inline]
fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B1>) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Equal)
}
}
impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B1>> for UInt<Ul, B0>
where
Ul: PrivateCmp<Ur, Less>,
{
type Output = PrivateCmpOut<Ul, Ur, Less>;
#[inline]
fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B1>) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Less)
}
}
impl<Ul: Unsigned, Ur: Unsigned> Cmp<UInt<Ur, B0>> for UInt<Ul, B1>
where
Ul: PrivateCmp<Ur, Greater>,
{
type Output = PrivateCmpOut<Ul, Ur, Greater>;
#[inline]
fn compare<IM: InternalMarker>(&self, rhs: &UInt<Ur, B0>) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Greater)
}
}
impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B0>, SoFar> for UInt<Ul, B0>
where
Ul: Unsigned,
Ur: Unsigned,
SoFar: Ord,
Ul: PrivateCmp<Ur, SoFar>,
{
type Output = PrivateCmpOut<Ul, Ur, SoFar>;
#[inline]
fn private_cmp(&self, rhs: &UInt<Ur, B0>, so_far: SoFar) -> Self::Output {
self.msb.private_cmp(&rhs.msb, so_far)
}
}
impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B1>, SoFar> for UInt<Ul, B1>
where
Ul: Unsigned,
Ur: Unsigned,
SoFar: Ord,
Ul: PrivateCmp<Ur, SoFar>,
{
type Output = PrivateCmpOut<Ul, Ur, SoFar>;
#[inline]
fn private_cmp(&self, rhs: &UInt<Ur, B1>, so_far: SoFar) -> Self::Output {
self.msb.private_cmp(&rhs.msb, so_far)
}
}
impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B1>, SoFar> for UInt<Ul, B0>
where
Ul: Unsigned,
Ur: Unsigned,
SoFar: Ord,
Ul: PrivateCmp<Ur, Less>,
{
type Output = PrivateCmpOut<Ul, Ur, Less>;
#[inline]
fn private_cmp(&self, rhs: &UInt<Ur, B1>, _: SoFar) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Less)
}
}
impl<Ul, Ur, SoFar> PrivateCmp<UInt<Ur, B0>, SoFar> for UInt<Ul, B1>
where
Ul: Unsigned,
Ur: Unsigned,
SoFar: Ord,
Ul: PrivateCmp<Ur, Greater>,
{
type Output = PrivateCmpOut<Ul, Ur, Greater>;
#[inline]
fn private_cmp(&self, rhs: &UInt<Ur, B0>, _: SoFar) -> Self::Output {
self.msb.private_cmp(&rhs.msb, Greater)
}
}
impl<U: Unsigned, B: Bit, SoFar: Ord> PrivateCmp<UInt<U, B>, SoFar> for UTerm {
type Output = Less;
#[inline]
fn private_cmp(&self, _: &UInt<U, B>, _: SoFar) -> Self::Output {
Less
}
}
impl<U: Unsigned, B: Bit, SoFar: Ord> PrivateCmp<UTerm, SoFar> for UInt<U, B> {
type Output = Greater;
#[inline]
fn private_cmp(&self, _: &UTerm, _: SoFar) -> Self::Output {
Greater
}
}
impl<SoFar: Ord> PrivateCmp<UTerm, SoFar> for UTerm {
type Output = SoFar;
#[inline]
fn private_cmp(&self, _: &UTerm, so_far: SoFar) -> Self::Output {
so_far
}
}
impl<Ul, Bl, Ur, Br> BitDiff<UInt<Ur, Br>> for UInt<Ul, Bl>
where
Ul: Unsigned,
Bl: Bit,
Ur: Unsigned,
Br: Bit,
Ul: BitDiff<Ur>,
{
type Output = BitDiffOut<Ul, Ur>;
}
impl<Ul> BitDiff<UTerm> for Ul
where
Ul: Unsigned + Len,
{
type Output = Length<Ul>;
}
use crate::private::ShiftDiff;
impl<Ul: Unsigned, Ur: Unsigned> ShiftDiff<Ur> for Ul
where
Ur: BitDiff<Ul>,
Ul: Shl<BitDiffOut<Ur, Ul>>,
{
type Output = Shleft<Ul, BitDiffOut<Ur, Ul>>;
}
impl<X: Unsigned, N: Unsigned> Pow<N> for X
where
X: PrivatePow<U1, N>,
{
type Output = PrivatePowOut<X, U1, N>;
#[inline]
fn powi(self, n: N) -> Self::Output {
self.private_pow(U1::new(), n)
}
}
impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U0> for X {
type Output = Y;
#[inline]
fn private_pow(self, y: Y, _: U0) -> Self::Output {
y
}
}
impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U1> for X
where
X: Mul<Y>,
{
type Output = Prod<X, Y>;
#[inline]
fn private_pow(self, y: Y, _: U1) -> Self::Output {
self * y
}
}
impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B0>> for X
where
X: Mul,
Square<X>: PrivatePow<Y, UInt<U, B>>,
{
type Output = PrivatePowOut<Square<X>, Y, UInt<U, B>>;
#[inline]
fn private_pow(self, y: Y, n: UInt<UInt<U, B>, B0>) -> Self::Output {
(self * self).private_pow(y, n.msb)
}
}
impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B1>> for X
where
X: Mul + Mul<Y>,
Square<X>: PrivatePow<Prod<X, Y>, UInt<U, B>>,
{
type Output = PrivatePowOut<Square<X>, Prod<X, Y>, UInt<U, B>>;
#[inline]
fn private_pow(self, y: Y, n: UInt<UInt<U, B>, B1>) -> Self::Output {
(self * self).private_pow(self * y, n.msb)
}
}
#[allow(unused)] type Even<N> = UInt<N, B0>;
type Odd<N> = UInt<N, B1>;
impl Gcd<U0> for U0 {
type Output = U0;
}
impl<X> Gcd<U0> for X
where
X: Unsigned + NonZero,
{
type Output = X;
}
impl<Y> Gcd<Y> for U0
where
Y: Unsigned + NonZero,
{
type Output = Y;
}
impl<Xp, Yp> Gcd<Even<Yp>> for Even<Xp>
where
Xp: Gcd<Yp>,
Even<Xp>: NonZero,
Even<Yp>: NonZero,
{
type Output = UInt<Gcf<Xp, Yp>, B0>;
}
impl<Xp, Yp> Gcd<Even<Yp>> for Odd<Xp>
where
Odd<Xp>: Gcd<Yp>,
Even<Yp>: NonZero,
{
type Output = Gcf<Odd<Xp>, Yp>;
}
impl<Xp, Yp> Gcd<Odd<Yp>> for Even<Xp>
where
Xp: Gcd<Odd<Yp>>,
Even<Xp>: NonZero,
{
type Output = Gcf<Xp, Odd<Yp>>;
}
impl<Xp, Yp> Gcd<Odd<Yp>> for Odd<Xp>
where
Odd<Xp>: Max<Odd<Yp>> + Min<Odd<Yp>>,
Odd<Yp>: Max<Odd<Xp>> + Min<Odd<Xp>>,
Maximum<Odd<Xp>, Odd<Yp>>: Sub<Minimum<Odd<Xp>, Odd<Yp>>>,
Diff<Maximum<Odd<Xp>, Odd<Yp>>, Minimum<Odd<Xp>, Odd<Yp>>>: Gcd<Minimum<Odd<Xp>, Odd<Yp>>>,
{
type Output =
Gcf<Diff<Maximum<Odd<Xp>, Odd<Yp>>, Minimum<Odd<Xp>, Odd<Yp>>>, Minimum<Odd<Xp>, Odd<Yp>>>;
}
#[cfg(test)]
mod gcd_tests {
use super::*;
use crate::consts::*;
macro_rules! gcd_test {
(
$( $a:ident, $b:ident => $c:ident ),* $(,)*
) => {
$(
assert_eq!(<Gcf<$a, $b> as Unsigned>::to_usize(), $c::to_usize());
assert_eq!(<Gcf<$b, $a> as Unsigned>::to_usize(), $c::to_usize());
)*
}
}
#[test]
fn gcd() {
gcd_test! {
U0, U0 => U0,
U0, U42 => U42,
U12, U8 => U4,
U13, U1013 => U1, U9, U26 => U1, U143, U273 => U13,
U117, U273 => U39,
}
}
}
#[allow(missing_docs)]
pub trait GetBit<I> {
#[allow(missing_docs)]
type Output;
#[doc(hidden)]
fn get_bit<IM: InternalMarker>(&self, _: &I) -> Self::Output;
}
#[allow(missing_docs)]
pub type GetBitOut<N, I> = <N as GetBit<I>>::Output;
impl<Un, Bn> GetBit<U0> for UInt<Un, Bn>
where
Bn: Copy,
{
type Output = Bn;
#[inline]
fn get_bit<IM: InternalMarker>(&self, _: &U0) -> Self::Output {
self.lsb
}
}
impl<Un, Bn, Ui, Bi> GetBit<UInt<Ui, Bi>> for UInt<Un, Bn>
where
UInt<Ui, Bi>: Copy + Sub<B1>,
Un: GetBit<Sub1<UInt<Ui, Bi>>>,
{
type Output = GetBitOut<Un, Sub1<UInt<Ui, Bi>>>;
#[inline]
fn get_bit<IM: InternalMarker>(&self, i: &UInt<Ui, Bi>) -> Self::Output {
self.msb.get_bit::<Internal>(&(*i - B1))
}
}
impl<I> GetBit<I> for UTerm {
type Output = B0;
#[inline]
fn get_bit<IM: InternalMarker>(&self, _: &I) -> Self::Output {
B0
}
}
#[test]
fn test_get_bit() {
use crate::consts::*;
use crate::Same;
type T1 = <GetBitOut<U2, U0> as Same<B0>>::Output;
type T2 = <GetBitOut<U2, U1> as Same<B1>>::Output;
type T3 = <GetBitOut<U2, U2> as Same<B0>>::Output;
<T1 as Bit>::to_bool();
<T2 as Bit>::to_bool();
<T3 as Bit>::to_bool();
}
pub trait SetBit<I, B> {
#[allow(missing_docs)]
type Output;
#[doc(hidden)]
fn set_bit<IM: InternalMarker>(self, _: I, _: B) -> Self::Output;
}
pub type SetBitOut<N, I, B> = <N as SetBit<I, B>>::Output;
use crate::private::{PrivateSetBit, PrivateSetBitOut};
impl<N, I, B> SetBit<I, B> for N
where
N: PrivateSetBit<I, B>,
PrivateSetBitOut<N, I, B>: Trim,
{
type Output = TrimOut<PrivateSetBitOut<N, I, B>>;
#[inline]
fn set_bit<IM: InternalMarker>(self, i: I, b: B) -> Self::Output {
self.private_set_bit(i, b).trim()
}
}
impl<Un, Bn, B> PrivateSetBit<U0, B> for UInt<Un, Bn> {
type Output = UInt<Un, B>;
#[inline]
fn private_set_bit(self, _: U0, b: B) -> Self::Output {
UInt {
msb: self.msb,
lsb: b,
}
}
}
impl<Un, Bn, Ui, Bi, B> PrivateSetBit<UInt<Ui, Bi>, B> for UInt<Un, Bn>
where
UInt<Ui, Bi>: Sub<B1>,
Un: PrivateSetBit<Sub1<UInt<Ui, Bi>>, B>,
{
type Output = UInt<PrivateSetBitOut<Un, Sub1<UInt<Ui, Bi>>, B>, Bn>;
#[inline]
fn private_set_bit(self, i: UInt<Ui, Bi>, b: B) -> Self::Output {
UInt {
msb: self.msb.private_set_bit(i - B1, b),
lsb: self.lsb,
}
}
}
impl<I> PrivateSetBit<I, B0> for UTerm {
type Output = UTerm;
#[inline]
fn private_set_bit(self, _: I, _: B0) -> Self::Output {
UTerm
}
}
impl<I> PrivateSetBit<I, B1> for UTerm
where
U1: Shl<I>,
{
type Output = Shleft<U1, I>;
#[inline]
fn private_set_bit(self, i: I, _: B1) -> Self::Output {
<U1 as Shl<I>>::shl(U1::new(), i)
}
}
#[test]
fn test_set_bit() {
use crate::consts::*;
use crate::Same;
type T1 = <SetBitOut<U2, U0, B0> as Same<U2>>::Output;
type T2 = <SetBitOut<U2, U0, B1> as Same<U3>>::Output;
type T3 = <SetBitOut<U2, U1, B0> as Same<U0>>::Output;
type T4 = <SetBitOut<U2, U1, B1> as Same<U2>>::Output;
type T5 = <SetBitOut<U2, U2, B0> as Same<U2>>::Output;
type T6 = <SetBitOut<U2, U2, B1> as Same<U6>>::Output;
type T7 = <SetBitOut<U2, U3, B0> as Same<U2>>::Output;
type T8 = <SetBitOut<U2, U3, B1> as Same<U10>>::Output;
type T9 = <SetBitOut<U2, U4, B0> as Same<U2>>::Output;
type T10 = <SetBitOut<U2, U4, B1> as Same<U18>>::Output;
type T11 = <SetBitOut<U3, U0, B0> as Same<U2>>::Output;
<T1 as Unsigned>::to_u32();
<T2 as Unsigned>::to_u32();
<T3 as Unsigned>::to_u32();
<T4 as Unsigned>::to_u32();
<T5 as Unsigned>::to_u32();
<T6 as Unsigned>::to_u32();
<T7 as Unsigned>::to_u32();
<T8 as Unsigned>::to_u32();
<T9 as Unsigned>::to_u32();
<T10 as Unsigned>::to_u32();
<T11 as Unsigned>::to_u32();
}
#[cfg(tests)]
mod tests {
macro_rules! test_div {
($a:ident / $b:ident = $c:ident) => {{
type R = Quot<$a, $b>;
assert_eq!(<R as Unsigned>::to_usize(), $c::to_usize());
}};
}
#[test]
fn test_div() {
use crate::consts::*;
use crate::{Quot, Same};
test_div!(U0 / U1 = U0);
test_div!(U1 / U1 = U1);
test_div!(U2 / U1 = U2);
test_div!(U3 / U1 = U3);
test_div!(U4 / U1 = U4);
test_div!(U0 / U2 = U0);
test_div!(U1 / U2 = U0);
test_div!(U2 / U2 = U1);
test_div!(U3 / U2 = U1);
test_div!(U4 / U2 = U2);
test_div!(U6 / U2 = U3);
test_div!(U7 / U2 = U3);
type T = <SetBitOut<U0, U1, B1> as Same<U2>>::Output;
<T as Unsigned>::to_u32();
}
}
use core::ops::Div;
impl<Ur: Unsigned, Br: Bit> Div<UInt<Ur, Br>> for UTerm {
type Output = UTerm;
#[inline]
fn div(self, _: UInt<Ur, Br>) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> Div<UInt<Ur, Br>> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: Len,
Length<UInt<Ul, Bl>>: Sub<B1>,
(): PrivateDiv<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>,
{
type Output = PrivateDivQuot<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>;
#[inline]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::suspicious_arithmetic_impl))]
fn div(self, rhs: UInt<Ur, Br>) -> Self::Output {
().private_div_quotient(self, rhs, U0::new(), U0::new(), self.len() - B1)
}
}
use core::ops::Rem;
impl<Ur: Unsigned, Br: Bit> Rem<UInt<Ur, Br>> for UTerm {
type Output = UTerm;
#[inline]
fn rem(self, _: UInt<Ur, Br>) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> Rem<UInt<Ur, Br>> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: Len,
Length<UInt<Ul, Bl>>: Sub<B1>,
(): PrivateDiv<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>,
{
type Output = PrivateDivRem<UInt<Ul, Bl>, UInt<Ur, Br>, U0, U0, Sub1<Length<UInt<Ul, Bl>>>>;
#[inline]
fn rem(self, rhs: UInt<Ur, Br>) -> Self::Output {
().private_div_remainder(self, rhs, UTerm, UTerm, self.len() - B1)
}
}
use crate::private::{PrivateDiv, PrivateDivQuot, PrivateDivRem};
use crate::Compare;
impl<N, D, Q, I> PrivateDiv<N, D, Q, U0, I> for ()
where
N: GetBit<I>,
UInt<UTerm, GetBitOut<N, I>>: Trim,
TrimOut<UInt<UTerm, GetBitOut<N, I>>>: Cmp<D>,
(): PrivateDivIf<
N,
D,
Q,
TrimOut<UInt<UTerm, GetBitOut<N, I>>>,
I,
Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>,
>,
{
type Quotient = PrivateDivIfQuot<
N,
D,
Q,
TrimOut<UInt<UTerm, GetBitOut<N, I>>>,
I,
Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>,
>;
type Remainder = PrivateDivIfRem<
N,
D,
Q,
TrimOut<UInt<UTerm, GetBitOut<N, I>>>,
I,
Compare<TrimOut<UInt<UTerm, GetBitOut<N, I>>>, D>,
>;
#[inline]
fn private_div_quotient(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Quotient
where {
let r = (UInt {
msb: UTerm,
lsb: n.get_bit::<Internal>(&i),
})
.trim();
let r_cmp_d = r.compare::<Internal>(&d);
().private_div_if_quotient(n, d, q, r, i, r_cmp_d)
}
#[inline]
fn private_div_remainder(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Remainder {
let r = (UInt {
msb: UTerm,
lsb: n.get_bit::<Internal>(&i),
})
.trim();
let r_cmp_d = r.compare::<Internal>(&d);
().private_div_if_remainder(n, d, q, r, i, r_cmp_d)
}
}
impl<N, D, Q, Ur, Br, I> PrivateDiv<N, D, Q, UInt<Ur, Br>, I> for ()
where
N: GetBit<I>,
UInt<UInt<Ur, Br>, GetBitOut<N, I>>: Cmp<D>,
(): PrivateDivIf<
N,
D,
Q,
UInt<UInt<Ur, Br>, GetBitOut<N, I>>,
I,
Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>,
>,
{
type Quotient = PrivateDivIfQuot<
N,
D,
Q,
UInt<UInt<Ur, Br>, GetBitOut<N, I>>,
I,
Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>,
>;
type Remainder = PrivateDivIfRem<
N,
D,
Q,
UInt<UInt<Ur, Br>, GetBitOut<N, I>>,
I,
Compare<UInt<UInt<Ur, Br>, GetBitOut<N, I>>, D>,
>;
#[inline]
fn private_div_quotient(self, n: N, d: D, q: Q, r: UInt<Ur, Br>, i: I) -> Self::Quotient {
let r = UInt {
msb: r,
lsb: n.get_bit::<Internal>(&i),
};
let r_cmp_d = r.compare::<Internal>(&d);
().private_div_if_quotient(n, d, q, r, i, r_cmp_d)
}
#[inline]
fn private_div_remainder(self, n: N, d: D, q: Q, r: UInt<Ur, Br>, i: I) -> Self::Remainder {
let r = UInt {
msb: r,
lsb: n.get_bit::<Internal>(&i),
};
let r_cmp_d = r.compare::<Internal>(&d);
().private_div_if_remainder(n, d, q, r, i, r_cmp_d)
}
}
use crate::private::{PrivateDivIf, PrivateDivIfQuot, PrivateDivIfRem};
impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Less> for ()
where
UInt<Ui, Bi>: Sub<B1>,
(): PrivateDiv<N, D, Q, R, Sub1<UInt<Ui, Bi>>>,
{
type Quotient = PrivateDivQuot<N, D, Q, R, Sub1<UInt<Ui, Bi>>>;
type Remainder = PrivateDivRem<N, D, Q, R, Sub1<UInt<Ui, Bi>>>;
#[inline]
fn private_div_if_quotient(
self,
n: N,
d: D,
q: Q,
r: R,
i: UInt<Ui, Bi>,
_: Less,
) -> Self::Quotient
where {
().private_div_quotient(n, d, q, r, i - B1)
}
#[inline]
fn private_div_if_remainder(
self,
n: N,
d: D,
q: Q,
r: R,
i: UInt<Ui, Bi>,
_: Less,
) -> Self::Remainder
where {
().private_div_remainder(n, d, q, r, i - B1)
}
}
impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Equal> for ()
where
UInt<Ui, Bi>: Copy + Sub<B1>,
Q: SetBit<UInt<Ui, Bi>, B1>,
(): PrivateDiv<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>,
{
type Quotient = PrivateDivQuot<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>;
type Remainder = PrivateDivRem<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, U0, Sub1<UInt<Ui, Bi>>>;
#[inline]
fn private_div_if_quotient(
self,
n: N,
d: D,
q: Q,
_: R,
i: UInt<Ui, Bi>,
_: Equal,
) -> Self::Quotient
where {
().private_div_quotient(n, d, q.set_bit::<Internal>(i, B1), U0::new(), i - B1)
}
#[inline]
fn private_div_if_remainder(
self,
n: N,
d: D,
q: Q,
_: R,
i: UInt<Ui, Bi>,
_: Equal,
) -> Self::Remainder
where {
().private_div_remainder(n, d, q.set_bit::<Internal>(i, B1), U0::new(), i - B1)
}
}
use crate::Diff;
impl<N, D, Q, R, Ui, Bi> PrivateDivIf<N, D, Q, R, UInt<Ui, Bi>, Greater> for ()
where
D: Copy,
UInt<Ui, Bi>: Copy + Sub<B1>,
R: Sub<D>,
Q: SetBit<UInt<Ui, Bi>, B1>,
(): PrivateDiv<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>,
{
type Quotient =
PrivateDivQuot<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>;
type Remainder =
PrivateDivRem<N, D, SetBitOut<Q, UInt<Ui, Bi>, B1>, Diff<R, D>, Sub1<UInt<Ui, Bi>>>;
#[inline]
fn private_div_if_quotient(
self,
n: N,
d: D,
q: Q,
r: R,
i: UInt<Ui, Bi>,
_: Greater,
) -> Self::Quotient
where {
().private_div_quotient(n, d, q.set_bit::<Internal>(i, B1), r - d, i - B1)
}
#[inline]
fn private_div_if_remainder(
self,
n: N,
d: D,
q: Q,
r: R,
i: UInt<Ui, Bi>,
_: Greater,
) -> Self::Remainder
where {
().private_div_remainder(n, d, q.set_bit::<Internal>(i, B1), r - d, i - B1)
}
}
impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Less> for () {
type Quotient = Q;
type Remainder = R;
#[inline]
fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, _: U0, _: Less) -> Self::Quotient {
q
}
#[inline]
fn private_div_if_remainder(self, _: N, _: D, _: Q, r: R, _: U0, _: Less) -> Self::Remainder {
r
}
}
impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Equal> for ()
where
Q: SetBit<U0, B1>,
{
type Quotient = SetBitOut<Q, U0, B1>;
type Remainder = U0;
#[inline]
fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Equal) -> Self::Quotient {
q.set_bit::<Internal>(i, B1)
}
#[inline]
fn private_div_if_remainder(self, _: N, _: D, _: Q, _: R, i: U0, _: Equal) -> Self::Remainder {
i
}
}
impl<N, D, Q, R> PrivateDivIf<N, D, Q, R, U0, Greater> for ()
where
R: Sub<D>,
Q: SetBit<U0, B1>,
{
type Quotient = SetBitOut<Q, U0, B1>;
type Remainder = Diff<R, D>;
#[inline]
fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Greater) -> Self::Quotient {
q.set_bit::<Internal>(i, B1)
}
#[inline]
fn private_div_if_remainder(
self,
_: N,
d: D,
_: Q,
r: R,
_: U0,
_: Greater,
) -> Self::Remainder {
r - d
}
}
use crate::{PartialDiv, Quot};
impl<Ur: Unsigned, Br: Bit> PartialDiv<UInt<Ur, Br>> for UTerm {
type Output = UTerm;
#[inline]
fn partial_div(self, _: UInt<Ur, Br>) -> Self::Output {
UTerm
}
}
impl<Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit> PartialDiv<UInt<Ur, Br>> for UInt<Ul, Bl>
where
UInt<Ul, Bl>: Div<UInt<Ur, Br>> + Rem<UInt<Ur, Br>, Output = U0>,
{
type Output = Quot<UInt<Ul, Bl>, UInt<Ur, Br>>;
#[inline]
fn partial_div(self, rhs: UInt<Ur, Br>) -> Self::Output {
self / rhs
}
}
use crate::private::{PrivateMin, PrivateMinOut};
impl<U, B, Ur> PrivateMin<Ur, Equal> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = UInt<U, B>;
#[inline]
fn private_min(self, _: Ur) -> Self::Output {
self
}
}
impl<U, B, Ur> PrivateMin<Ur, Less> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = UInt<U, B>;
#[inline]
fn private_min(self, _: Ur) -> Self::Output {
self
}
}
impl<U, B, Ur> PrivateMin<Ur, Greater> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = Ur;
#[inline]
fn private_min(self, rhs: Ur) -> Self::Output {
rhs
}
}
use crate::Min;
impl<U> Min<U> for UTerm
where
U: Unsigned,
{
type Output = UTerm;
#[inline]
fn min(self, _: U) -> Self::Output {
self
}
}
impl<U, B, Ur> Min<Ur> for UInt<U, B>
where
U: Unsigned,
B: Bit,
Ur: Unsigned,
UInt<U, B>: Cmp<Ur> + PrivateMin<Ur, Compare<UInt<U, B>, Ur>>,
{
type Output = PrivateMinOut<UInt<U, B>, Ur, Compare<UInt<U, B>, Ur>>;
#[inline]
fn min(self, rhs: Ur) -> Self::Output {
self.private_min(rhs)
}
}
use crate::private::{PrivateMax, PrivateMaxOut};
impl<U, B, Ur> PrivateMax<Ur, Equal> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = UInt<U, B>;
#[inline]
fn private_max(self, _: Ur) -> Self::Output {
self
}
}
impl<U, B, Ur> PrivateMax<Ur, Less> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = Ur;
#[inline]
fn private_max(self, rhs: Ur) -> Self::Output {
rhs
}
}
impl<U, B, Ur> PrivateMax<Ur, Greater> for UInt<U, B>
where
Ur: Unsigned,
U: Unsigned,
B: Bit,
{
type Output = UInt<U, B>;
#[inline]
fn private_max(self, _: Ur) -> Self::Output {
self
}
}
use crate::Max;
impl<U> Max<U> for UTerm
where
U: Unsigned,
{
type Output = U;
#[inline]
fn max(self, rhs: U) -> Self::Output {
rhs
}
}
impl<U, B, Ur> Max<Ur> for UInt<U, B>
where
U: Unsigned,
B: Bit,
Ur: Unsigned,
UInt<U, B>: Cmp<Ur> + PrivateMax<Ur, Compare<UInt<U, B>, Ur>>,
{
type Output = PrivateMaxOut<UInt<U, B>, Ur, Compare<UInt<U, B>, Ur>>;
#[inline]
fn max(self, rhs: Ur) -> Self::Output {
self.private_max(rhs)
}
}
impl<N> SquareRoot for N
where
N: PrivateSquareRoot,
{
type Output = <Self as PrivateSquareRoot>::Output;
}
impl PrivateSquareRoot for UTerm {
type Output = UTerm;
}
impl PrivateSquareRoot for UInt<UTerm, B1> {
type Output = UInt<UTerm, B1>;
}
impl<U, Ba, Bb> PrivateSquareRoot for UInt<UInt<U, Ba>, Bb>
where
U: Unsigned,
Ba: Bit,
Bb: Bit,
U: SquareRoot,
Sqrt<U>: Shl<B1>,
Double<Sqrt<U>>: Add<B1>,
Add1<Double<Sqrt<U>>>: Mul,
Self: IsGreaterOrEqual<Square<Add1<Double<Sqrt<U>>>>>,
Double<Sqrt<U>>: Add<GrEq<Self, Square<Add1<Double<Sqrt<U>>>>>>,
{
type Output = Sum<Double<Sqrt<U>>, GrEq<Self, Square<Add1<Double<Sqrt<U>>>>>>;
}
#[test]
fn sqrt_test() {
use crate::consts::*;
assert_eq!(0, <Sqrt<U0>>::to_u32());
assert_eq!(1, <Sqrt<U1>>::to_u32());
assert_eq!(1, <Sqrt<U2>>::to_u32());
assert_eq!(1, <Sqrt<U3>>::to_u32());
assert_eq!(2, <Sqrt<U4>>::to_u32());
assert_eq!(2, <Sqrt<U5>>::to_u32());
assert_eq!(2, <Sqrt<U6>>::to_u32());
assert_eq!(2, <Sqrt<U7>>::to_u32());
assert_eq!(2, <Sqrt<U8>>::to_u32());
assert_eq!(3, <Sqrt<U9>>::to_u32());
assert_eq!(3, <Sqrt<U10>>::to_u32());
assert_eq!(3, <Sqrt<U11>>::to_u32());
assert_eq!(3, <Sqrt<U12>>::to_u32());
assert_eq!(3, <Sqrt<U13>>::to_u32());
assert_eq!(3, <Sqrt<U14>>::to_u32());
assert_eq!(3, <Sqrt<U15>>::to_u32());
assert_eq!(4, <Sqrt<U16>>::to_u32());
assert_eq!(4, <Sqrt<U17>>::to_u32());
assert_eq!(4, <Sqrt<U18>>::to_u32());
assert_eq!(4, <Sqrt<U19>>::to_u32());
assert_eq!(4, <Sqrt<U20>>::to_u32());
assert_eq!(4, <Sqrt<U21>>::to_u32());
assert_eq!(4, <Sqrt<U22>>::to_u32());
assert_eq!(4, <Sqrt<U23>>::to_u32());
assert_eq!(4, <Sqrt<U24>>::to_u32());
assert_eq!(5, <Sqrt<U25>>::to_u32());
assert_eq!(5, <Sqrt<U26>>::to_u32());
}
impl<N> Logarithm2 for N
where
N: PrivateLogarithm2,
{
type Output = <Self as PrivateLogarithm2>::Output;
}
impl PrivateLogarithm2 for UInt<UTerm, B1> {
type Output = U0;
}
impl<U, B> PrivateLogarithm2 for UInt<U, B>
where
U: Unsigned + Logarithm2,
B: Bit,
Log2<U>: Add<B1>,
{
type Output = Add1<Log2<U>>;
}
impl ToInt<i8> for UTerm {
#[inline]
fn to_int() -> i8 {
Self::I8
}
}
impl ToInt<i16> for UTerm {
#[inline]
fn to_int() -> i16 {
Self::I16
}
}
impl ToInt<i32> for UTerm {
#[inline]
fn to_int() -> i32 {
Self::I32
}
}
impl ToInt<i64> for UTerm {
#[inline]
fn to_int() -> i64 {
Self::I64
}
}
impl ToInt<u8> for UTerm {
#[inline]
fn to_int() -> u8 {
Self::U8
}
}
impl ToInt<u16> for UTerm {
#[inline]
fn to_int() -> u16 {
Self::U16
}
}
impl ToInt<u32> for UTerm {
#[inline]
fn to_int() -> u32 {
Self::U32
}
}
impl ToInt<u64> for UTerm {
#[inline]
fn to_int() -> u64 {
Self::U64
}
}
impl ToInt<usize> for UTerm {
#[inline]
fn to_int() -> usize {
Self::USIZE
}
}
impl<U, B> ToInt<i8> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> i8 {
Self::I8
}
}
impl<U, B> ToInt<i16> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> i16 {
Self::I16
}
}
impl<U, B> ToInt<i32> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> i32 {
Self::I32
}
}
impl<U, B> ToInt<i64> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> i64 {
Self::I64
}
}
impl<U, B> ToInt<u8> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> u8 {
Self::U8
}
}
impl<U, B> ToInt<u16> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> u16 {
Self::U16
}
}
impl<U, B> ToInt<u32> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> u32 {
Self::U32
}
}
impl<U, B> ToInt<u64> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> u64 {
Self::U64
}
}
impl<U, B> ToInt<usize> for UInt<U, B>
where
U: Unsigned,
B: Bit,
{
#[inline]
fn to_int() -> usize {
Self::USIZE
}
}
#[cfg(test)]
mod tests {
use crate::consts::*;
use crate::{Log2, ToInt, Unsigned};
#[test]
fn log2_test() {
assert_eq!(0, <Log2<U1>>::to_u32());
assert_eq!(1, <Log2<U2>>::to_u32());
assert_eq!(1, <Log2<U3>>::to_u32());
assert_eq!(2, <Log2<U4>>::to_u32());
assert_eq!(2, <Log2<U5>>::to_u32());
assert_eq!(2, <Log2<U6>>::to_u32());
assert_eq!(2, <Log2<U7>>::to_u32());
assert_eq!(3, <Log2<U8>>::to_u32());
assert_eq!(3, <Log2<U9>>::to_u32());
assert_eq!(3, <Log2<U10>>::to_u32());
assert_eq!(3, <Log2<U11>>::to_u32());
assert_eq!(3, <Log2<U12>>::to_u32());
assert_eq!(3, <Log2<U13>>::to_u32());
assert_eq!(3, <Log2<U14>>::to_u32());
assert_eq!(3, <Log2<U15>>::to_u32());
assert_eq!(4, <Log2<U16>>::to_u32());
assert_eq!(4, <Log2<U17>>::to_u32());
assert_eq!(4, <Log2<U18>>::to_u32());
assert_eq!(4, <Log2<U19>>::to_u32());
assert_eq!(4, <Log2<U20>>::to_u32());
assert_eq!(4, <Log2<U21>>::to_u32());
assert_eq!(4, <Log2<U22>>::to_u32());
assert_eq!(4, <Log2<U23>>::to_u32());
assert_eq!(4, <Log2<U24>>::to_u32());
assert_eq!(4, <Log2<U25>>::to_u32());
assert_eq!(4, <Log2<U26>>::to_u32());
assert_eq!(4, <Log2<U27>>::to_u32());
assert_eq!(4, <Log2<U28>>::to_u32());
assert_eq!(4, <Log2<U29>>::to_u32());
assert_eq!(4, <Log2<U30>>::to_u32());
assert_eq!(4, <Log2<U31>>::to_u32());
assert_eq!(5, <Log2<U32>>::to_u32());
assert_eq!(5, <Log2<U33>>::to_u32());
}
#[test]
fn uint_toint_test() {
assert_eq!(0_i8, U0::to_int());
assert_eq!(1_i8, U1::to_int());
assert_eq!(2_i8, U2::to_int());
assert_eq!(3_i8, U3::to_int());
assert_eq!(4_i8, U4::to_int());
assert_eq!(0_i16, U0::to_int());
assert_eq!(1_i16, U1::to_int());
assert_eq!(2_i16, U2::to_int());
assert_eq!(3_i16, U3::to_int());
assert_eq!(4_i16, U4::to_int());
assert_eq!(0_i32, U0::to_int());
assert_eq!(1_i32, U1::to_int());
assert_eq!(2_i32, U2::to_int());
assert_eq!(3_i32, U3::to_int());
assert_eq!(4_i32, U4::to_int());
assert_eq!(0_i64, U0::to_int());
assert_eq!(1_i64, U1::to_int());
assert_eq!(2_i64, U2::to_int());
assert_eq!(3_i64, U3::to_int());
assert_eq!(4_i64, U4::to_int());
assert_eq!(0_u8, U0::to_int());
assert_eq!(1_u8, U1::to_int());
assert_eq!(2_u8, U2::to_int());
assert_eq!(3_u8, U3::to_int());
assert_eq!(4_u8, U4::to_int());
assert_eq!(0_u16, U0::to_int());
assert_eq!(1_u16, U1::to_int());
assert_eq!(2_u16, U2::to_int());
assert_eq!(3_u16, U3::to_int());
assert_eq!(4_u16, U4::to_int());
assert_eq!(0_u32, U0::to_int());
assert_eq!(1_u32, U1::to_int());
assert_eq!(2_u32, U2::to_int());
assert_eq!(3_u32, U3::to_int());
assert_eq!(4_u32, U4::to_int());
assert_eq!(0_u64, U0::to_int());
assert_eq!(1_u64, U1::to_int());
assert_eq!(2_u64, U2::to_int());
assert_eq!(3_u64, U3::to_int());
assert_eq!(4_u64, U4::to_int());
assert_eq!(0_usize, U0::to_int());
assert_eq!(1_usize, U1::to_int());
assert_eq!(2_usize, U2::to_int());
assert_eq!(3_usize, U3::to_int());
assert_eq!(4_usize, U4::to_int());
}
}