]>
Commit | Line | Data |
---|---|---|
49aad941 | 1 | //! `From`-like conversions for [`Uint`]. |
0a29b90c | 2 | |
49aad941 | 3 | use crate::{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 { | |
159 | let (hi, lo) = n.split(); | |
160 | (u64::from(hi) as u128) << 64 | (u64::from(lo) as u128) | |
161 | } | |
162 | } | |
163 | ||
49aad941 | 164 | impl<const LIMBS: usize> From<[Word; LIMBS]> for Uint<LIMBS> { |
0a29b90c FG |
165 | fn from(arr: [Word; LIMBS]) -> Self { |
166 | Self::from_words(arr) | |
167 | } | |
168 | } | |
169 | ||
49aad941 FG |
170 | impl<const LIMBS: usize> From<Uint<LIMBS>> for [Word; LIMBS] { |
171 | fn from(n: Uint<LIMBS>) -> [Word; LIMBS] { | |
0a29b90c FG |
172 | *n.as_ref() |
173 | } | |
174 | } | |
175 | ||
49aad941 | 176 | impl<const LIMBS: usize> From<[Limb; LIMBS]> for Uint<LIMBS> { |
0a29b90c FG |
177 | fn from(limbs: [Limb; LIMBS]) -> Self { |
178 | Self { limbs } | |
179 | } | |
180 | } | |
181 | ||
49aad941 FG |
182 | impl<const LIMBS: usize> From<Uint<LIMBS>> for [Limb; LIMBS] { |
183 | fn from(n: Uint<LIMBS>) -> [Limb; LIMBS] { | |
0a29b90c FG |
184 | n.limbs |
185 | } | |
186 | } | |
187 | ||
49aad941 | 188 | impl<const LIMBS: usize> From<Limb> for Uint<LIMBS> { |
0a29b90c FG |
189 | fn from(limb: Limb) -> Self { |
190 | limb.0.into() | |
191 | } | |
192 | } | |
193 | ||
194 | #[cfg(test)] | |
195 | mod tests { | |
196 | use crate::{Limb, Word, U128}; | |
197 | ||
198 | #[cfg(target_pointer_width = "32")] | |
49aad941 | 199 | use crate::U64 as UintEx; |
0a29b90c FG |
200 | |
201 | #[cfg(target_pointer_width = "64")] | |
49aad941 | 202 | use crate::U128 as UintEx; |
0a29b90c FG |
203 | |
204 | #[test] | |
205 | fn from_u8() { | |
49aad941 FG |
206 | let n = UintEx::from(42u8); |
207 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
208 | } |
209 | ||
210 | #[test] | |
211 | fn from_u16() { | |
49aad941 FG |
212 | let n = UintEx::from(42u16); |
213 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
214 | } |
215 | ||
216 | #[test] | |
217 | fn from_u64() { | |
49aad941 FG |
218 | let n = UintEx::from(42u64); |
219 | assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]); | |
0a29b90c FG |
220 | } |
221 | ||
222 | #[test] | |
223 | fn from_u128() { | |
224 | let n = U128::from(42u128); | |
49aad941 | 225 | assert_eq!(&n.as_limbs()[..2], &[Limb(42), Limb(0)]); |
0a29b90c FG |
226 | assert_eq!(u128::from(n), 42u128); |
227 | } | |
228 | ||
229 | #[test] | |
230 | fn array_round_trip() { | |
231 | let arr1 = [1, 2]; | |
49aad941 | 232 | let n = UintEx::from(arr1); |
0a29b90c FG |
233 | let arr2: [Word; 2] = n.into(); |
234 | assert_eq!(arr1, arr2); | |
235 | } | |
236 | } |