const_arithmetic/integer.rs
1//! This implements the integer trait which denotes a 32 bit unsigned integer
2
3
4use super::binary::*;
5use super::hex::*;
6use std::marker::PhantomData;
7
8mod impls;
9use impls::*;
10
11/// A struct which generics represents an unique integer from 0 to 2 ** 32 - 1
12///
13/// Example
14/// ```
15/// use const_arithmetic::*;
16/// let a = parse_integer!(3);
17/// // a has type TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>
18/// ```
19#[derive(Clone, Copy)]
20pub struct TypedInteger<H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex> {
21 pub _m0: PhantomData<H0>,
22 pub _m1: PhantomData<H1>,
23 pub _m2: PhantomData<H2>,
24 pub _m3: PhantomData<H3>,
25 pub _m4: PhantomData<H4>,
26 pub _m5: PhantomData<H5>,
27 pub _m6: PhantomData<H6>,
28 pub _m7: PhantomData<H7>
29}
30
31impl<H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex> TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> {
32 /// Returns the value of the Typed integer
33 ///
34 /// Example
35 /// ```
36 /// use const_arithmetic::*;
37 /// let a = parse_integer!(3);
38 /// assert_eq!(a.number(), 3);
39 /// ```
40 pub const fn number() -> u32 {
41 H0::NUMBER + 16 * H1::NUMBER + 256 * H2::NUMBER + 4096 * H3::NUMBER + 65536 * H4::NUMBER + 1048576 * H5::NUMBER + 16777216 * H6::NUMBER + 268435456 * H7::NUMBER
42 }
43}
44
45/// A trait that denotes whether something is an integer
46/// Example
47/// ```
48/// use const_arithmetic::*;
49/// let a = parse_integer!(3);
50///
51/// // This verifies that a is 3
52/// fn is_3<T>(_a: T) where
53/// T: IsInteger,
54/// T: TypedAssertEqual<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>>
55/// {}
56///
57/// is_3(a);
58/// ```
59pub trait IsInteger: Copy {
60 type Hex0: Hex; type Hex1: Hex; type Hex2: Hex; type Hex3: Hex; type Hex4: Hex; type Hex5: Hex; type Hex6: Hex; type Hex7: Hex;
61 fn number() -> u32;
62}
63
64impl<H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex> IsInteger for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> {
65 type Hex0 = H0; type Hex1 = H1; type Hex2 = H2; type Hex3 = H3; type Hex4 = H4; type Hex5 = H5; type Hex6 = H6; type Hex7 = H7;
66 fn number() -> u32 {
67 H0::NUMBER + 16 * H1::NUMBER + 256 * H2::NUMBER + 4096 * H3::NUMBER + 65536 * H4::NUMBER + 1048576 * H5::NUMBER + 16777216 * H6::NUMBER + 268435456 * H7::NUMBER
68 }
69}
70
71/// A trait that asserts two integers are equal
72/// Example
73/// ```
74/// use const_arithmetic::*;
75/// let a = parse_integer!(3);
76///
77/// // This verifies that a is 3
78/// fn is_3<T>(_a: T) where
79/// T: IsInteger,
80/// T: TypedAssertEqual<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>>
81/// {}
82///
83/// is_3(a);
84/// ```
85pub trait TypedAssertEqual<N: IsInteger> {}
86impl<N: IsInteger> TypedAssertEqual<N> for TypedInteger<N::Hex0, N::Hex1, N::Hex2, N::Hex3, N::Hex4, N::Hex5, N::Hex6, N::Hex7> {}
87
88/// A trait that returns a binary depending on whether two integers are equal
89///
90/// Example
91/// ```
92/// use const_arithmetic::*;
93/// let a = parse_integer!(3);
94///
95/// // This verifies that a <= 5 but not a < 3
96/// fn example<T, R, S>(_a: T) where
97/// T: IsInteger,
98/// R: Binary,
99/// S: Binary,
100/// T: TypedEqual<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>, Output = R>,
101/// R: AssertTrue,
102/// T: TypedEqual<TypedInteger<_5, _0, _0, _0, _0, _0, _0, _0>, Output = S>,
103/// S: AssertFalse
104/// {}
105///
106/// example(a);
107/// ```
108pub trait TypedEqual<N: IsInteger> { type Output: Binary; }
109impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: Binary> TypedEqual<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
110N: _Equal<TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>, Output = R> {
111 type Output = R;
112}
113
114/// A trait that returns a binary depending on whether a < b
115///
116/// Example
117/// ```
118/// use const_arithmetic::*;
119/// let a = parse_integer!(3);
120///
121/// // This verifies that a <= 5 but not a < 3
122/// fn example<T, R, S>(_a: T) where
123/// T: IsInteger,
124/// R: Binary,
125/// S: Binary,
126/// T: TypedLessThan<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>, Output = R>,
127/// R: AssertFalse,
128/// T: TypedLessThan<TypedInteger<_5, _0, _0, _0, _0, _0, _0, _0>, Output = S>,
129/// S: AssertTrue
130/// {}
131///
132/// example(a);
133/// ```
134pub trait TypedLessThan<N: IsInteger> { type Output: Binary; }
135impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: Binary> TypedLessThan<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
136TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _LessThan<N, Output = R> {
137 type Output = R;
138}
139
140/// A trait that returns a binary depending on whether two integers are less or equal
141///
142/// Example
143/// ```
144/// use const_arithmetic::*;
145/// let a = parse_integer!(3);
146///
147/// // This verifies that a <= 5 but not a < 3
148/// fn example<T, R, S>(_a: T) where
149/// T: IsInteger,
150/// R: Binary,
151/// S: Binary,
152/// T: TypedLeq<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>, Output = R>,
153/// R: AssertTrue,
154/// T: TypedLeq<TypedInteger<_5, _0, _0, _0, _0, _0, _0, _0>, Output = S>,
155/// S: AssertTrue
156/// {}
157///
158/// example(a);
159/// ```
160pub trait TypedLeq<N: IsInteger> { type Output: Binary; }
161impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: Binary> TypedLeq<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
162TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Leq<N, Output = R> {
163 type Output = R;
164}
165
166/// A trait that returns a binary depending on whether two integers are greater or equal
167///
168/// Example
169/// ```
170/// use const_arithmetic::*;
171/// let a = parse_integer!(3);
172///
173/// // This verifies that a <= 5 but not a < 3
174/// fn example<T, R, S>(_a: T) where
175/// T: IsInteger,
176/// R: Binary,
177/// S: Binary,
178/// T: TypedGeq<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>, Output = R>,
179/// R: AssertTrue,
180/// T: TypedGeq<TypedInteger<_5, _0, _0, _0, _0, _0, _0, _0>, Output = S>,
181/// S: AssertFalse
182/// {}
183///
184/// example(a);
185/// ```
186pub trait TypedGeq<N: IsInteger> { type Output: Binary; }
187impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: Binary> TypedGeq<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
188TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Geq<N, Output = R> {
189 type Output = R;
190}
191
192/// A trait that returns a binary depending on whether a > b
193///
194/// Example
195/// ```
196/// use const_arithmetic::*;
197/// let a = parse_integer!(3);
198///
199/// // This verifies that a <= 5 but not a < 3
200/// fn example<T, R, S>(_a: T) where
201/// T: IsInteger,
202/// R: Binary,
203/// S: Binary,
204/// T: TypedGreaterThan<TypedInteger<_3, _0, _0, _0, _0, _0, _0, _0>, Output = R>,
205/// R: AssertFalse,
206/// T: TypedGreaterThan<TypedInteger<_1, _0, _0, _0, _0, _0, _0, _0>, Output = S>,
207/// S: AssertTrue
208/// {}
209///
210/// example(a);
211/// ```
212pub trait TypedGreaterThan<N: IsInteger> { type Output: Binary; }
213impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: Binary> TypedGreaterThan<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
214TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _GreaterThan<N, Output = R> {
215 type Output = R;
216}
217
218/// Denotes integer addition. If this says C7 does not implement HexAssertEq, this means it overflowed.
219///
220/// Example
221/// ```
222/// use const_arithmetic::*;
223/// let a = parse_integer!(3);
224/// let b = parse_integer!(5);
225/// let c = parse_integer!(8);
226///
227/// // This verifies that 3 + 5 = 8
228/// fn example<P, Q, R>(_p: P, _q: Q, _r: R) where
229/// P: IsInteger,
230/// Q: IsInteger,
231/// R: IsInteger,
232/// P: TypedAdd<Q, Output = R>
233/// {}
234///
235/// example(a, b, c);
236///
237/// // This is another way of implementing the above
238/// fn example2<P, Q, R, S, T>(_p: P, _q: Q, _r: R) where
239/// P: IsInteger,
240/// Q: IsInteger,
241/// R: IsInteger,
242/// S: IsInteger,
243/// T: Binary,
244/// P: TypedAdd<Q, Output = S>,
245/// R: TypedEqual<S, Output = T>,
246/// T: AssertTrue {}
247/// example2(a, b, c);
248/// ```
249pub trait TypedAdd<N: IsInteger> { type Output: IsInteger; }
250impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: IsInteger> TypedAdd<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
251TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Add<N, Output = R> {
252 type Output = R;
253}
254
255/// Denotes integer subtraction. If this says C7 does not implement HexAssertEq, this means it underflowed.
256///
257/// Example
258/// ```
259/// use const_arithmetic::*;
260/// let a = parse_integer!(7);
261/// let b = parse_integer!(4);
262/// let c = parse_integer!(3);
263///
264/// // This verifies that 7 - 4 = 3
265/// fn example<P, Q, R>(_p: P, _q: Q, _r: R) where
266/// P: IsInteger,
267/// Q: IsInteger,
268/// R: IsInteger,
269/// P: TypedSub<Q, Output = R>
270/// {}
271///
272/// example(a, b, c);
273/// ```
274pub trait TypedSub<N: IsInteger> { type Output: IsInteger; }
275impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: IsInteger> TypedSub<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
276TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Sub<N, Output = R> {
277 type Output = R;
278}
279
280
281
282/// A multiplication of 32 bit number and 32 bit number can be stored safely in a 64 bit number. We represent them as lower 32 bits and upper 32 bits
283///
284/// Example
285/// ```
286/// use const_arithmetic::*;
287/// let a = parse_integer!(6);
288/// let b = parse_integer!(4);
289/// let c = parse_integer!(24);
290///
291/// // This verifies that 6 * 4 = 24
292/// fn example<P, Q, R>(_p: P, _q: Q, _r: R) where
293/// P: IsInteger,
294/// Q: IsInteger,
295/// R: IsInteger,
296/// P: TypedMul<Q, Output = R>
297/// {}
298///
299/// example(a, b, c);
300///
301/// // If we are handling really big integers we can get the overflowed bits as follows
302/// // 1234567890 * 987654321 = 1219326311126352690 = 283896529 * (2**32) + 3623437106
303/// let a = parse_integer!(1234567890);
304/// let b = parse_integer!(987654321);
305/// let overflow = parse_integer!(283896529);
306/// let result = parse_integer!(3623437106);
307///
308/// // This verifies that 7 - 4 = 3
309/// fn example2<P, Q, R, S>(_p: P, _q: Q, _r: R, _s: S) where
310/// P: IsInteger,
311/// Q: IsInteger,
312/// R: IsInteger,
313/// S: IsInteger,
314/// P: TypedMul<Q, Output = R, Overflow = S>
315/// {}
316///
317/// example2(a, b, result, overflow);
318/// ```
319pub trait TypedMul<N: IsInteger> { type Output: IsInteger; type Overflow: IsInteger; }
320impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: IsInteger, O: IsInteger> TypedMul<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
321TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Mul<N, Output = R, Overflow = O> {
322 type Output = R;
323 type Overflow = O;
324}
325
326
327// TODO: We can actually implement bitshift to optimize division
328
329/// Returns the Quotient of H/K for H: Div<K, Output: ...>
330///
331/// Note about implementation detail: This is an expanded version of long division - it takes O(1) steps but the constant is quite big unfortunately
332/// (to be precise its 32 multiplications plus a negligible amount of addition and subtraction and other stuff)
333/// If there were many divisions, the compile time increases quite a bit
334///
335/// Example
336/// ```
337/// // (This doc test takes about 5 seconds to complete on my computer)
338/// use const_arithmetic::*;
339/// let a = parse_integer!(25);
340/// let b = parse_integer!(4);
341/// let quotient = parse_integer!(6);
342/// let modulus = parse_integer!(1);
343///
344/// // This verifies that 25/4 = 6 ... 1
345/// fn example<P, Q, R, S>(_p: P, _q: Q, _r: R, _s: S) where
346/// P: IsInteger,
347/// Q: IsInteger,
348/// R: IsInteger,
349/// S: IsInteger,
350/// P: TypedDiv<Q, Output = R, Remainder = S>
351/// {}
352///
353/// example(a, b, quotient, modulus);
354pub trait TypedDiv<K: IsInteger> { type Output: IsInteger; type Remainder: IsInteger; }
355impl <N: IsInteger, H0: Hex, H1: Hex, H2: Hex, H3: Hex, H4: Hex, H5: Hex, H6: Hex, H7: Hex, R: IsInteger, O: IsInteger> TypedDiv<N> for TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7> where
356TypedInteger<H0, H1, H2, H3, H4, H5, H6, H7>: _Div<N, Output = R, Remainder = O> {
357 type Output = R;
358 type Remainder = O;
359}