1#![allow(clippy::needless_range_loop, clippy::many_single_char_names)]
4
5#[macro_use]
6mod macros;
7
8mod add;
9mod add_mod;
10mod bit_and;
11mod bit_not;
12mod bit_or;
13mod bit_xor;
14mod bits;
15mod cmp;
16mod concat;
17mod div;
18pub(crate) mod div_limb;
19mod encoding;
20mod from;
21mod inv_mod;
22mod mul;
23mod mul_mod;
24mod neg;
25mod neg_mod;
26mod resize;
27mod shl;
28mod shr;
29mod split;
30mod sqrt;
31mod sub;
32mod sub_mod;
33
34pub mod modular;
36
37#[cfg(feature = "generic-array")]
38mod array;
39
40#[cfg(feature = "rand_core")]
41mod rand;
42
43use crate::{Bounded, Encoding, Integer, Limb, Word, Zero};
44use core::fmt;
45use subtle::{Choice, ConditionallySelectable};
46
47#[cfg(feature = "serde")]
48use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
49
50#[cfg(feature = "zeroize")]
51use zeroize::DefaultIsZeroes;
52
53#[allow(clippy::derived_hash_with_manual_eq)]
72#[derive(Copy, Clone, Hash)]
73pub struct Uint<const LIMBS: usize> {
74    limbs: [Limb; LIMBS],
76}
77
78impl<const LIMBS: usize> Uint<LIMBS> {
79    pub const ZERO: Self = Self::from_u8(0);
81
82    pub const ONE: Self = Self::from_u8(1);
84
85    pub const MAX: Self = Self {
87        limbs: [Limb::MAX; LIMBS],
88    };
89
90    pub const BITS: usize = LIMBS * Limb::BITS;
92
93    pub(crate) const LOG2_BITS: usize = (usize::BITS - Self::BITS.leading_zeros()) as usize;
96
97    pub const BYTES: usize = LIMBS * Limb::BYTES;
99
100    pub const LIMBS: usize = LIMBS;
102
103    pub const fn new(limbs: [Limb; LIMBS]) -> Self {
105        Self { limbs }
106    }
107
108    #[inline]
111    pub const fn from_words(arr: [Word; LIMBS]) -> Self {
112        let mut limbs = [Limb::ZERO; LIMBS];
113        let mut i = 0;
114
115        while i < LIMBS {
116            limbs[i] = Limb(arr[i]);
117            i += 1;
118        }
119
120        Self { limbs }
121    }
122
123    #[inline]
126    pub const fn to_words(self) -> [Word; LIMBS] {
127        let mut arr = [0; LIMBS];
128        let mut i = 0;
129
130        while i < LIMBS {
131            arr[i] = self.limbs[i].0;
132            i += 1;
133        }
134
135        arr
136    }
137
138    pub const fn as_words(&self) -> &[Word; LIMBS] {
140        #[allow(trivial_casts, unsafe_code)]
142        unsafe {
143            &*((&self.limbs as *const _) as *const [Word; LIMBS])
144        }
145    }
146
147    pub fn as_words_mut(&mut self) -> &mut [Word; LIMBS] {
149        #[allow(trivial_casts, unsafe_code)]
151        unsafe {
152            &mut *((&mut self.limbs as *mut _) as *mut [Word; LIMBS])
153        }
154    }
155
156    pub const fn as_limbs(&self) -> &[Limb; LIMBS] {
158        &self.limbs
159    }
160
161    pub fn as_limbs_mut(&mut self) -> &mut [Limb; LIMBS] {
163        &mut self.limbs
164    }
165
166    pub const fn to_limbs(self) -> [Limb; LIMBS] {
168        self.limbs
169    }
170}
171
172impl<const LIMBS: usize> AsRef<[Word; LIMBS]> for Uint<LIMBS> {
173    fn as_ref(&self) -> &[Word; LIMBS] {
174        self.as_words()
175    }
176}
177
178impl<const LIMBS: usize> AsMut<[Word; LIMBS]> for Uint<LIMBS> {
179    fn as_mut(&mut self) -> &mut [Word; LIMBS] {
180        self.as_words_mut()
181    }
182}
183
184impl<const LIMBS: usize> AsRef<[Limb]> for Uint<LIMBS> {
185    fn as_ref(&self) -> &[Limb] {
186        self.as_limbs()
187    }
188}
189
190impl<const LIMBS: usize> AsMut<[Limb]> for Uint<LIMBS> {
191    fn as_mut(&mut self) -> &mut [Limb] {
192        self.as_limbs_mut()
193    }
194}
195
196impl<const LIMBS: usize> ConditionallySelectable for Uint<LIMBS> {
197    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
198        let mut limbs = [Limb::ZERO; LIMBS];
199
200        for i in 0..LIMBS {
201            limbs[i] = Limb::conditional_select(&a.limbs[i], &b.limbs[i], choice);
202        }
203
204        Self { limbs }
205    }
206}
207
208impl<const LIMBS: usize> Default for Uint<LIMBS> {
209    fn default() -> Self {
210        Self::ZERO
211    }
212}
213
214impl<const LIMBS: usize> Integer for Uint<LIMBS> {
215    const ONE: Self = Self::ONE;
216    const MAX: Self = Self::MAX;
217    const BITS: usize = Self::BITS;
218    const BYTES: usize = Self::BYTES;
219    const LIMBS: usize = Self::LIMBS;
220
221    fn is_odd(&self) -> Choice {
222        self.limbs
223            .first()
224            .map(|limb| limb.is_odd())
225            .unwrap_or_else(|| Choice::from(0))
226    }
227}
228
229impl<const LIMBS: usize> Zero for Uint<LIMBS> {
230    const ZERO: Self = Self::ZERO;
231}
232
233impl<const LIMBS: usize> Bounded for Uint<LIMBS> {
234    const BITS: usize = Self::BITS;
235    const BYTES: usize = Self::BYTES;
236}
237
238impl<const LIMBS: usize> fmt::Debug for Uint<LIMBS> {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        write!(f, "Uint(0x{self:X})")
241    }
242}
243
244impl<const LIMBS: usize> fmt::Display for Uint<LIMBS> {
245    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246        fmt::UpperHex::fmt(self, f)
247    }
248}
249
250impl<const LIMBS: usize> fmt::LowerHex for Uint<LIMBS> {
251    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252        for limb in self.limbs.iter().rev() {
253            fmt::LowerHex::fmt(limb, f)?;
254        }
255        Ok(())
256    }
257}
258
259impl<const LIMBS: usize> fmt::UpperHex for Uint<LIMBS> {
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        for limb in self.limbs.iter().rev() {
262            fmt::UpperHex::fmt(limb, f)?;
263        }
264        Ok(())
265    }
266}
267
268#[cfg(feature = "serde")]
269impl<'de, const LIMBS: usize> Deserialize<'de> for Uint<LIMBS>
270where
271    Uint<LIMBS>: Encoding,
272{
273    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
274    where
275        D: Deserializer<'de>,
276    {
277        let mut buffer = Self::ZERO.to_le_bytes();
278        serdect::array::deserialize_hex_or_bin(buffer.as_mut(), deserializer)?;
279
280        Ok(Self::from_le_bytes(buffer))
281    }
282}
283
284#[cfg(feature = "serde")]
285impl<const LIMBS: usize> Serialize for Uint<LIMBS>
286where
287    Uint<LIMBS>: Encoding,
288{
289    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
290    where
291        S: Serializer,
292    {
293        serdect::array::serialize_hex_lower_or_bin(&Encoding::to_le_bytes(self), serializer)
294    }
295}
296
297#[cfg(feature = "zeroize")]
298impl<const LIMBS: usize> DefaultIsZeroes for Uint<LIMBS> {}
299
300impl_uint_aliases! {
302    (U64, 64, "64-bit"),
303    (U128, 128, "128-bit"),
304    (U192, 192, "192-bit"),
305    (U256, 256, "256-bit"),
306    (U320, 320, "320-bit"),
307    (U384, 384, "384-bit"),
308    (U448, 448, "448-bit"),
309    (U512, 512, "512-bit"),
310    (U576, 576, "576-bit"),
311    (U640, 640, "640-bit"),
312    (U704, 704, "704-bit"),
313    (U768, 768, "768-bit"),
314    (U832, 832, "832-bit"),
315    (U896, 896, "896-bit"),
316    (U960, 960, "960-bit"),
317    (U1024, 1024, "1024-bit"),
318    (U1280, 1280, "1280-bit"),
319    (U1536, 1536, "1536-bit"),
320    (U1792, 1792, "1792-bit"),
321    (U2048, 2048, "2048-bit"),
322    (U3072, 3072, "3072-bit"),
323    (U3584, 3584, "3584-bit"),
324    (U4096, 4096, "4096-bit"),
325    (U4224, 4224, "4224-bit"),
326    (U4352, 4352, "4352-bit"),
327    (U6144, 6144, "6144-bit"),
328    (U8192, 8192, "8192-bit"),
329    (U16384, 16384, "16384-bit"),
330    (U32768, 32768, "32768-bit")
331}
332
333#[cfg(target_pointer_width = "32")]
334impl_uint_aliases! {
335    (U224, 224, "224-bit"), (U544, 544, "544-bit")  }
338
339#[cfg(target_pointer_width = "32")]
340impl_uint_concat_split_even! {
341    U64,
342}
343
344impl_uint_concat_split_even! {
347    U128,
348    U256,
349    U384,
350    U512,
351    U640,
352    U768,
353    U896,
354    U1024,
355    U1280,
356    U1536,
357    U1792,
358    U2048,
359    U3072,
360    U3584,
361    U4096,
362    U4224,
363    U4352,
364    U6144,
365    U8192,
366    U16384,
367}
368
369impl_uint_concat_split_mixed! {
375    (U192, [1, 2]),
376    (U256, [1, 3]),
377    (U320, [1, 2, 3, 4]),
378    (U384, [1, 2, 4, 5]),
379    (U448, [1, 2, 3, 4, 5, 6]),
380    (U512, [1, 2, 3, 5, 6, 7]),
381    (U576, [1, 2, 3, 4, 5, 6, 7, 8]),
382    (U640, [1, 2, 3, 4, 6, 7, 8, 9]),
383    (U704, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
384    (U768, [1, 2, 3, 4, 5, 7, 8, 9, 10, 11]),
385    (U832, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
386    (U896, [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]),
387    (U960, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
388    (U1024, [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15]),
389}
390
391#[cfg(feature = "extra-sizes")]
392mod extra_sizes;
393#[cfg(feature = "extra-sizes")]
394pub use extra_sizes::*;
395
396#[cfg(test)]
397#[allow(clippy::unwrap_used)]
398mod tests {
399    use crate::{Encoding, U128};
400    use subtle::ConditionallySelectable;
401
402    #[cfg(feature = "alloc")]
403    use alloc::format;
404
405    #[cfg(feature = "serde")]
406    use crate::U64;
407
408    #[cfg(feature = "alloc")]
409    #[test]
410    fn debug() {
411        let hex = "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
412        let n = U128::from_be_hex(hex);
413
414        assert_eq!(
415            format!("{:?}", n),
416            "Uint(0xAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD)"
417        );
418    }
419
420    #[cfg(feature = "alloc")]
421    #[test]
422    fn display() {
423        let hex = "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
424        let n = U128::from_be_hex(hex);
425
426        use alloc::string::ToString;
427        assert_eq!(hex, n.to_string());
428
429        let hex = "AAAAAAAABBBBBBBB0000000000000000";
430        let n = U128::from_be_hex(hex);
431        assert_eq!(hex, n.to_string());
432
433        let hex = "AAAAAAAABBBBBBBB00000000DDDDDDDD";
434        let n = U128::from_be_hex(hex);
435        assert_eq!(hex, n.to_string());
436
437        let hex = "AAAAAAAABBBBBBBB0CCCCCCCDDDDDDDD";
438        let n = U128::from_be_hex(hex);
439        assert_eq!(hex, n.to_string());
440    }
441
442    #[test]
443    fn from_bytes() {
444        let a = U128::from_be_hex("AAAAAAAABBBBBBBB0CCCCCCCDDDDDDDD");
445
446        let be_bytes = a.to_be_bytes();
447        let le_bytes = a.to_le_bytes();
448        for i in 0..16 {
449            assert_eq!(le_bytes[i], be_bytes[15 - i]);
450        }
451
452        let a_from_be = U128::from_be_bytes(be_bytes);
453        let a_from_le = U128::from_le_bytes(le_bytes);
454        assert_eq!(a_from_be, a_from_le);
455        assert_eq!(a_from_be, a);
456    }
457
458    #[test]
459    fn conditional_select() {
460        let a = U128::from_be_hex("00002222444466668888AAAACCCCEEEE");
461        let b = U128::from_be_hex("11113333555577779999BBBBDDDDFFFF");
462
463        let select_0 = U128::conditional_select(&a, &b, 0.into());
464        assert_eq!(a, select_0);
465
466        let select_1 = U128::conditional_select(&a, &b, 1.into());
467        assert_eq!(b, select_1);
468    }
469
470    #[cfg(feature = "serde")]
471    #[test]
472    fn serde() {
473        const TEST: U64 = U64::from_u64(0x0011223344556677);
474
475        let serialized = bincode::serialize(&TEST).unwrap();
476        let deserialized: U64 = bincode::deserialize(&serialized).unwrap();
477
478        assert_eq!(TEST, deserialized);
479    }
480
481    #[cfg(feature = "serde")]
482    #[test]
483    fn serde_owned() {
484        const TEST: U64 = U64::from_u64(0x0011223344556677);
485
486        let serialized = bincode::serialize(&TEST).unwrap();
487        let deserialized: U64 = bincode::deserialize_from(serialized.as_slice()).unwrap();
488
489        assert_eq!(TEST, deserialized);
490    }
491}