typers/num/
unsigned.rs

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    /// The value equivalent of `Self`
12    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
44/// The most significant bits of `Self`.
45pub type Msb<U> = <U as Unsigned>::Msb;
46/// The least significant bit of `Self`.
47pub type Lsb<U> = <U as Unsigned>::Lsb;
48/// The result of bit shifting right on `Self`.
49pub type Bsr<U> = <U as Unsigned>::Bsr;
50/// The result of bit shifting left on `Self`.
51pub type Bsl<U> = <U as Unsigned>::Bsl;
52/// The result of incrementing `Self`.
53pub type Inc<U> = <U as Unsigned>::Inc;
54/// The result of decrementing `Self`.
55pub type Dec<U> = <U as Unsigned>::Dec;
56/// Result of adding `Self` with `Rhs`.
57pub type Add<Lhs, Rhs> = <Lhs as Unsigned>::Add<Rhs>;
58/// Result of adding `Self` with `Rhs` and a carry bit.
59pub type AddWithCarry<Lhs, Rhs, C> = <Lhs as Unsigned>::AddWithCarry<Rhs, C>;
60/// Result of substracting `Self` with `Rhs`.
61pub type Sub<Lhs, Rhs> = <Lhs as Unsigned>::Sub<Rhs>;
62/// Result of substracting`Self` with `Rhs` and a borrow bit.
63pub type SubWithBorrow<Lhs, Rhs, B> = <Lhs as Unsigned>::SubWithBorrow<Rhs, B>;
64/// Check if the Unsigned is zero.
65pub type IsZero<U> = <U as Unsigned>::IsZero;
66/// Remove the extra zero bits that can occur durring computation.
67pub type RmExtraBits<U> = <U as Unsigned>::RmExtraBits;
68/// Result of multiplying `Self` with `Rhs`.
69pub type Mul<Lhs, Rhs> = <Lhs as Unsigned>::Mul<Rhs>;
70
71/// `Uint` is represented as a list of bits.
72#[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/// `Msb` is the most significant bit of the Uint.
77#[derive(Default)]
78pub struct Last<B: Bit>(marker::PhantomData<B>);
79impl<B: Bit> seal::Sealed for Last<B> {}
80
81/// A macro to define simle Unsigned types with just the bits.
82/// ```ignore
83/// type U10 = uint!(B1, B0, B1, B0);
84/// ```
85#[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; // Shouldn't be accessed.
126
127    type Inc = If<bit::IsZero<Lsb_>, /*Then*/ Last<B1>, /*Else*/ UInt<Self, B0>>;
128    type Dec = If<bit::IsZero<Lsb_>, /*Then*/ Invalid, /*Else*/ Last<B0>>;
129
130    type Bsr = Last<B0>;
131    type Bsl = If<bit::IsZero<Lsb_>, /*Then*/ Last<B0>, UInt<Self, B0>>;
132
133    type Add<Rhs: Unsigned> = If<bit::IsZero<Lsb_>, /*Then*/ Rhs, /*Else*/ Inc<Rhs>>;
134    type AddWithCarry<Rhs: Unsigned, C: Bit> = UInt<
135        If<
136            bit::IsZero<bit::FullCarry<Lsb_, Lsb<Rhs>, C>>,
137            /*Then*/ Rhs::Msb,
138            /*Else*/ Inc<Rhs::Msb>,
139        >,
140        bit::FullAdd<Lsb_, Lsb<Rhs>, C>,
141    >;
142
143    type Sub<Rhs: Unsigned> = If<bit::IsZero<Lsb_>, /*Then*/ Rhs, /*Else*/ Dec<Rhs>>;
144    type SubWithBorrow<Rhs: Unsigned, B: Bit> = If<
145        bit::IsZero<Lsb_>,
146        /*Then*/ Sub<Rhs, Last<B>>,
147        /*Else*/ 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_>, /*Then*/ UInt<Msbs, B1>, /*Else*/ UInt<Inc<Msbs>, B0>>;
164    type Dec =
165        If<bit::IsZero<Lsb_>, /*Then*/ UInt<Dec<Msbs>, B1>, /*Else*/ 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, /*Then*/ Last<B0>, /*Else*/ UInt<RmExtraBits<Msbs>, Lsb_>>;
182    type Mul<Rhs: Unsigned> =
183        Add<If<bit::IsZero<Lsb_>, /*Then*/ Last<B0>, /*Else*/ 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}