]>
Commit | Line | Data |
---|---|---|
49aad941 | 1 | //! `From`-like conversions for [`Uint`]. |
0a29b90c | 2 | |
4b012472 | 3 | use crate::{ConcatMixed, Limb, Uint, WideWord, Word, U128, U64}; |
0a29b90c | 4 | |
49aad941 FG |
5 | impl<const LIMBS: usize> Uint<LIMBS> { |
6 | /// Create a [`Uint`] from a `u8` (const-friendly) | |
0a29b90c FG |
7 | // TODO(tarcieri): replace with `const impl From<u8>` when stable |
8 | pub const fn from_u8(n: u8) -> Self { | |
9 | assert!(LIMBS >= 1, "number of limbs must be greater than zero"); | |
10 | let mut limbs = [Limb::ZERO; LIMBS]; | |
11 | limbs[0].0 = n as Word; | |
12 | Self { limbs } | |
13 | } | |
14 | ||
49aad941 | 15 | /// Create a [`Uint`] from a `u16` (const-friendly) |
0a29b90c FG |
16 | // TODO(tarcieri): replace with `const impl From<u16>` when stable |
17 | pub const fn from_u16(n: u16) -> Self { | |
18 | assert!(LIMBS >= 1, "number of limbs must be greater than zero"); | |
19 | let mut limbs = [Limb::ZERO; LIMBS]; | |
20 | limbs[0].0 = n as Word; | |
21 | Self { limbs } | |
22 | } | |
23 | ||
49aad941 | 24 | /// Create a [`Uint`] from a `u32` (const-friendly) |
0a29b90c FG |
25 | // TODO(tarcieri): replace with `const impl From<u32>` when stable |
26 | #[allow(trivial_numeric_casts)] | |
27 | pub const fn from_u32(n: u32) -> Self { | |
28 | assert!(LIMBS >= 1, "number of limbs must be greater than zero"); | |
29 | let mut limbs = [Limb::ZERO; LIMBS]; | |
30 | limbs[0].0 = n as Word; | |
31 | Self { limbs } | |
32 | } | |
33 | ||
49aad941 | 34 | /// Create a [`Uint`] from a `u64` (const-friendly) |
0a29b90c FG |
35 | // TODO(tarcieri): replace with `const impl From<u64>` when stable |
36 | #[cfg(target_pointer_width = "32")] | |
37 | pub const fn from_u64(n: u64) -> Self { | |
38 | assert!(LIMBS >= 2, "number of limbs must be two or greater"); | |
39 | let mut limbs = [Limb::ZERO; LIMBS]; | |
40 | limbs[0].0 = (n & 0xFFFFFFFF) as u32; | |
41 | limbs[1].0 = (n >> 32) as u32; | |
42 | Self { limbs } | |
43 | } | |
44 | ||
49aad941 | 45 | /// Create a [`Uint`] from a `u64` (const-friendly) |
0a29b90c FG |
46 | // TODO(tarcieri): replace with `const impl From<u64>` when stable |
47 | #[cfg(target_pointer_width = "64")] | |
48 | pub const fn from_u64(n: u64) -> Self { | |
49 | assert!(LIMBS >= 1, "number of limbs must be greater than zero"); | |
50 | let mut limbs = [Limb::ZERO; LIMBS]; | |
51 | limbs[0].0 = n; | |
52 | Self { limbs } | |
53 | } | |
54 | ||
49aad941 | 55 | /// Create a [`Uint`] from a `u128` (const-friendly) |
0a29b90c FG |
56 | // TODO(tarcieri): replace with `const impl From<u128>` when stable |
57 | pub const fn from_u128(n: u128) -> Self { | |
58 | assert!( | |
49aad941 | 59 | LIMBS >= (128 / Limb::BITS), |
0a29b90c FG |
60 | "number of limbs must be greater than zero" |
61 | ); | |
62 | ||
63 | let lo = U64::from_u64((n & 0xffff_ffff_ffff_ffff) as u64); | |
64 | let hi = U64::from_u64((n >> 64) as u64); | |
65 | ||
66 | let mut limbs = [Limb::ZERO; LIMBS]; | |
67 | ||
68 | let mut i = 0; | |
69 | while i < lo.limbs.len() { | |
70 | limbs[i] = lo.limbs[i]; | |
71 | i += 1; | |
72 | } | |
73 | ||
74 | let mut j = 0; | |
75 | while j < hi.limbs.len() { | |
76 | limbs[i + j] = hi.limbs[j]; | |
77 | j += 1; | |
78 | } | |
79 | ||
80 | Self { limbs } | |
81 | } | |
82 | ||
49aad941 | 83 | /// Create a [`Uint`] from a `Word` (const-friendly) |
0a29b90c FG |
84 | // TODO(tarcieri): replace with `const impl From<Word>` when stable |
85 | pub const fn from_word(n: Word) -> Self { | |
86 | assert!(LIMBS >= 1, "number of limbs must be greater than zero"); | |
87 | let mut limbs = [Limb::ZERO; LIMBS]; | |
88 | limbs[0].0 = n; | |
89 | Self { limbs } | |
90 | } | |
91 | ||
49aad941 | 92 | /// Create a [`Uint`] from a `WideWord` (const-friendly) |
0a29b90c FG |
93 | // TODO(tarcieri): replace with `const impl From<WideWord>` when stable |
94 | pub const fn from_wide_word(n: WideWord) -> Self { | |
95 | assert!(LIMBS >= 2, "number of limbs must be two or greater"); | |
96 | let mut limbs = [Limb::ZERO; LIMBS]; | |
97 | limbs[0].0 = n as Word; | |
49aad941 | 98 | limbs[1].0 = (n >> Limb::BITS) as Word; |
0a29b90c FG |
99 | Self { limbs } |
100 | } | |
101 | } | |
102 | ||
49aad941 | 103 | impl<const LIMBS: usize> From<u8> for Uint<LIMBS> { |
0a29b90c FG |
104 | fn from(n: u8) -> Self { |
105 | // TODO(tarcieri): const where clause when possible | |
106 | debug_assert!(LIMBS > 0, "limbs must be non-zero"); | |
107 | Self::from_u8(n) | |
108 | } | |
109 | } | |
110 | ||
49aad941 | 111 | impl<const LIMBS: usize> From<u16> for Uint<LIMBS> { |
0a29b90c FG |
112 | fn from(n: u16) -> Self { |
113 | // TODO(tarcieri): const where clause when possible | |
114 | debug_assert!(LIMBS > 0, "limbs must be non-zero"); | |
115 | Self::from_u16(n) | |
116 | } | |
117 | } | |
118 | ||
49aad941 | 119 | impl<const LIMBS: usize> From<u32> for Uint<LIMBS> { |
0a29b90c FG |
120 | fn from(n: u32) -> Self { |
121 | // TODO(tarcieri): const where clause when possible | |
122 | debug_assert!(LIMBS > 0, "limbs must be non-zero"); | |
123 | Self::from_u32(n) | |
124 | } | |
125 | } | |
126 | ||
49aad941 | 127 | impl<const LIMBS: usize> From<u64> for Uint<LIMBS> { |
0a29b90c FG |
128 | fn from(n: u64) -> Self { |
129 | // TODO(tarcieri): const where clause when possible | |
49aad941 | 130 | debug_assert!(LIMBS >= (64 / Limb::BITS), "not enough limbs"); |
0a29b90c FG |
131 | Self::from_u64(n) |
132 | } | |
133 | } | |
134 | ||
49aad941 | 135 | impl<const LIMBS: usize> From<u128> for Uint<LIMBS> { |
0a29b90c FG |
136 | fn from(n: u128) -> Self { |
137 | // TODO(tarcieri): const where clause when possible | |
49aad941 | 138 | debug_assert!(LIMBS >= (128 / Limb::BITS), "not enough limbs"); |
0a29b90c FG |
139 | Self::from_u128(n) |
140 | } | |
141 | } | |
142 | ||
143 | #[cfg(target_pointer_width = "32")] | |
0a29b90c FG |
144 | impl From<U64> for u64 { |
145 | fn from(n: U64) -> u64 { | |
146 | (n.limbs[0].0 as u64) | ((n.limbs[1].0 as u64) << 32) | |
147 | } | |
148 | } | |
149 | ||
150 | #[cfg(target_pointer_width = "64")] | |
0a29b90c FG |
151 | impl From<U64> for u64 { |
152 | fn from(n: U64) -> u64 { | |
153 | n.limbs[0].into() | |
154 | } | |
155 | } | |
156 | ||
157 | impl From<U128> for u128 { | |
158 | fn from(n: U128) -> u128 { | |
4b012472 FG |
159 | let mut i = U128::LIMBS - 1; |
160 | let mut res = n.limbs[i].0 as u128; | |
161 | while i > 0 { | |
162 | i -= 1; | |
163 | res = (res << Limb::BITS) | (n.limbs[i].0 as u128); | |
164 | } | |
165 | res | |
0a29b90c FG |
166 | } |
167 | } | |
168 | ||
49aad941 | 169 | impl<const LIMBS: usize> From<[Word; LIMBS]> for Uint<LIMBS> { |
0a29b90c FG |
170 | fn from(arr: [Word; LIMBS]) -> Self { |
171 | Self::from_words(arr) | |
172 | } | |
173 | } | |
174 | ||
49aad941 FG |
175 | impl<const LIMBS: usize> From<Uint<LIMBS>> for [Word; LIMBS] { |
176 | fn from(n: Uint<LIMBS>) -> [Word; LIMBS] { | |
0a29b90c FG |
177 | *n.as_ref() |
178 | } | |
179 | } | |
180 | ||
49aad941 | 181 | impl<const LIMBS: usize> From<[Limb; LIMBS]> for Uint<LIMBS> { |
0a29b90c FG |
182 | fn from(limbs: [Limb; LIMBS]) -> Self { |
183 | Self { limbs } | |
184 | } | |
185 | } | |
186 | ||
49aad941 FG |
187 | impl<const LIMBS: usize> From<Uint<LIMBS>> for [Limb; LIMBS] { |
188 | fn from(n: Uint<LIMBS>) -> [Limb; LIMBS] { | |
0a29b90c FG |
189 | n.limbs |
190 | } | |
191 | } | |
192 | ||
49aad941 | 193 | impl<const LIMBS: usize> From<Limb> for Uint<LIMBS> { |
0a29b90c FG |
194 | fn from(limb: Limb) -> Self { |
195 | limb.0.into() | |
196 | } | |
197 | } | |
198 | ||
4b012472 FG |
199 | impl<const L: usize, const H: usize, const LIMBS: usize> From<(Uint<L>, Uint<H>)> for Uint<LIMBS> |
200 | where | |
201 | Uint<H>: ConcatMixed<Uint<L>, MixedOutput = Uint<LIMBS>>, | |
202 | { | |
203 | fn from(nums: (Uint<L>, Uint<H>)) -> Uint<LIMBS> { | |
204 | nums.1.concat_mixed(&nums.0) | |
205 | } | |
206 | } | |
207 | ||
208 | impl<const L: usize, const H: usize, const LIMBS: usize> From<&(Uint<L>, Uint<H>)> for Uint<LIMBS> | |
209 | where | |
210 | Uint<H>: ConcatMixed<Uint<L>, MixedOutput = Uint<LIMBS>>, | |
211 | { | |
212 | fn from(nums: &(Uint<L>, Uint<H>)) -> Uint<LIMBS> { | |
213 | nums.1.concat_mixed(&nums.0) | |
214 | } | |
215 | } | |
216 | ||
217 | impl<const L: usize, const H: usize, const LIMBS: usize> From<Uint<LIMBS>> for (Uint<L>, Uint<H>) { | |
218 | fn from(num: Uint<LIMBS>) -> (Uint<L>, Uint<H>) { | |
219 | crate::uint::split::split_mixed(&num) | |
220 | } | |
221 | } | |
222 | ||
223 | impl<const LIMBS: usize, const LIMBS2: usize> From<&Uint<LIMBS>> for Uint<LIMBS2> { | |
224 | fn from(num: &Uint<LIMBS>) -> Uint<LIMBS2> { | |
225 | num.resize() | |
226 | } | |
227 | } | |
228 | ||
0a29b90c FG |
229 | #[cfg(test)] |
230 | mod tests { | |
231 | use crate::{Limb, Word, U128}; | |
232 | ||
233 | #[cfg(target_pointer_width = "32")] | |
49aad941 | 234 | use crate::U64 as UintEx; |
0a29b90c FG |
235 | |
236 | #[cfg(target_pointer_width = "64")] | |
49aad941 | 237 | use crate::U128 as UintEx; |
0a29b90c FG |
238 | |
239 | #[test] | |
240 | fn from_u8() { | |
49aad941 FG |
241 | let n = UintEx::from(42u8); |
242 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
243 | } |
244 | ||
245 | #[test] | |
246 | fn from_u16() { | |
49aad941 FG |
247 | let n = UintEx::from(42u16); |
248 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
249 | } |
250 | ||
251 | #[test] | |
252 | fn from_u64() { | |
49aad941 FG |
253 | let n = UintEx::from(42u64); |
254 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
255 | } |
256 | ||
257 | #[test] | |
258 | fn from_u128() { | |
259 | let n = U128::from(42u128); | |
49aad941 | 260 | assert_eq!(&n.as_limbs()[..2], &[Limb(42), Limb(0)]); |
0a29b90c FG |
261 | assert_eq!(u128::from(n), 42u128); |
262 | } | |
263 | ||
264 | #[test] | |
265 | fn array_round_trip() { | |
266 | let arr1 = [1, 2]; | |
49aad941 | 267 | let n = UintEx::from(arr1); |
0a29b90c FG |
268 | let arr2: [Word; 2] = n.into(); |
269 | assert_eq!(arr1, arr2); | |
270 | } | |
271 | } |