1use crate::{
2 bool::{self, Bool},
3 num::bit::{self, Bit, B0, B1},
4 seal, Invalid,
5};
6use std::marker;
7
8pub type If<C, A, B> = <C as Bool>::Ifuint<A, B>;
9
10pub trait Unsigned: seal::Sealed {
11 const USIZE: usize;
13
14 #[doc(hidden)]
15 type Msb: Unsigned;
16 #[doc(hidden)]
17 type Lsb: Bit;
18
19 #[doc(hidden)]
20 type Bsr: Unsigned;
21 #[doc(hidden)]
22 type Bsl: Unsigned;
23
24 #[doc(hidden)]
25 type Inc: Unsigned;
26 #[doc(hidden)]
27 type Dec: Unsigned;
28 #[doc(hidden)]
29 type Add<Rhs: Unsigned>: Unsigned;
30 #[doc(hidden)]
31 type AddWithCarry<Rhs: Unsigned, C: Bit>: Unsigned;
32 #[doc(hidden)]
33 type Sub<Rhs: Unsigned>: Unsigned;
34 #[doc(hidden)]
35 type SubWithBorrow<Rhs: Unsigned, B: Bit>: Unsigned;
36 #[doc(hidden)]
37 type IsZero: Bool;
38 #[doc(hidden)]
39 type RmExtraBits: Unsigned;
40 #[doc(hidden)]
41 type Mul<Rhs: Unsigned>: Unsigned;
42}
43
44pub type Msb<U> = <U as Unsigned>::Msb;
46pub type Lsb<U> = <U as Unsigned>::Lsb;
48pub type Bsr<U> = <U as Unsigned>::Bsr;
50pub type Bsl<U> = <U as Unsigned>::Bsl;
52pub type Inc<U> = <U as Unsigned>::Inc;
54pub type Dec<U> = <U as Unsigned>::Dec;
56pub type Add<Lhs, Rhs> = <Lhs as Unsigned>::Add<Rhs>;
58pub type AddWithCarry<Lhs, Rhs, C> = <Lhs as Unsigned>::AddWithCarry<Rhs, C>;
60pub type Sub<Lhs, Rhs> = <Lhs as Unsigned>::Sub<Rhs>;
62pub type SubWithBorrow<Lhs, Rhs, B> = <Lhs as Unsigned>::SubWithBorrow<Rhs, B>;
64pub type IsZero<U> = <U as Unsigned>::IsZero;
66pub type RmExtraBits<U> = <U as Unsigned>::RmExtraBits;
68pub type Mul<Lhs, Rhs> = <Lhs as Unsigned>::Mul<Rhs>;
70
71#[derive(Default)]
73pub struct UInt<Msbs: Unsigned, Lsb: Bit>(marker::PhantomData<(Msbs, Lsb)>);
74impl<Msbs: Unsigned, Lsb: Bit> seal::Sealed for UInt<Msbs, Lsb> {}
75
76#[derive(Default)]
78pub struct Last<B: Bit>(marker::PhantomData<B>);
79impl<B: Bit> seal::Sealed for Last<B> {}
80
81#[macro_export]
86macro_rules! uint {
87 ($ty:ident $(, $rest:ident)*) => {
88 uint!(@parse input: [$($rest),*], out: [Last<$ty>])
89 };
90
91 (@parse input: [$ty:ident $(, $rest:ident)*], out: [$($out:tt)*]) => {
92 uint!(@parse input: [$($rest),*], out: [UInt<$($out)*, $ty>])
93 };
94 (@parse input: [], out: [$($out:tt)*]) => {
95 $($out)*
96 };
97}
98
99impl Unsigned for Invalid {
100 #[doc(hidden)]
101 const USIZE: usize = { panic!("Invlid Unsigned Value!") };
102 type Msb = Invalid;
103 type Lsb = Invalid;
104
105 type Bsr = Invalid;
106 type Bsl = Invalid;
107
108 type Inc = Invalid;
109 type Dec = Invalid;
110
111 type Add<Rhs: Unsigned> = Invalid;
112 type AddWithCarry<Rhs: Unsigned, C: Bit> = Invalid;
113
114 type Sub<Rhs: Unsigned> = Invalid;
115 type SubWithBorrow<Rhs: Unsigned, B: Bit> = Invalid;
116
117 type IsZero = Invalid;
118 type RmExtraBits = Invalid;
119 type Mul<Rhs: Unsigned> = Invalid;
120}
121
122impl<Lsb_: Bit> Unsigned for Last<Lsb_> {
123 const USIZE: usize = Lsb_::USIZE;
124 type Lsb = Lsb_;
125 type Msb = Invalid; type Inc = If<bit::IsZero<Lsb_>, Last<B1>, UInt<Self, B0>>;
128 type Dec = If<bit::IsZero<Lsb_>, Invalid, Last<B0>>;
129
130 type Bsr = Last<B0>;
131 type Bsl = If<bit::IsZero<Lsb_>, Last<B0>, UInt<Self, B0>>;
132
133 type Add<Rhs: Unsigned> = If<bit::IsZero<Lsb_>, Rhs, Inc<Rhs>>;
134 type AddWithCarry<Rhs: Unsigned, C: Bit> = UInt<
135 If<
136 bit::IsZero<bit::FullCarry<Lsb_, Lsb<Rhs>, C>>,
137 Rhs::Msb,
138 Inc<Rhs::Msb>,
139 >,
140 bit::FullAdd<Lsb_, Lsb<Rhs>, C>,
141 >;
142
143 type Sub<Rhs: Unsigned> = If<bit::IsZero<Lsb_>, Rhs, Dec<Rhs>>;
144 type SubWithBorrow<Rhs: Unsigned, B: Bit> = If<
145 bit::IsZero<Lsb_>,
146 Sub<Rhs, Last<B>>,
147 Sub<Dec<Rhs>, Last<B>>,
148 >;
149
150 type IsZero = bit::IsZero<Lsb_>;
151 type RmExtraBits = Self;
152 type Mul<Rhs: Unsigned> = If<bit::IsZero<Lsb_>, Last<B0>, Rhs>;
153}
154
155impl<Msbs: Unsigned, Lsb_: Bit> Unsigned for UInt<Msbs, Lsb_> {
156 const USIZE: usize = { (Msbs::USIZE << 1) | Lsb_::USIZE };
157 type Msb = Msbs;
158 type Lsb = Lsb_;
159 type Bsr = Msbs;
160 type Bsl = UInt<Self, B0>;
161
162 type Inc =
163 If<bit::IsZero<Lsb_>, UInt<Msbs, B1>, UInt<Inc<Msbs>, B0>>;
164 type Dec =
165 If<bit::IsZero<Lsb_>, UInt<Dec<Msbs>, B1>, UInt<Msbs, B0>>;
166
167 type Add<Rhs: Unsigned> = AddWithCarry<Self, Rhs, B0>;
168 type AddWithCarry<Rhs: Unsigned, C: Bit> = UInt<
169 AddWithCarry<Msbs, Rhs::Msb, bit::FullCarry<Lsb_, Rhs::Lsb, C>>,
170 bit::FullAdd<Lsb_, Lsb<Rhs>, C>,
171 >;
172
173 type Sub<Rhs: Unsigned> = RmExtraBits<SubWithBorrow<Self, Rhs, B0>>;
174 type SubWithBorrow<Rhs: Unsigned, B: Bit> = UInt<
175 SubWithBorrow<Msbs, Msb<Rhs>, bit::FullBorrow<Lsb_, Rhs::Lsb, B>>,
176 bit::FullDiff<Lsb_, Lsb<Rhs>, B>,
177 >;
178
179 type IsZero = bool::And<bit::IsZero<Lsb_>, Msbs::IsZero>;
180 type RmExtraBits =
181 If<Self::IsZero, Last<B0>, UInt<RmExtraBits<Msbs>, Lsb_>>;
182 type Mul<Rhs: Unsigned> =
183 Add<If<bit::IsZero<Lsb_>, Last<B0>, Rhs>, Bsl<Mul<Msbs, Rhs>>>;
184}
185
186pub type U0 = uint!(B0);
187pub type U1 = uint!(B1);
188pub type U2 = uint!(B1, B0);
189pub type U3 = uint!(B1, B1);
190pub type U4 = uint!(B1, B0, B0);
191pub type U5 = uint!(B1, B0, B1);
192pub type U6 = uint!(B1, B1, B0);
193pub type U7 = uint!(B1, B1, B1);
194pub type U8 = uint!(B1, B0, B0, B0);
195pub type U9 = uint!(B1, B0, B0, B1);
196pub type U10 = uint!(B1, B0, B1, B0);
197pub type U11 = uint!(B1, B0, B1, B1);
198pub type U12 = uint!(B1, B1, B0, B0);
199pub type U13 = uint!(B1, B1, B0, B1);
200pub type U14 = uint!(B1, B1, B1, B0);
201pub type U15 = uint!(B1, B1, B1, B1);
202pub type U16 = uint!(B1, B0, B0, B0, B0);
203pub type U17 = uint!(B1, B0, B0, B0, B1);
204pub type U18 = uint!(B1, B0, B0, B1, B0);
205pub type U19 = uint!(B1, B0, B0, B1, B1);
206pub type U20 = uint!(B1, B0, B1, B0, B0);
207pub type U21 = uint!(B1, B0, B1, B0, B1);
208pub type U22 = uint!(B1, B0, B1, B1, B0);
209pub type U23 = uint!(B1, B0, B1, B1, B1);
210pub type U24 = uint!(B1, B1, B0, B0, B0);
211pub type U25 = uint!(B1, B1, B0, B0, B1);
212pub type U26 = uint!(B1, B1, B0, B1, B0);
213pub type U27 = uint!(B1, B1, B0, B1, B1);
214pub type U28 = uint!(B1, B1, B1, B0, B0);
215pub type U29 = uint!(B1, B1, B1, B0, B1);
216pub type U30 = uint!(B1, B1, B1, B1, B0);
217pub type U31 = uint!(B1, B1, B1, B1, B1);
218pub type U32 = uint!(B1, B0, B0, B0, B0, B0);
219
220#[cfg(test)]
221mod test {
222 use super::*;
223
224 fn test_pair<A: Unsigned, B: Unsigned>() {
225 assert_eq!(A::USIZE, B::USIZE);
226 }
227
228 #[test]
229 fn test_two() {
230 test_pair::<<U1 as Unsigned>::Add<U2>, U3>();
231 test_pair::<<U2 as Unsigned>::Sub<U2>, U0>();
232 test_pair::<<U4 as Unsigned>::Mul<U3>, U12>();
233 test_pair::<<U8 as Unsigned>::Bsl, U16>();
234 test_pair::<<U8 as Unsigned>::Bsr, U4>();
235 }
236}