crypto_bigint/uint/
from.rs1use crate::{Concat, Limb, Split, U64, U128, Uint, WideWord, Word};
4
5macro_rules! check_limbs {
6 ($limbs:expr) => {
7 check_limbs!($limbs, 1)
8 };
9 ($limbs:expr, $min:expr) => {
10 const {
11 assert!($limbs >= 1, "number of limbs too small of supplied type");
12 }
13 };
14}
15
16impl<const LIMBS: usize> Uint<LIMBS> {
17 #[inline]
20 #[must_use]
21 pub const fn from_u8(n: u8) -> Self {
22 check_limbs!(LIMBS);
23 let mut limbs = [Limb::ZERO; LIMBS];
24 limbs[0].0 = n as Word;
25 Self { limbs }
26 }
27
28 #[inline]
31 #[must_use]
32 pub const fn from_u16(n: u16) -> Self {
33 check_limbs!(LIMBS);
34 let mut limbs = [Limb::ZERO; LIMBS];
35 limbs[0].0 = n as Word;
36 Self { limbs }
37 }
38
39 #[allow(trivial_numeric_casts)]
42 #[inline]
43 #[must_use]
44 pub const fn from_u32(n: u32) -> Self {
45 check_limbs!(LIMBS);
46 let mut limbs = [Limb::ZERO; LIMBS];
47 limbs[0].0 = n as Word;
48 Self { limbs }
49 }
50
51 cpubits::cpubits! {
52 32 => {
53 #[inline]
56 pub const fn from_u64(n: u64) -> Self {
57 check_limbs!(LIMBS, 2);
58 let mut limbs = [Limb::ZERO; LIMBS];
59 limbs[0].0 = (n & 0xFFFFFFFF) as u32;
60 limbs[1].0 = (n >> 32) as u32;
61 Self { limbs }
62 }
63 }
64 64 => {
65 #[inline]
68 #[must_use]
69 pub const fn from_u64(n: u64) -> Self {
70 check_limbs!(LIMBS);
71 let mut limbs = [Limb::ZERO; LIMBS];
72 limbs[0].0 = n;
73 Self { limbs }
74 }
75 }
76 }
77
78 #[inline]
81 #[must_use]
82 pub const fn from_u128(n: u128) -> Self {
83 check_limbs!(LIMBS, 16 / Limb::BYTES);
84 let lo = U64::from_u64((n & 0xffff_ffff_ffff_ffff) as u64);
85 let hi = U64::from_u64((n >> 64) as u64);
86
87 let mut limbs = [Limb::ZERO; LIMBS];
88
89 let mut i = 0;
90 while i < lo.limbs.len() {
91 limbs[i] = lo.limbs[i];
92 i += 1;
93 }
94
95 let mut j = 0;
96 while j < hi.limbs.len() {
97 limbs[i + j] = hi.limbs[j];
98 j += 1;
99 }
100
101 Self { limbs }
102 }
103
104 #[inline]
107 #[must_use]
108 pub const fn from_word(n: Word) -> Self {
109 check_limbs!(LIMBS);
110 let mut limbs = [Limb::ZERO; LIMBS];
111 limbs[0].0 = n;
112 Self { limbs }
113 }
114
115 #[inline]
118 #[must_use]
119 #[allow(clippy::cast_possible_truncation)]
120 pub const fn from_wide_word(n: WideWord) -> Self {
121 check_limbs!(LIMBS, 2);
122 let mut limbs = [Limb::ZERO; LIMBS];
123 limbs[0].0 = n as Word;
124 limbs[1].0 = (n >> Limb::BITS) as Word;
125 Self { limbs }
126 }
127}
128
129impl<const LIMBS: usize> From<u8> for Uint<LIMBS> {
130 #[inline]
131 fn from(n: u8) -> Self {
132 check_limbs!(LIMBS);
133 Self::from_u8(n)
134 }
135}
136
137impl<const LIMBS: usize> From<u16> for Uint<LIMBS> {
138 #[inline]
139 fn from(n: u16) -> Self {
140 check_limbs!(LIMBS);
141 Self::from_u16(n)
142 }
143}
144
145impl<const LIMBS: usize> From<u32> for Uint<LIMBS> {
146 #[inline]
147 fn from(n: u32) -> Self {
148 check_limbs!(LIMBS);
149 Self::from_u32(n)
150 }
151}
152
153impl<const LIMBS: usize> From<u64> for Uint<LIMBS> {
154 #[inline]
155 fn from(n: u64) -> Self {
156 check_limbs!(LIMBS, 8 / Limb::BYTES);
157 Self::from_u64(n)
158 }
159}
160
161impl<const LIMBS: usize> From<u128> for Uint<LIMBS> {
162 #[inline]
163 fn from(n: u128) -> Self {
164 check_limbs!(LIMBS, 16 / Limb::BYTES);
165 Self::from_u128(n)
166 }
167}
168
169cpubits::cpubits! {
170 32 => {
171 impl From<U64> for u64 {
172 #[inline]
173 fn from(n: U64) -> u64 {
174 (n.limbs[0].0 as u64) | ((n.limbs[1].0 as u64) << 32)
175 }
176 }
177 }
178 64 => {
179 impl From<U64> for u64 {
180 #[inline]
181 fn from(n: U64) -> u64 {
182 n.limbs[0].into()
183 }
184 }
185 }
186}
187
188impl From<U128> for u128 {
189 #[inline]
190 fn from(n: U128) -> u128 {
191 let mut i = U128::LIMBS - 1;
192 let mut res = u128::from(n.limbs[i].0);
193 while i > 0 {
194 i -= 1;
195 res = (res << Limb::BITS) | u128::from(n.limbs[i].0);
196 }
197 res
198 }
199}
200
201impl<const LIMBS: usize> From<[Word; LIMBS]> for Uint<LIMBS> {
202 #[inline]
203 fn from(arr: [Word; LIMBS]) -> Self {
204 Self::from_words(arr)
205 }
206}
207
208impl<const LIMBS: usize> From<Uint<LIMBS>> for [Word; LIMBS] {
209 #[inline]
210 fn from(n: Uint<LIMBS>) -> [Word; LIMBS] {
211 *n.as_ref()
212 }
213}
214
215impl<const LIMBS: usize> From<[Limb; LIMBS]> for Uint<LIMBS> {
216 #[inline]
217 fn from(limbs: [Limb; LIMBS]) -> Self {
218 Self { limbs }
219 }
220}
221
222impl<const LIMBS: usize> From<Uint<LIMBS>> for [Limb; LIMBS] {
223 #[inline]
224 fn from(n: Uint<LIMBS>) -> [Limb; LIMBS] {
225 n.limbs
226 }
227}
228
229impl<const LIMBS: usize> From<Limb> for Uint<LIMBS> {
230 #[inline]
231 fn from(limb: Limb) -> Self {
232 limb.0.into()
233 }
234}
235
236impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize>
237 From<(Uint<LO_LIMBS>, Uint<HI_LIMBS>)> for Uint<WIDE_LIMBS>
238where
239 Uint<LO_LIMBS>: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
240{
241 #[inline]
242 fn from(nums: (Uint<LO_LIMBS>, Uint<HI_LIMBS>)) -> Uint<WIDE_LIMBS> {
243 nums.0.concat_mixed(&nums.1)
244 }
245}
246
247impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize>
248 From<&(Uint<LO_LIMBS>, Uint<HI_LIMBS>)> for Uint<WIDE_LIMBS>
249where
250 Uint<LO_LIMBS>: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
251{
252 #[inline]
253 fn from(nums: &(Uint<LO_LIMBS>, Uint<HI_LIMBS>)) -> Uint<WIDE_LIMBS> {
254 nums.0.concat_mixed(&nums.1)
255 }
256}
257
258impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize> From<Uint<WIDE_LIMBS>>
259 for (Uint<LO_LIMBS>, Uint<HI_LIMBS>)
260where
261 Uint<WIDE_LIMBS>: Split<LO_LIMBS, Output = Uint<HI_LIMBS>>,
262{
263 #[inline]
264 fn from(num: Uint<WIDE_LIMBS>) -> (Uint<LO_LIMBS>, Uint<HI_LIMBS>) {
265 num.split_mixed()
266 }
267}
268
269impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize> From<&Uint<WIDE_LIMBS>>
270 for (Uint<LO_LIMBS>, Uint<HI_LIMBS>)
271where
272 Uint<WIDE_LIMBS>: Split<LO_LIMBS, Output = Uint<HI_LIMBS>>,
273{
274 #[inline]
275 fn from(num: &Uint<WIDE_LIMBS>) -> (Uint<LO_LIMBS>, Uint<HI_LIMBS>) {
276 num.split_mixed()
277 }
278}
279
280impl<const LIMBS: usize, const LIMBS2: usize> From<&Uint<LIMBS>> for Uint<LIMBS2> {
281 #[inline]
282 fn from(num: &Uint<LIMBS>) -> Uint<LIMBS2> {
283 num.resize()
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use crate::{Limb, U64, U128, Word};
290
291 cpubits::cpubits! {
292 32 => { use crate::U64 as UintEx; }
293 64 => { use crate::U128 as UintEx; }
294 }
295
296 #[test]
297 fn from_u8() {
298 let n = UintEx::from(42u8);
299 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
300 }
301
302 #[test]
303 fn from_u16() {
304 let n = UintEx::from(42u16);
305 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
306 }
307
308 #[test]
309 fn from_u64() {
310 let n = UintEx::from(42u64);
311 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
312 }
313
314 #[test]
315 fn from_u128() {
316 let n = U128::from(42u128);
317 assert_eq!(&n.as_limbs()[..2], &[Limb(42), Limb(0)]);
318 assert_eq!(u128::from(n), 42u128);
319 }
320
321 #[test]
322 fn concat_mixed() {
323 let wide: U128 = (U64::ONE, U64::ZERO).into();
324 assert_eq!(wide, U128::ONE);
325
326 let wide: U128 = (&(U64::MAX, U64::MAX)).into();
327 assert_eq!(wide, U128::MAX);
328 }
329
330 #[test]
331 fn split_mixed() {
332 let lo_hi: (U64, _) = U128::ONE.into();
333 assert_eq!(lo_hi, (U64::ONE, U64::ZERO));
334
335 let lo_hi: (U64, _) = (&U128::MAX).into();
336 assert_eq!(lo_hi, (U64::MAX, U64::MAX));
337 }
338
339 #[test]
340 fn array_round_trip() {
341 let arr1 = [1, 2];
342 let n = UintEx::from(arr1);
343 let arr2: [Word; 2] = n.into();
344 assert_eq!(arr1, arr2);
345 }
346}