crypto_bigint/uint/
macros.rs

1//! Macros used to define traits on aliases of `Uint`.
2
3/// Impl the `Inverter` trait, where we need to compute the number of unsaturated limbs for a given number of bits.
4macro_rules! impl_precompute_inverter_trait {
5    ($name:ident, $bits:expr) => {
6        /// Precompute a Bernstein-Yang inverter using `self` as the modulus.
7        impl PrecomputeInverter for Odd<$name> {
8            #[allow(trivial_numeric_casts)]
9            type Inverter =
10                SafeGcdInverter<{ nlimbs!($bits) }, { safegcd_nlimbs!($bits as usize) }>;
11
12            type Output = $name;
13
14            fn precompute_inverter(&self) -> Self::Inverter {
15                Self::precompute_inverter_with_adjuster(self, &Uint::ONE)
16            }
17        }
18
19        /// Precompute a Bernstein-Yang inverter using `self` as the modulus.
20        impl PrecomputeInverterWithAdjuster<$name> for Odd<$name> {
21            fn precompute_inverter_with_adjuster(&self, adjuster: &$name) -> Self::Inverter {
22                Self::Inverter::new(self, adjuster)
23            }
24        }
25
26        /// Const assertion that the unsaturated integer is sufficiently sized to hold the maximum
27        /// value represented by a saturated `$bits`-sized integer.
28        #[cfg(debug_assertions)]
29        #[allow(trivial_numeric_casts)]
30        const _: () = assert!((safegcd_nlimbs!($bits as usize) * 62) - 64 >= $bits);
31    };
32}
33
34// TODO(tarcieri): use `generic_const_exprs` when stable to make generic around bits.
35macro_rules! impl_uint_aliases {
36    ($(($name:ident, $bits:expr, $doc:expr)),+) => {
37        $(
38            #[doc = $doc]
39            #[doc="unsigned big integer."]
40            pub type $name = Uint<{ nlimbs!($bits) }>;
41
42            impl $name {
43                /// Serialize as big endian bytes.
44                pub const fn to_be_bytes(&self) -> [u8; $bits / 8] {
45                    encoding::uint_to_be_bytes::<{ nlimbs!($bits) }, { $bits / 8 }>(self)
46                }
47
48                /// Serialize as little endian bytes.
49                pub const fn to_le_bytes(&self) -> [u8; $bits / 8] {
50                    encoding::uint_to_le_bytes::<{ nlimbs!($bits) }, { $bits / 8 }>(self)
51                }
52            }
53
54            impl Encoding for $name {
55                type Repr = [u8; $bits / 8];
56
57                #[inline]
58                fn from_be_bytes(bytes: Self::Repr) -> Self {
59                    Self::from_be_slice(&bytes)
60                }
61
62                #[inline]
63                fn from_le_bytes(bytes: Self::Repr) -> Self {
64                    Self::from_le_slice(&bytes)
65                }
66
67                #[inline]
68                fn to_be_bytes(&self) -> Self::Repr {
69                    encoding::uint_to_be_bytes(self)
70                }
71
72                #[inline]
73                fn to_le_bytes(&self) -> Self::Repr {
74                    encoding::uint_to_le_bytes(self)
75                }
76            }
77
78            impl_precompute_inverter_trait!($name, $bits);
79        )+
80     };
81}
82
83macro_rules! impl_uint_concat_split_mixed {
84    ($name:ident, $size:literal) => {
85        impl $crate::traits::ConcatMixed<Uint<{ U64::LIMBS * $size }>> for Uint<{ <$name>::LIMBS - U64::LIMBS * $size }>
86        {
87            type MixedOutput = $name;
88
89            fn concat_mixed(&self, hi: &Uint<{ U64::LIMBS * $size }>) -> Self::MixedOutput {
90                Uint::concat_mixed(self, hi)
91            }
92        }
93
94        impl $crate::traits::SplitMixed<Uint<{ U64::LIMBS * $size }>, Uint<{ <$name>::LIMBS - U64::LIMBS * $size }>> for $name
95        {
96            fn split_mixed(&self) -> (Uint<{ U64::LIMBS * $size }>, Uint<{ <$name>::LIMBS - U64::LIMBS * $size }>) {
97                self.split_mixed()
98            }
99        }
100
101        impl $crate::traits::RemMixed<Uint<{ U64::LIMBS * $size }>> for $name
102        {
103            fn rem_mixed(&self, reductor: &NonZero<Uint<{ U64::LIMBS * $size }>>) -> Uint<{ U64::LIMBS * $size }> {
104                self.div_rem_vartime(reductor).1
105            }
106        }
107    };
108    ($name:ident, [ $($size:literal),+ ]) => {
109        $(
110            impl_uint_concat_split_mixed!($name, $size);
111        )+
112    };
113    ($( ($name:ident, $sizes:tt), )+) => {
114        $(
115            impl_uint_concat_split_mixed!($name, $sizes);
116        )+
117    };
118}
119
120macro_rules! impl_uint_concat_split_even {
121    ($name:ident) => {
122        impl $crate::traits::ConcatMixed<Uint<{ <$name>::LIMBS / 2 }>> for Uint<{ <$name>::LIMBS / 2 }>
123        {
124            type MixedOutput = $name;
125
126            fn concat_mixed(&self, hi: &Uint<{ <$name>::LIMBS / 2 }>) -> Self::MixedOutput {
127                Uint::concat_mixed(self, hi)
128            }
129        }
130
131        impl $crate::traits::SplitMixed<Uint<{ <$name>::LIMBS / 2 }>, Uint<{ <$name>::LIMBS / 2 }>> for $name
132        {
133            fn split_mixed(&self) -> (Uint<{ <$name>::LIMBS / 2 }>, Uint<{ <$name>::LIMBS / 2 }>) {
134                self.split_mixed()
135            }
136        }
137
138        impl $crate::traits::Split for $name
139        {
140            type Output = Uint<{ <$name>::LIMBS / 2 }>;
141        }
142    };
143    ($($name:ident,)+) => {
144        $(
145            impl_uint_concat_split_even!($name);
146        )+
147    }
148}