/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.4.4/src/biguint/convert.rs
Line | Count | Source |
1 | | // This uses stdlib features higher than the MSRV |
2 | | #![allow(clippy::manual_range_contains)] // 1.35 |
3 | | |
4 | | use super::{biguint_from_vec, BigUint, ToBigUint}; |
5 | | |
6 | | use super::addition::add2; |
7 | | use super::division::div_rem_digit; |
8 | | use super::multiplication::mac_with_carry; |
9 | | |
10 | | use crate::big_digit::{self, BigDigit}; |
11 | | use crate::std_alloc::Vec; |
12 | | use crate::ParseBigIntError; |
13 | | #[cfg(has_try_from)] |
14 | | use crate::TryFromBigIntError; |
15 | | |
16 | | use core::cmp::Ordering::{Equal, Greater, Less}; |
17 | | #[cfg(has_try_from)] |
18 | | use core::convert::TryFrom; |
19 | | use core::mem; |
20 | | use core::str::FromStr; |
21 | | use num_integer::{Integer, Roots}; |
22 | | use num_traits::float::FloatCore; |
23 | | use num_traits::{FromPrimitive, Num, One, PrimInt, ToPrimitive, Zero}; |
24 | | |
25 | | /// Find last set bit |
26 | | /// fls(0) == 0, fls(u32::MAX) == 32 |
27 | 0 | fn fls<T: PrimInt>(v: T) -> u8 { |
28 | 0 | mem::size_of::<T>() as u8 * 8 - v.leading_zeros() as u8 |
29 | 0 | } Unexecuted instantiation: num_bigint::biguint::convert::fls::<u32> Unexecuted instantiation: num_bigint::biguint::convert::fls::<u64> |
30 | | |
31 | 0 | fn ilog2<T: PrimInt>(v: T) -> u8 { |
32 | 0 | fls(v) - 1 |
33 | 0 | } |
34 | | |
35 | | impl FromStr for BigUint { |
36 | | type Err = ParseBigIntError; |
37 | | |
38 | | #[inline] |
39 | 0 | fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> { |
40 | 0 | BigUint::from_str_radix(s, 10) |
41 | 0 | } |
42 | | } |
43 | | |
44 | | // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides |
45 | | // BigDigit::BITS |
46 | 5.49k | pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { |
47 | 5.49k | debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); |
48 | 5.49k | debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); |
49 | | |
50 | 5.49k | let digits_per_big_digit = big_digit::BITS / bits; |
51 | | |
52 | 5.49k | let data = v |
53 | 5.49k | .chunks(digits_per_big_digit.into()) |
54 | 12.6k | .map(|chunk| { |
55 | 12.6k | chunk |
56 | 12.6k | .iter() |
57 | 12.6k | .rev() |
58 | 91.5k | .fold(0, |acc, &c| (acc << bits) | BigDigit::from(c)) |
59 | 12.6k | }) |
60 | 5.49k | .collect(); |
61 | | |
62 | 5.49k | biguint_from_vec(data) |
63 | 5.49k | } |
64 | | |
65 | | // Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide |
66 | | // BigDigit::BITS |
67 | 0 | fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { |
68 | 0 | debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); |
69 | 0 | debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); |
70 | | |
71 | 0 | let total_bits = (v.len() as u64).saturating_mul(bits.into()); |
72 | 0 | let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into()) |
73 | 0 | .to_usize() |
74 | 0 | .unwrap_or(core::usize::MAX); |
75 | 0 | let mut data = Vec::with_capacity(big_digits); |
76 | | |
77 | 0 | let mut d = 0; |
78 | 0 | let mut dbits = 0; // number of bits we currently have in d |
79 | | |
80 | | // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a |
81 | | // big_digit: |
82 | 0 | for &c in v { |
83 | 0 | d |= BigDigit::from(c) << dbits; |
84 | 0 | dbits += bits; |
85 | | |
86 | 0 | if dbits >= big_digit::BITS { |
87 | 0 | data.push(d); |
88 | 0 | dbits -= big_digit::BITS; |
89 | 0 | // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit |
90 | 0 | // in d) - grab the bits we lost here: |
91 | 0 | d = BigDigit::from(c) >> (bits - dbits); |
92 | 0 | } |
93 | | } |
94 | | |
95 | 0 | if dbits > 0 { |
96 | 0 | debug_assert!(dbits < big_digit::BITS); |
97 | 0 | data.push(d as BigDigit); |
98 | 0 | } |
99 | | |
100 | 0 | biguint_from_vec(data) |
101 | 0 | } |
102 | | |
103 | | // Read little-endian radix digits |
104 | 0 | fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { |
105 | 0 | debug_assert!(!v.is_empty() && !radix.is_power_of_two()); |
106 | 0 | debug_assert!(v.iter().all(|&c| u32::from(c) < radix)); |
107 | | |
108 | | // Estimate how big the result will be, so we can pre-allocate it. |
109 | | #[cfg(feature = "std")] |
110 | 0 | let big_digits = { |
111 | 0 | let radix_log2 = f64::from(radix).log2(); |
112 | 0 | let bits = radix_log2 * v.len() as f64; |
113 | 0 | (bits / big_digit::BITS as f64).ceil() |
114 | | }; |
115 | | #[cfg(not(feature = "std"))] |
116 | | let big_digits = { |
117 | | let radix_log2 = ilog2(radix.next_power_of_two()) as usize; |
118 | | let bits = radix_log2 * v.len(); |
119 | | (bits / big_digit::BITS as usize) + 1 |
120 | | }; |
121 | | |
122 | 0 | let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); |
123 | | |
124 | 0 | let (base, power) = get_radix_base(radix, big_digit::BITS); |
125 | 0 | let radix = radix as BigDigit; |
126 | | |
127 | 0 | let r = v.len() % power; |
128 | 0 | let i = if r == 0 { power } else { r }; |
129 | 0 | let (head, tail) = v.split_at(i); |
130 | | |
131 | 0 | let first = head |
132 | 0 | .iter() |
133 | 0 | .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); |
134 | 0 | data.push(first); |
135 | | |
136 | 0 | debug_assert!(tail.len() % power == 0); |
137 | 0 | for chunk in tail.chunks(power) { |
138 | 0 | if data.last() != Some(&0) { |
139 | 0 | data.push(0); |
140 | 0 | } |
141 | | |
142 | 0 | let mut carry = 0; |
143 | 0 | for d in data.iter_mut() { |
144 | 0 | *d = mac_with_carry(0, *d, base, &mut carry); |
145 | 0 | } |
146 | 0 | debug_assert!(carry == 0); |
147 | | |
148 | 0 | let n = chunk |
149 | 0 | .iter() |
150 | 0 | .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); |
151 | 0 | add2(&mut data, &[n]); |
152 | | } |
153 | | |
154 | 0 | biguint_from_vec(data) |
155 | 0 | } |
156 | | |
157 | 0 | pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> { |
158 | 0 | assert!( |
159 | 0 | 2 <= radix && radix <= 256, |
160 | | "The radix must be within 2...256" |
161 | | ); |
162 | | |
163 | 0 | if buf.is_empty() { |
164 | 0 | return Some(Zero::zero()); |
165 | 0 | } |
166 | | |
167 | 0 | if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { |
168 | 0 | return None; |
169 | 0 | } |
170 | | |
171 | 0 | let res = if radix.is_power_of_two() { |
172 | | // Powers of two can use bitwise masks and shifting instead of multiplication |
173 | 0 | let bits = ilog2(radix); |
174 | 0 | let mut v = Vec::from(buf); |
175 | 0 | v.reverse(); |
176 | 0 | if big_digit::BITS % bits == 0 { |
177 | 0 | from_bitwise_digits_le(&v, bits) |
178 | | } else { |
179 | 0 | from_inexact_bitwise_digits_le(&v, bits) |
180 | | } |
181 | | } else { |
182 | 0 | from_radix_digits_be(buf, radix) |
183 | | }; |
184 | | |
185 | 0 | Some(res) |
186 | 0 | } |
187 | | |
188 | 0 | pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> { |
189 | 0 | assert!( |
190 | 0 | 2 <= radix && radix <= 256, |
191 | | "The radix must be within 2...256" |
192 | | ); |
193 | | |
194 | 0 | if buf.is_empty() { |
195 | 0 | return Some(Zero::zero()); |
196 | 0 | } |
197 | | |
198 | 0 | if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { |
199 | 0 | return None; |
200 | 0 | } |
201 | | |
202 | 0 | let res = if radix.is_power_of_two() { |
203 | | // Powers of two can use bitwise masks and shifting instead of multiplication |
204 | 0 | let bits = ilog2(radix); |
205 | 0 | if big_digit::BITS % bits == 0 { |
206 | 0 | from_bitwise_digits_le(buf, bits) |
207 | | } else { |
208 | 0 | from_inexact_bitwise_digits_le(buf, bits) |
209 | | } |
210 | | } else { |
211 | 0 | let mut v = Vec::from(buf); |
212 | 0 | v.reverse(); |
213 | 0 | from_radix_digits_be(&v, radix) |
214 | | }; |
215 | | |
216 | 0 | Some(res) |
217 | 0 | } |
218 | | |
219 | | impl Num for BigUint { |
220 | | type FromStrRadixErr = ParseBigIntError; |
221 | | |
222 | | /// Creates and initializes a `BigUint`. |
223 | 0 | fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> { |
224 | 0 | assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); |
225 | 0 | let mut s = s; |
226 | 0 | if s.starts_with('+') { |
227 | 0 | let tail = &s[1..]; |
228 | 0 | if !tail.starts_with('+') { |
229 | 0 | s = tail |
230 | 0 | } |
231 | 0 | } |
232 | | |
233 | 0 | if s.is_empty() { |
234 | 0 | return Err(ParseBigIntError::empty()); |
235 | 0 | } |
236 | | |
237 | 0 | if s.starts_with('_') { |
238 | | // Must lead with a real digit! |
239 | 0 | return Err(ParseBigIntError::invalid()); |
240 | 0 | } |
241 | | |
242 | | // First normalize all characters to plain digit values |
243 | 0 | let mut v = Vec::with_capacity(s.len()); |
244 | 0 | for b in s.bytes() { |
245 | 0 | let d = match b { |
246 | 0 | b'0'..=b'9' => b - b'0', |
247 | 0 | b'a'..=b'z' => b - b'a' + 10, |
248 | 0 | b'A'..=b'Z' => b - b'A' + 10, |
249 | 0 | b'_' => continue, |
250 | 0 | _ => core::u8::MAX, |
251 | | }; |
252 | 0 | if d < radix as u8 { |
253 | 0 | v.push(d); |
254 | 0 | } else { |
255 | 0 | return Err(ParseBigIntError::invalid()); |
256 | | } |
257 | | } |
258 | | |
259 | 0 | let res = if radix.is_power_of_two() { |
260 | | // Powers of two can use bitwise masks and shifting instead of multiplication |
261 | 0 | let bits = ilog2(radix); |
262 | 0 | v.reverse(); |
263 | 0 | if big_digit::BITS % bits == 0 { |
264 | 0 | from_bitwise_digits_le(&v, bits) |
265 | | } else { |
266 | 0 | from_inexact_bitwise_digits_le(&v, bits) |
267 | | } |
268 | | } else { |
269 | 0 | from_radix_digits_be(&v, radix) |
270 | | }; |
271 | 0 | Ok(res) |
272 | 0 | } |
273 | | } |
274 | | |
275 | 0 | fn high_bits_to_u64(v: &BigUint) -> u64 { |
276 | 0 | match v.data.len() { |
277 | 0 | 0 => 0, |
278 | | 1 => { |
279 | | // XXX Conversion is useless if already 64-bit. |
280 | | #[allow(clippy::useless_conversion)] |
281 | 0 | let v0 = u64::from(v.data[0]); |
282 | 0 | v0 |
283 | | } |
284 | | _ => { |
285 | 0 | let mut bits = v.bits(); |
286 | 0 | let mut ret = 0u64; |
287 | 0 | let mut ret_bits = 0; |
288 | | |
289 | 0 | for d in v.data.iter().rev() { |
290 | 0 | let digit_bits = (bits - 1) % u64::from(big_digit::BITS) + 1; |
291 | 0 | let bits_want = Ord::min(64 - ret_bits, digit_bits); |
292 | | |
293 | 0 | if bits_want != 0 { |
294 | 0 | if bits_want != 64 { |
295 | 0 | ret <<= bits_want; |
296 | 0 | } |
297 | | // XXX Conversion is useless if already 64-bit. |
298 | | #[allow(clippy::useless_conversion)] |
299 | 0 | let d0 = u64::from(*d) >> (digit_bits - bits_want); |
300 | 0 | ret |= d0; |
301 | 0 | } |
302 | | |
303 | | // Implement round-to-odd: If any lower bits are 1, set LSB to 1 |
304 | | // so that rounding again to floating point value using |
305 | | // nearest-ties-to-even is correct. |
306 | | // |
307 | | // See: https://en.wikipedia.org/wiki/Rounding#Rounding_to_prepare_for_shorter_precision |
308 | | |
309 | 0 | if digit_bits - bits_want != 0 { |
310 | 0 | // XXX Conversion is useless if already 64-bit. |
311 | 0 | #[allow(clippy::useless_conversion)] |
312 | 0 | let masked = u64::from(*d) << (64 - (digit_bits - bits_want) as u32); |
313 | 0 | ret |= (masked != 0) as u64; |
314 | 0 | } |
315 | | |
316 | 0 | ret_bits += bits_want; |
317 | 0 | bits -= bits_want; |
318 | | } |
319 | | |
320 | 0 | ret |
321 | | } |
322 | | } |
323 | 0 | } |
324 | | |
325 | | impl ToPrimitive for BigUint { |
326 | | #[inline] |
327 | 0 | fn to_i64(&self) -> Option<i64> { |
328 | 0 | self.to_u64().as_ref().and_then(u64::to_i64) |
329 | 0 | } |
330 | | |
331 | | #[inline] |
332 | 0 | fn to_i128(&self) -> Option<i128> { |
333 | 0 | self.to_u128().as_ref().and_then(u128::to_i128) |
334 | 0 | } |
335 | | |
336 | | #[allow(clippy::useless_conversion)] |
337 | | #[inline] |
338 | 0 | fn to_u64(&self) -> Option<u64> { |
339 | 0 | let mut ret: u64 = 0; |
340 | 0 | let mut bits = 0; |
341 | | |
342 | 0 | for i in self.data.iter() { |
343 | 0 | if bits >= 64 { |
344 | 0 | return None; |
345 | 0 | } |
346 | | |
347 | | // XXX Conversion is useless if already 64-bit. |
348 | 0 | ret += u64::from(*i) << bits; |
349 | 0 | bits += big_digit::BITS; |
350 | | } |
351 | | |
352 | 0 | Some(ret) |
353 | 0 | } |
354 | | |
355 | | #[inline] |
356 | 0 | fn to_u128(&self) -> Option<u128> { |
357 | 0 | let mut ret: u128 = 0; |
358 | 0 | let mut bits = 0; |
359 | | |
360 | 0 | for i in self.data.iter() { |
361 | 0 | if bits >= 128 { |
362 | 0 | return None; |
363 | 0 | } |
364 | | |
365 | 0 | ret |= u128::from(*i) << bits; |
366 | 0 | bits += big_digit::BITS; |
367 | | } |
368 | | |
369 | 0 | Some(ret) |
370 | 0 | } |
371 | | |
372 | | #[inline] |
373 | 0 | fn to_f32(&self) -> Option<f32> { |
374 | 0 | let mantissa = high_bits_to_u64(self); |
375 | 0 | let exponent = self.bits() - u64::from(fls(mantissa)); |
376 | | |
377 | 0 | if exponent > core::f32::MAX_EXP as u64 { |
378 | 0 | Some(core::f32::INFINITY) |
379 | | } else { |
380 | 0 | Some((mantissa as f32) * 2.0f32.powi(exponent as i32)) |
381 | | } |
382 | 0 | } |
383 | | |
384 | | #[inline] |
385 | 0 | fn to_f64(&self) -> Option<f64> { |
386 | 0 | let mantissa = high_bits_to_u64(self); |
387 | 0 | let exponent = self.bits() - u64::from(fls(mantissa)); |
388 | | |
389 | 0 | if exponent > core::f64::MAX_EXP as u64 { |
390 | 0 | Some(core::f64::INFINITY) |
391 | | } else { |
392 | 0 | Some((mantissa as f64) * 2.0f64.powi(exponent as i32)) |
393 | | } |
394 | 0 | } |
395 | | } |
396 | | |
397 | | macro_rules! impl_try_from_biguint { |
398 | | ($T:ty, $to_ty:path) => { |
399 | | #[cfg(has_try_from)] |
400 | | impl TryFrom<&BigUint> for $T { |
401 | | type Error = TryFromBigIntError<()>; |
402 | | |
403 | | #[inline] |
404 | 0 | fn try_from(value: &BigUint) -> Result<$T, TryFromBigIntError<()>> { |
405 | 0 | $to_ty(value).ok_or(TryFromBigIntError::new(())) |
406 | 0 | } Unexecuted instantiation: <u8 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u16 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u32 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u64 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <usize as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u128 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i8 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i16 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i32 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i64 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <isize as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i128 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from |
407 | | } |
408 | | |
409 | | #[cfg(has_try_from)] |
410 | | impl TryFrom<BigUint> for $T { |
411 | | type Error = TryFromBigIntError<BigUint>; |
412 | | |
413 | | #[inline] |
414 | 0 | fn try_from(value: BigUint) -> Result<$T, TryFromBigIntError<BigUint>> { |
415 | 0 | <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0} |
416 | 0 | } Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from |
417 | | } |
418 | | }; |
419 | | } |
420 | | |
421 | | impl_try_from_biguint!(u8, ToPrimitive::to_u8); |
422 | | impl_try_from_biguint!(u16, ToPrimitive::to_u16); |
423 | | impl_try_from_biguint!(u32, ToPrimitive::to_u32); |
424 | | impl_try_from_biguint!(u64, ToPrimitive::to_u64); |
425 | | impl_try_from_biguint!(usize, ToPrimitive::to_usize); |
426 | | impl_try_from_biguint!(u128, ToPrimitive::to_u128); |
427 | | |
428 | | impl_try_from_biguint!(i8, ToPrimitive::to_i8); |
429 | | impl_try_from_biguint!(i16, ToPrimitive::to_i16); |
430 | | impl_try_from_biguint!(i32, ToPrimitive::to_i32); |
431 | | impl_try_from_biguint!(i64, ToPrimitive::to_i64); |
432 | | impl_try_from_biguint!(isize, ToPrimitive::to_isize); |
433 | | impl_try_from_biguint!(i128, ToPrimitive::to_i128); |
434 | | |
435 | | impl FromPrimitive for BigUint { |
436 | | #[inline] |
437 | 0 | fn from_i64(n: i64) -> Option<BigUint> { |
438 | 0 | if n >= 0 { |
439 | 0 | Some(BigUint::from(n as u64)) |
440 | | } else { |
441 | 0 | None |
442 | | } |
443 | 0 | } |
444 | | |
445 | | #[inline] |
446 | 0 | fn from_i128(n: i128) -> Option<BigUint> { |
447 | 0 | if n >= 0 { |
448 | 0 | Some(BigUint::from(n as u128)) |
449 | | } else { |
450 | 0 | None |
451 | | } |
452 | 0 | } |
453 | | |
454 | | #[inline] |
455 | 0 | fn from_u64(n: u64) -> Option<BigUint> { |
456 | 0 | Some(BigUint::from(n)) |
457 | 0 | } |
458 | | |
459 | | #[inline] |
460 | 0 | fn from_u128(n: u128) -> Option<BigUint> { |
461 | 0 | Some(BigUint::from(n)) |
462 | 0 | } |
463 | | |
464 | | #[inline] |
465 | 0 | fn from_f64(mut n: f64) -> Option<BigUint> { |
466 | | // handle NAN, INFINITY, NEG_INFINITY |
467 | 0 | if !n.is_finite() { |
468 | 0 | return None; |
469 | 0 | } |
470 | | |
471 | | // match the rounding of casting from float to int |
472 | 0 | n = n.trunc(); |
473 | | |
474 | | // handle 0.x, -0.x |
475 | 0 | if n.is_zero() { |
476 | 0 | return Some(BigUint::zero()); |
477 | 0 | } |
478 | | |
479 | 0 | let (mantissa, exponent, sign) = FloatCore::integer_decode(n); |
480 | | |
481 | 0 | if sign == -1 { |
482 | 0 | return None; |
483 | 0 | } |
484 | | |
485 | 0 | let mut ret = BigUint::from(mantissa); |
486 | 0 | match exponent.cmp(&0) { |
487 | 0 | Greater => ret <<= exponent as usize, |
488 | 0 | Equal => {} |
489 | 0 | Less => ret >>= (-exponent) as usize, |
490 | | } |
491 | 0 | Some(ret) |
492 | 0 | } |
493 | | } |
494 | | |
495 | | impl From<u64> for BigUint { |
496 | | #[inline] |
497 | 0 | fn from(mut n: u64) -> Self { |
498 | 0 | let mut ret: BigUint = Zero::zero(); |
499 | | |
500 | 0 | while n != 0 { |
501 | 0 | ret.data.push(n as BigDigit); |
502 | 0 | // don't overflow if BITS is 64: |
503 | 0 | n = (n >> 1) >> (big_digit::BITS - 1); |
504 | 0 | } |
505 | | |
506 | 0 | ret |
507 | 0 | } |
508 | | } |
509 | | |
510 | | impl From<u128> for BigUint { |
511 | | #[inline] |
512 | 0 | fn from(mut n: u128) -> Self { |
513 | 0 | let mut ret: BigUint = Zero::zero(); |
514 | | |
515 | 0 | while n != 0 { |
516 | 0 | ret.data.push(n as BigDigit); |
517 | 0 | n >>= big_digit::BITS; |
518 | 0 | } |
519 | | |
520 | 0 | ret |
521 | 0 | } |
522 | | } |
523 | | |
524 | | macro_rules! impl_biguint_from_uint { |
525 | | ($T:ty) => { |
526 | | impl From<$T> for BigUint { |
527 | | #[inline] |
528 | 0 | fn from(n: $T) -> Self { |
529 | 0 | BigUint::from(n as u64) |
530 | 0 | } Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u8>>::from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u16>>::from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<usize>>::from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u32>>::from |
531 | | } |
532 | | }; |
533 | | } |
534 | | |
535 | | impl_biguint_from_uint!(u8); |
536 | | impl_biguint_from_uint!(u16); |
537 | | impl_biguint_from_uint!(u32); |
538 | | impl_biguint_from_uint!(usize); |
539 | | |
540 | | macro_rules! impl_biguint_try_from_int { |
541 | | ($T:ty, $from_ty:path) => { |
542 | | #[cfg(has_try_from)] |
543 | | impl TryFrom<$T> for BigUint { |
544 | | type Error = TryFromBigIntError<()>; |
545 | | |
546 | | #[inline] |
547 | 0 | fn try_from(value: $T) -> Result<BigUint, TryFromBigIntError<()>> { |
548 | 0 | $from_ty(value).ok_or(TryFromBigIntError::new(())) |
549 | 0 | } Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i32>>::try_from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i64>>::try_from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<isize>>::try_from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i128>>::try_from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i8>>::try_from Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i16>>::try_from |
550 | | } |
551 | | }; |
552 | | } |
553 | | |
554 | | impl_biguint_try_from_int!(i8, FromPrimitive::from_i8); |
555 | | impl_biguint_try_from_int!(i16, FromPrimitive::from_i16); |
556 | | impl_biguint_try_from_int!(i32, FromPrimitive::from_i32); |
557 | | impl_biguint_try_from_int!(i64, FromPrimitive::from_i64); |
558 | | impl_biguint_try_from_int!(isize, FromPrimitive::from_isize); |
559 | | impl_biguint_try_from_int!(i128, FromPrimitive::from_i128); |
560 | | |
561 | | impl ToBigUint for BigUint { |
562 | | #[inline] |
563 | 0 | fn to_biguint(&self) -> Option<BigUint> { |
564 | 0 | Some(self.clone()) |
565 | 0 | } |
566 | | } |
567 | | |
568 | | macro_rules! impl_to_biguint { |
569 | | ($T:ty, $from_ty:path) => { |
570 | | impl ToBigUint for $T { |
571 | | #[inline] |
572 | 0 | fn to_biguint(&self) -> Option<BigUint> { |
573 | 0 | $from_ty(*self) |
574 | 0 | } Unexecuted instantiation: <isize as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <i8 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <i16 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <i32 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <i64 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <i128 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <usize as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <u8 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <u16 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <u32 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <u64 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <u128 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <f32 as num_bigint::biguint::ToBigUint>::to_biguint Unexecuted instantiation: <f64 as num_bigint::biguint::ToBigUint>::to_biguint |
575 | | } |
576 | | }; |
577 | | } |
578 | | |
579 | | impl_to_biguint!(isize, FromPrimitive::from_isize); |
580 | | impl_to_biguint!(i8, FromPrimitive::from_i8); |
581 | | impl_to_biguint!(i16, FromPrimitive::from_i16); |
582 | | impl_to_biguint!(i32, FromPrimitive::from_i32); |
583 | | impl_to_biguint!(i64, FromPrimitive::from_i64); |
584 | | impl_to_biguint!(i128, FromPrimitive::from_i128); |
585 | | |
586 | | impl_to_biguint!(usize, FromPrimitive::from_usize); |
587 | | impl_to_biguint!(u8, FromPrimitive::from_u8); |
588 | | impl_to_biguint!(u16, FromPrimitive::from_u16); |
589 | | impl_to_biguint!(u32, FromPrimitive::from_u32); |
590 | | impl_to_biguint!(u64, FromPrimitive::from_u64); |
591 | | impl_to_biguint!(u128, FromPrimitive::from_u128); |
592 | | |
593 | | impl_to_biguint!(f32, FromPrimitive::from_f32); |
594 | | impl_to_biguint!(f64, FromPrimitive::from_f64); |
595 | | |
596 | | impl From<bool> for BigUint { |
597 | 0 | fn from(x: bool) -> Self { |
598 | 0 | if x { |
599 | 0 | One::one() |
600 | | } else { |
601 | 0 | Zero::zero() |
602 | | } |
603 | 0 | } |
604 | | } |
605 | | |
606 | | // Extract bitwise digits that evenly divide BigDigit |
607 | 0 | pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> { |
608 | 0 | debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); |
609 | | |
610 | 0 | let last_i = u.data.len() - 1; |
611 | 0 | let mask: BigDigit = (1 << bits) - 1; |
612 | 0 | let digits_per_big_digit = big_digit::BITS / bits; |
613 | 0 | let digits = Integer::div_ceil(&u.bits(), &u64::from(bits)) |
614 | 0 | .to_usize() |
615 | 0 | .unwrap_or(core::usize::MAX); |
616 | 0 | let mut res = Vec::with_capacity(digits); |
617 | | |
618 | 0 | for mut r in u.data[..last_i].iter().cloned() { |
619 | 0 | for _ in 0..digits_per_big_digit { |
620 | 0 | res.push((r & mask) as u8); |
621 | 0 | r >>= bits; |
622 | 0 | } |
623 | | } |
624 | | |
625 | 0 | let mut r = u.data[last_i]; |
626 | 0 | while r != 0 { |
627 | 0 | res.push((r & mask) as u8); |
628 | 0 | r >>= bits; |
629 | 0 | } |
630 | | |
631 | 0 | res |
632 | 0 | } |
633 | | |
634 | | // Extract bitwise digits that don't evenly divide BigDigit |
635 | 0 | fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> { |
636 | 0 | debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); |
637 | | |
638 | 0 | let mask: BigDigit = (1 << bits) - 1; |
639 | 0 | let digits = Integer::div_ceil(&u.bits(), &u64::from(bits)) |
640 | 0 | .to_usize() |
641 | 0 | .unwrap_or(core::usize::MAX); |
642 | 0 | let mut res = Vec::with_capacity(digits); |
643 | | |
644 | 0 | let mut r = 0; |
645 | 0 | let mut rbits = 0; |
646 | | |
647 | 0 | for c in &u.data { |
648 | 0 | r |= *c << rbits; |
649 | 0 | rbits += big_digit::BITS; |
650 | | |
651 | 0 | while rbits >= bits { |
652 | 0 | res.push((r & mask) as u8); |
653 | 0 | r >>= bits; |
654 | | |
655 | | // r had more bits than it could fit - grab the bits we lost |
656 | 0 | if rbits > big_digit::BITS { |
657 | 0 | r = *c >> (big_digit::BITS - (rbits - bits)); |
658 | 0 | } |
659 | | |
660 | 0 | rbits -= bits; |
661 | | } |
662 | | } |
663 | | |
664 | 0 | if rbits != 0 { |
665 | 0 | res.push(r as u8); |
666 | 0 | } |
667 | | |
668 | 0 | while let Some(&0) = res.last() { |
669 | 0 | res.pop(); |
670 | 0 | } |
671 | | |
672 | 0 | res |
673 | 0 | } |
674 | | |
675 | | // Extract little-endian radix digits |
676 | | #[inline(always)] // forced inline to get const-prop for radix=10 |
677 | 0 | pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8> { |
678 | 0 | debug_assert!(!u.is_zero() && !radix.is_power_of_two()); |
679 | | |
680 | | #[cfg(feature = "std")] |
681 | 0 | let radix_digits = { |
682 | 0 | let radix_log2 = f64::from(radix).log2(); |
683 | 0 | ((u.bits() as f64) / radix_log2).ceil() |
684 | | }; |
685 | | #[cfg(not(feature = "std"))] |
686 | | let radix_digits = { |
687 | | let radix_log2 = ilog2(radix) as usize; |
688 | | ((u.bits() as usize) / radix_log2) + 1 |
689 | | }; |
690 | | |
691 | | // Estimate how big the result will be, so we can pre-allocate it. |
692 | 0 | let mut res = Vec::with_capacity(radix_digits.to_usize().unwrap_or(0)); |
693 | | |
694 | 0 | let mut digits = u.clone(); |
695 | | |
696 | 0 | let (base, power) = get_radix_base(radix, big_digit::HALF_BITS); |
697 | 0 | let radix = radix as BigDigit; |
698 | | |
699 | | // For very large numbers, the O(n²) loop of repeated `div_rem_digit` dominates the |
700 | | // performance. We can mitigate this by dividing into chunks of a larger base first. |
701 | | // The threshold for this was chosen by anecdotal performance measurements to |
702 | | // approximate where this starts to make a noticeable difference. |
703 | 0 | if digits.data.len() >= 64 { |
704 | 0 | let mut big_base = BigUint::from(base * base); |
705 | 0 | let mut big_power = 2usize; |
706 | | |
707 | | // Choose a target base length near √n. |
708 | 0 | let target_len = digits.data.len().sqrt(); |
709 | 0 | while big_base.data.len() < target_len { |
710 | 0 | big_base = &big_base * &big_base; |
711 | 0 | big_power *= 2; |
712 | 0 | } |
713 | | |
714 | | // This outer loop will run approximately √n times. |
715 | 0 | while digits > big_base { |
716 | | // This is still the dominating factor, with n digits divided by √n digits. |
717 | 0 | let (q, mut big_r) = digits.div_rem(&big_base); |
718 | 0 | digits = q; |
719 | | |
720 | | // This inner loop now has O(√n²)=O(n) behavior altogether. |
721 | 0 | for _ in 0..big_power { |
722 | 0 | let (q, mut r) = div_rem_digit(big_r, base); |
723 | 0 | big_r = q; |
724 | 0 | for _ in 0..power { |
725 | 0 | res.push((r % radix) as u8); |
726 | 0 | r /= radix; |
727 | 0 | } |
728 | | } |
729 | | } |
730 | 0 | } |
731 | | |
732 | 0 | while digits.data.len() > 1 { |
733 | 0 | let (q, mut r) = div_rem_digit(digits, base); |
734 | 0 | for _ in 0..power { |
735 | 0 | res.push((r % radix) as u8); |
736 | 0 | r /= radix; |
737 | 0 | } |
738 | 0 | digits = q; |
739 | | } |
740 | | |
741 | 0 | let mut r = digits.data[0]; |
742 | 0 | while r != 0 { |
743 | 0 | res.push((r % radix) as u8); |
744 | 0 | r /= radix; |
745 | 0 | } |
746 | | |
747 | 0 | res |
748 | 0 | } |
749 | | |
750 | 0 | pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec<u8> { |
751 | 0 | if u.is_zero() { |
752 | 0 | vec![0] |
753 | 0 | } else if radix.is_power_of_two() { |
754 | | // Powers of two can use bitwise masks and shifting instead of division |
755 | 0 | let bits = ilog2(radix); |
756 | 0 | if big_digit::BITS % bits == 0 { |
757 | 0 | to_bitwise_digits_le(u, bits) |
758 | | } else { |
759 | 0 | to_inexact_bitwise_digits_le(u, bits) |
760 | | } |
761 | 0 | } else if radix == 10 { |
762 | | // 10 is so common that it's worth separating out for const-propagation. |
763 | | // Optimizers can often turn constant division into a faster multiplication. |
764 | 0 | to_radix_digits_le(u, 10) |
765 | | } else { |
766 | 0 | to_radix_digits_le(u, radix) |
767 | | } |
768 | 0 | } |
769 | | |
770 | 0 | pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8> { |
771 | 0 | assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); |
772 | | |
773 | 0 | if u.is_zero() { |
774 | 0 | return vec![b'0']; |
775 | 0 | } |
776 | | |
777 | 0 | let mut res = to_radix_le(u, radix); |
778 | | |
779 | | // Now convert everything to ASCII digits. |
780 | 0 | for r in &mut res { |
781 | 0 | debug_assert!(u32::from(*r) < radix); |
782 | 0 | if *r < 10 { |
783 | 0 | *r += b'0'; |
784 | 0 | } else { |
785 | 0 | *r += b'a' - 10; |
786 | 0 | } |
787 | | } |
788 | 0 | res |
789 | 0 | } |
790 | | |
791 | | /// Returns the greatest power of the radix for the given bit size |
792 | | #[inline] |
793 | 0 | fn get_radix_base(radix: u32, bits: u8) -> (BigDigit, usize) { |
794 | | mod gen { |
795 | | include! { concat!(env!("OUT_DIR"), "/radix_bases.rs") } |
796 | | } |
797 | | |
798 | 0 | debug_assert!( |
799 | 0 | 2 <= radix && radix <= 256, |
800 | | "The radix must be within 2...256" |
801 | | ); |
802 | 0 | debug_assert!(!radix.is_power_of_two()); |
803 | 0 | debug_assert!(bits <= big_digit::BITS); |
804 | | |
805 | 0 | match bits { |
806 | | 16 => { |
807 | 0 | let (base, power) = gen::BASES_16[radix as usize]; |
808 | 0 | (base as BigDigit, power) |
809 | | } |
810 | | 32 => { |
811 | 0 | let (base, power) = gen::BASES_32[radix as usize]; |
812 | 0 | (base as BigDigit, power) |
813 | | } |
814 | | 64 => { |
815 | 0 | let (base, power) = gen::BASES_64[radix as usize]; |
816 | 0 | (base as BigDigit, power) |
817 | | } |
818 | 0 | _ => panic!("Invalid bigdigit size"), |
819 | | } |
820 | 0 | } |