1 use super::Sign::{self, Minus, NoSign, Plus};
2 use super::{BigInt, ToBigInt};
3
4 use crate::TryFromBigIntError;
5 use crate::{BigUint, ParseBigIntError, ToBigUint};
6
7 use alloc::vec::Vec;
8 use core::cmp::Ordering::{Equal, Greater, Less};
9 use core::convert::TryFrom;
10 use core::str::{self, FromStr};
11 use num_traits::{FromPrimitive, Num, One, ToPrimitive, Zero};
12
13 impl FromStr for BigInt {
14 type Err = ParseBigIntError;
15
16 #[inline]
from_str(s: &str) -> Result<BigInt, ParseBigIntError>17 fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
18 BigInt::from_str_radix(s, 10)
19 }
20 }
21
22 impl Num for BigInt {
23 type FromStrRadixErr = ParseBigIntError;
24
25 /// Creates and initializes a [`BigInt`].
26 #[inline]
from_str_radix(mut s: &str, radix: u32) -> Result<BigInt, ParseBigIntError>27 fn from_str_radix(mut s: &str, radix: u32) -> Result<BigInt, ParseBigIntError> {
28 let sign = if let Some(tail) = s.strip_prefix('-') {
29 if !tail.starts_with('+') {
30 s = tail
31 }
32 Minus
33 } else {
34 Plus
35 };
36 let bu = BigUint::from_str_radix(s, radix)?;
37 Ok(BigInt::from_biguint(sign, bu))
38 }
39 }
40
41 impl ToPrimitive for BigInt {
42 #[inline]
to_i64(&self) -> Option<i64>43 fn to_i64(&self) -> Option<i64> {
44 match self.sign {
45 Plus => self.data.to_i64(),
46 NoSign => Some(0),
47 Minus => {
48 let n = self.data.to_u64()?;
49 let m: u64 = 1 << 63;
50 match n.cmp(&m) {
51 Less => Some(-(n as i64)),
52 Equal => Some(i64::MIN),
53 Greater => None,
54 }
55 }
56 }
57 }
58
59 #[inline]
to_i128(&self) -> Option<i128>60 fn to_i128(&self) -> Option<i128> {
61 match self.sign {
62 Plus => self.data.to_i128(),
63 NoSign => Some(0),
64 Minus => {
65 let n = self.data.to_u128()?;
66 let m: u128 = 1 << 127;
67 match n.cmp(&m) {
68 Less => Some(-(n as i128)),
69 Equal => Some(i128::MIN),
70 Greater => None,
71 }
72 }
73 }
74 }
75
76 #[inline]
to_u64(&self) -> Option<u64>77 fn to_u64(&self) -> Option<u64> {
78 match self.sign {
79 Plus => self.data.to_u64(),
80 NoSign => Some(0),
81 Minus => None,
82 }
83 }
84
85 #[inline]
to_u128(&self) -> Option<u128>86 fn to_u128(&self) -> Option<u128> {
87 match self.sign {
88 Plus => self.data.to_u128(),
89 NoSign => Some(0),
90 Minus => None,
91 }
92 }
93
94 #[inline]
to_f32(&self) -> Option<f32>95 fn to_f32(&self) -> Option<f32> {
96 let n = self.data.to_f32()?;
97 Some(if self.sign == Minus { -n } else { n })
98 }
99
100 #[inline]
to_f64(&self) -> Option<f64>101 fn to_f64(&self) -> Option<f64> {
102 let n = self.data.to_f64()?;
103 Some(if self.sign == Minus { -n } else { n })
104 }
105 }
106
107 macro_rules! impl_try_from_bigint {
108 ($T:ty, $to_ty:path) => {
109 impl TryFrom<&BigInt> for $T {
110 type Error = TryFromBigIntError<()>;
111
112 #[inline]
113 fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> {
114 $to_ty(value).ok_or(TryFromBigIntError::new(()))
115 }
116 }
117
118 impl TryFrom<BigInt> for $T {
119 type Error = TryFromBigIntError<BigInt>;
120
121 #[inline]
122 fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError<BigInt>> {
123 <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value))
124 }
125 }
126 };
127 }
128
129 impl_try_from_bigint!(u8, ToPrimitive::to_u8);
130 impl_try_from_bigint!(u16, ToPrimitive::to_u16);
131 impl_try_from_bigint!(u32, ToPrimitive::to_u32);
132 impl_try_from_bigint!(u64, ToPrimitive::to_u64);
133 impl_try_from_bigint!(usize, ToPrimitive::to_usize);
134 impl_try_from_bigint!(u128, ToPrimitive::to_u128);
135
136 impl_try_from_bigint!(i8, ToPrimitive::to_i8);
137 impl_try_from_bigint!(i16, ToPrimitive::to_i16);
138 impl_try_from_bigint!(i32, ToPrimitive::to_i32);
139 impl_try_from_bigint!(i64, ToPrimitive::to_i64);
140 impl_try_from_bigint!(isize, ToPrimitive::to_isize);
141 impl_try_from_bigint!(i128, ToPrimitive::to_i128);
142
143 impl FromPrimitive for BigInt {
144 #[inline]
from_i64(n: i64) -> Option<BigInt>145 fn from_i64(n: i64) -> Option<BigInt> {
146 Some(BigInt::from(n))
147 }
148
149 #[inline]
from_i128(n: i128) -> Option<BigInt>150 fn from_i128(n: i128) -> Option<BigInt> {
151 Some(BigInt::from(n))
152 }
153
154 #[inline]
from_u64(n: u64) -> Option<BigInt>155 fn from_u64(n: u64) -> Option<BigInt> {
156 Some(BigInt::from(n))
157 }
158
159 #[inline]
from_u128(n: u128) -> Option<BigInt>160 fn from_u128(n: u128) -> Option<BigInt> {
161 Some(BigInt::from(n))
162 }
163
164 #[inline]
from_f64(n: f64) -> Option<BigInt>165 fn from_f64(n: f64) -> Option<BigInt> {
166 if n >= 0.0 {
167 BigUint::from_f64(n).map(BigInt::from)
168 } else {
169 let x = BigUint::from_f64(-n)?;
170 Some(-BigInt::from(x))
171 }
172 }
173 }
174
175 impl From<i64> for BigInt {
176 #[inline]
from(n: i64) -> Self177 fn from(n: i64) -> Self {
178 if n >= 0 {
179 BigInt::from(n as u64)
180 } else {
181 let u = u64::MAX - (n as u64) + 1;
182 BigInt {
183 sign: Minus,
184 data: BigUint::from(u),
185 }
186 }
187 }
188 }
189
190 impl From<i128> for BigInt {
191 #[inline]
from(n: i128) -> Self192 fn from(n: i128) -> Self {
193 if n >= 0 {
194 BigInt::from(n as u128)
195 } else {
196 let u = u128::MAX - (n as u128) + 1;
197 BigInt {
198 sign: Minus,
199 data: BigUint::from(u),
200 }
201 }
202 }
203 }
204
205 macro_rules! impl_bigint_from_int {
206 ($T:ty) => {
207 impl From<$T> for BigInt {
208 #[inline]
209 fn from(n: $T) -> Self {
210 BigInt::from(n as i64)
211 }
212 }
213 };
214 }
215
216 impl_bigint_from_int!(i8);
217 impl_bigint_from_int!(i16);
218 impl_bigint_from_int!(i32);
219 impl_bigint_from_int!(isize);
220
221 impl From<u64> for BigInt {
222 #[inline]
from(n: u64) -> Self223 fn from(n: u64) -> Self {
224 if n > 0 {
225 BigInt {
226 sign: Plus,
227 data: BigUint::from(n),
228 }
229 } else {
230 Self::ZERO
231 }
232 }
233 }
234
235 impl From<u128> for BigInt {
236 #[inline]
from(n: u128) -> Self237 fn from(n: u128) -> Self {
238 if n > 0 {
239 BigInt {
240 sign: Plus,
241 data: BigUint::from(n),
242 }
243 } else {
244 Self::ZERO
245 }
246 }
247 }
248
249 macro_rules! impl_bigint_from_uint {
250 ($T:ty) => {
251 impl From<$T> for BigInt {
252 #[inline]
253 fn from(n: $T) -> Self {
254 BigInt::from(n as u64)
255 }
256 }
257 };
258 }
259
260 impl_bigint_from_uint!(u8);
261 impl_bigint_from_uint!(u16);
262 impl_bigint_from_uint!(u32);
263 impl_bigint_from_uint!(usize);
264
265 impl From<BigUint> for BigInt {
266 #[inline]
from(n: BigUint) -> Self267 fn from(n: BigUint) -> Self {
268 if n.is_zero() {
269 Self::ZERO
270 } else {
271 BigInt {
272 sign: Plus,
273 data: n,
274 }
275 }
276 }
277 }
278
279 impl ToBigInt for BigInt {
280 #[inline]
to_bigint(&self) -> Option<BigInt>281 fn to_bigint(&self) -> Option<BigInt> {
282 Some(self.clone())
283 }
284 }
285
286 impl ToBigInt for BigUint {
287 #[inline]
to_bigint(&self) -> Option<BigInt>288 fn to_bigint(&self) -> Option<BigInt> {
289 if self.is_zero() {
290 Some(BigInt::ZERO)
291 } else {
292 Some(BigInt {
293 sign: Plus,
294 data: self.clone(),
295 })
296 }
297 }
298 }
299
300 impl ToBigUint for BigInt {
301 #[inline]
to_biguint(&self) -> Option<BigUint>302 fn to_biguint(&self) -> Option<BigUint> {
303 match self.sign() {
304 Plus => Some(self.data.clone()),
305 NoSign => Some(BigUint::ZERO),
306 Minus => None,
307 }
308 }
309 }
310
311 impl TryFrom<&BigInt> for BigUint {
312 type Error = TryFromBigIntError<()>;
313
314 #[inline]
try_from(value: &BigInt) -> Result<BigUint, TryFromBigIntError<()>>315 fn try_from(value: &BigInt) -> Result<BigUint, TryFromBigIntError<()>> {
316 value
317 .to_biguint()
318 .ok_or_else(|| TryFromBigIntError::new(()))
319 }
320 }
321
322 impl TryFrom<BigInt> for BigUint {
323 type Error = TryFromBigIntError<BigInt>;
324
325 #[inline]
try_from(value: BigInt) -> Result<BigUint, TryFromBigIntError<BigInt>>326 fn try_from(value: BigInt) -> Result<BigUint, TryFromBigIntError<BigInt>> {
327 if value.sign() == Sign::Minus {
328 Err(TryFromBigIntError::new(value))
329 } else {
330 Ok(value.data)
331 }
332 }
333 }
334
335 macro_rules! impl_to_bigint {
336 ($T:ty, $from_ty:path) => {
337 impl ToBigInt for $T {
338 #[inline]
339 fn to_bigint(&self) -> Option<BigInt> {
340 $from_ty(*self)
341 }
342 }
343 };
344 }
345
346 impl_to_bigint!(isize, FromPrimitive::from_isize);
347 impl_to_bigint!(i8, FromPrimitive::from_i8);
348 impl_to_bigint!(i16, FromPrimitive::from_i16);
349 impl_to_bigint!(i32, FromPrimitive::from_i32);
350 impl_to_bigint!(i64, FromPrimitive::from_i64);
351 impl_to_bigint!(i128, FromPrimitive::from_i128);
352
353 impl_to_bigint!(usize, FromPrimitive::from_usize);
354 impl_to_bigint!(u8, FromPrimitive::from_u8);
355 impl_to_bigint!(u16, FromPrimitive::from_u16);
356 impl_to_bigint!(u32, FromPrimitive::from_u32);
357 impl_to_bigint!(u64, FromPrimitive::from_u64);
358 impl_to_bigint!(u128, FromPrimitive::from_u128);
359
360 impl_to_bigint!(f32, FromPrimitive::from_f32);
361 impl_to_bigint!(f64, FromPrimitive::from_f64);
362
363 impl From<bool> for BigInt {
from(x: bool) -> Self364 fn from(x: bool) -> Self {
365 if x {
366 One::one()
367 } else {
368 Self::ZERO
369 }
370 }
371 }
372
373 #[inline]
from_signed_bytes_be(digits: &[u8]) -> BigInt374 pub(super) fn from_signed_bytes_be(digits: &[u8]) -> BigInt {
375 let sign = match digits.first() {
376 Some(v) if *v > 0x7f => Sign::Minus,
377 Some(_) => Sign::Plus,
378 None => return BigInt::ZERO,
379 };
380
381 if sign == Sign::Minus {
382 // two's-complement the content to retrieve the magnitude
383 let mut digits = Vec::from(digits);
384 twos_complement_be(&mut digits);
385 BigInt::from_biguint(sign, BigUint::from_bytes_be(&digits))
386 } else {
387 BigInt::from_biguint(sign, BigUint::from_bytes_be(digits))
388 }
389 }
390
391 #[inline]
from_signed_bytes_le(digits: &[u8]) -> BigInt392 pub(super) fn from_signed_bytes_le(digits: &[u8]) -> BigInt {
393 let sign = match digits.last() {
394 Some(v) if *v > 0x7f => Sign::Minus,
395 Some(_) => Sign::Plus,
396 None => return BigInt::ZERO,
397 };
398
399 if sign == Sign::Minus {
400 // two's-complement the content to retrieve the magnitude
401 let mut digits = Vec::from(digits);
402 twos_complement_le(&mut digits);
403 BigInt::from_biguint(sign, BigUint::from_bytes_le(&digits))
404 } else {
405 BigInt::from_biguint(sign, BigUint::from_bytes_le(digits))
406 }
407 }
408
409 #[inline]
to_signed_bytes_be(x: &BigInt) -> Vec<u8>410 pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec<u8> {
411 let mut bytes = x.data.to_bytes_be();
412 let first_byte = bytes.first().cloned().unwrap_or(0);
413 if first_byte > 0x7f
414 && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && x.sign == Sign::Minus)
415 {
416 // msb used by magnitude, extend by 1 byte
417 bytes.insert(0, 0);
418 }
419 if x.sign == Sign::Minus {
420 twos_complement_be(&mut bytes);
421 }
422 bytes
423 }
424
425 #[inline]
to_signed_bytes_le(x: &BigInt) -> Vec<u8>426 pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec<u8> {
427 let mut bytes = x.data.to_bytes_le();
428 let last_byte = bytes.last().cloned().unwrap_or(0);
429 if last_byte > 0x7f
430 && !(last_byte == 0x80
431 && bytes.iter().rev().skip(1).all(Zero::is_zero)
432 && x.sign == Sign::Minus)
433 {
434 // msb used by magnitude, extend by 1 byte
435 bytes.push(0);
436 }
437 if x.sign == Sign::Minus {
438 twos_complement_le(&mut bytes);
439 }
440 bytes
441 }
442
443 /// Perform in-place two's complement of the given binary representation,
444 /// in little-endian byte order.
445 #[inline]
twos_complement_le(digits: &mut [u8])446 fn twos_complement_le(digits: &mut [u8]) {
447 twos_complement(digits)
448 }
449
450 /// Perform in-place two's complement of the given binary representation
451 /// in big-endian byte order.
452 #[inline]
twos_complement_be(digits: &mut [u8])453 fn twos_complement_be(digits: &mut [u8]) {
454 twos_complement(digits.iter_mut().rev())
455 }
456
457 /// Perform in-place two's complement of the given digit iterator
458 /// starting from the least significant byte.
459 #[inline]
twos_complement<'a, I>(digits: I) where I: IntoIterator<Item = &'a mut u8>,460 fn twos_complement<'a, I>(digits: I)
461 where
462 I: IntoIterator<Item = &'a mut u8>,
463 {
464 let mut carry = true;
465 for d in digits {
466 *d = !*d;
467 if carry {
468 *d = d.wrapping_add(1);
469 carry = d.is_zero();
470 }
471 }
472 }
473