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