crypto_bigint/uint/
from.rs1use crate::{Concat, Limb, NonZero, Odd, 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 LIMBS: usize> From<NonZero<Limb>> for NonZero<Uint<LIMBS>> {
237 #[inline]
238 fn from(limb: NonZero<Limb>) -> Self {
239 NonZero(limb.0.into())
240 }
241}
242
243impl<const LIMBS: usize> From<Odd<Limb>> for Odd<Uint<LIMBS>> {
244 #[inline]
245 fn from(limb: Odd<Limb>) -> Self {
246 Odd(limb.0.into())
247 }
248}
249
250impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize>
251 From<(Uint<LO_LIMBS>, Uint<HI_LIMBS>)> for Uint<WIDE_LIMBS>
252where
253 Uint<LO_LIMBS>: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
254{
255 #[inline]
256 fn from(nums: (Uint<LO_LIMBS>, Uint<HI_LIMBS>)) -> Uint<WIDE_LIMBS> {
257 nums.0.concat_mixed(&nums.1)
258 }
259}
260
261impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize>
262 From<&(Uint<LO_LIMBS>, Uint<HI_LIMBS>)> for Uint<WIDE_LIMBS>
263where
264 Uint<LO_LIMBS>: Concat<HI_LIMBS, Output = Uint<WIDE_LIMBS>>,
265{
266 #[inline]
267 fn from(nums: &(Uint<LO_LIMBS>, Uint<HI_LIMBS>)) -> Uint<WIDE_LIMBS> {
268 nums.0.concat_mixed(&nums.1)
269 }
270}
271
272impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize> From<Uint<WIDE_LIMBS>>
273 for (Uint<LO_LIMBS>, Uint<HI_LIMBS>)
274where
275 Uint<WIDE_LIMBS>: Split<LO_LIMBS, Output = Uint<HI_LIMBS>>,
276{
277 #[inline]
278 fn from(num: Uint<WIDE_LIMBS>) -> (Uint<LO_LIMBS>, Uint<HI_LIMBS>) {
279 num.split_mixed()
280 }
281}
282
283impl<const LO_LIMBS: usize, const HI_LIMBS: usize, const WIDE_LIMBS: usize> From<&Uint<WIDE_LIMBS>>
284 for (Uint<LO_LIMBS>, Uint<HI_LIMBS>)
285where
286 Uint<WIDE_LIMBS>: Split<LO_LIMBS, Output = Uint<HI_LIMBS>>,
287{
288 #[inline]
289 fn from(num: &Uint<WIDE_LIMBS>) -> (Uint<LO_LIMBS>, Uint<HI_LIMBS>) {
290 num.split_mixed()
291 }
292}
293
294impl<const LIMBS: usize, const LIMBS2: usize> From<&Uint<LIMBS>> for Uint<LIMBS2> {
295 #[inline]
296 fn from(num: &Uint<LIMBS>) -> Uint<LIMBS2> {
297 num.resize()
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use crate::{Limb, U64, U128, Word};
304
305 cpubits::cpubits! {
306 32 => { use crate::U64 as UintEx; }
307 64 => { use crate::U128 as UintEx; }
308 }
309
310 #[test]
311 fn from_u8() {
312 let n = UintEx::from(42u8);
313 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
314 }
315
316 #[test]
317 fn from_u16() {
318 let n = UintEx::from(42u16);
319 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
320 }
321
322 #[test]
323 fn from_u64() {
324 let n = UintEx::from(42u64);
325 assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
326 }
327
328 #[test]
329 fn from_u128() {
330 let n = U128::from(42u128);
331 assert_eq!(&n.as_limbs()[..2], &[Limb(42), Limb(0)]);
332 assert_eq!(u128::from(n), 42u128);
333 }
334
335 #[test]
336 fn concat_mixed() {
337 let wide: U128 = (U64::ONE, U64::ZERO).into();
338 assert_eq!(wide, U128::ONE);
339
340 let wide: U128 = (&(U64::MAX, U64::MAX)).into();
341 assert_eq!(wide, U128::MAX);
342 }
343
344 #[test]
345 fn split_mixed() {
346 let lo_hi: (U64, _) = U128::ONE.into();
347 assert_eq!(lo_hi, (U64::ONE, U64::ZERO));
348
349 let lo_hi: (U64, _) = (&U128::MAX).into();
350 assert_eq!(lo_hi, (U64::MAX, U64::MAX));
351 }
352
353 #[test]
354 fn array_round_trip() {
355 let arr1 = [1, 2];
356 let n = UintEx::from(arr1);
357 let arr2: [Word; 2] = n.into();
358 assert_eq!(arr1, arr2);
359 }
360}