173 lines
4.9 KiB
Rust
173 lines
4.9 KiB
Rust
use crate::num::Sign::{self};
|
|
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
extern crate alloc;
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
use alloc::string::*;
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
use alloc::vec::*;
|
|
use core::convert::TryInto;
|
|
use core::prelude::v1::*;
|
|
#[cfg(feature = "std")]
|
|
use std::prelude::v1::*;
|
|
|
|
use super::BigInt;
|
|
|
|
macro_rules! impl_from_smaller {
|
|
($(($s: ty, $u: ty)),* ) => {
|
|
$(
|
|
impl From<$s> for BigInt {
|
|
/// Create a `BigInt` from a signed integer primitive
|
|
fn from(n: $s) -> Self {
|
|
let sign = if n < 0 { Sign::Negative } else { Sign::Positive };
|
|
let n = n.abs();
|
|
let raw: usize = <$s>::try_into(n).unwrap();
|
|
|
|
Self {
|
|
inner: vec![raw],
|
|
sign,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$u> for BigInt {
|
|
/// Create a `BigInt` from an unsigned integer primitive
|
|
fn from(n: $u) -> Self {
|
|
let mut new = Self::empty();
|
|
new.inner.push(n as usize);
|
|
|
|
new
|
|
}
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_from_larger {
|
|
($(($s: ty, $u: ty)),* ) => {
|
|
$(
|
|
impl From<$s> for BigInt {
|
|
/// Create a `BigInt` from a signed integer primitive
|
|
fn from(n: $s) -> Self {
|
|
let target_radix: $s = (usize::MAX as $s) + 1;
|
|
let sign = if n < 0 { Sign::Negative } else { Sign::Positive };
|
|
let n = n.abs();
|
|
|
|
let mut quotient = n / target_radix;
|
|
let mut rem = n % target_radix;
|
|
|
|
if quotient == 0 {
|
|
Self::from(rem as usize)
|
|
} else {
|
|
let mut inner: Vec<usize> = vec![rem as usize];
|
|
|
|
loop {
|
|
rem = quotient % target_radix;
|
|
quotient /= target_radix;
|
|
|
|
inner.push(rem as usize);
|
|
|
|
if (quotient == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
BigInt {
|
|
inner,
|
|
sign,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$u> for BigInt {
|
|
/// Create a `BigInt` from an unsigned integer primitive
|
|
fn from(n: $u) -> Self {
|
|
let target_radix: $u = (usize::MAX as $u) + 1;
|
|
|
|
let mut quotient = n / target_radix;
|
|
let mut rem = n % target_radix;
|
|
|
|
if quotient == 0 {
|
|
Self::from(rem as usize)
|
|
} else {
|
|
let mut inner: Vec<usize> = vec![rem as usize];
|
|
|
|
loop {
|
|
rem = quotient % target_radix;
|
|
quotient /= target_radix;
|
|
|
|
inner.push(rem as usize);
|
|
|
|
if (quotient == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
BigInt {
|
|
inner,
|
|
sign: Sign::Positive
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)*
|
|
};
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "16")]
|
|
impl_from_larger!((i32, u32), (i64, u64), (i128, u128));
|
|
#[cfg(target_pointer_width = "16")]
|
|
impl_from_smaller!((i8, u8), (i16, u16));
|
|
|
|
#[cfg(target_pointer_width = "32")]
|
|
impl_from_larger!((i64, u64), (i128, u128));
|
|
#[cfg(target_pointer_width = "32")]
|
|
impl_from_smaller!((i8, u8), (i16, u16), (i32, u32));
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
impl_from_larger!((i128, u128));
|
|
#[cfg(target_pointer_width = "64")]
|
|
impl_from_smaller!((i8, u8), (i16, u16), (i32, u32), (i64, u64));
|
|
|
|
#[cfg(target_pointer_width = "128")]
|
|
impl_from_smaller!((i8, u8), (i16, u16), (i32, u32), (i64, u64), (i128, u128));
|
|
|
|
impl From<usize> for BigInt {
|
|
fn from(n: usize) -> Self {
|
|
Self {
|
|
inner: vec![n],
|
|
sign: Sign::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<isize> for BigInt {
|
|
fn from(n: isize) -> Self {
|
|
let sign = if n < 0 {
|
|
Sign::Negative
|
|
} else {
|
|
Sign::Positive
|
|
};
|
|
let n = n.abs();
|
|
let raw: usize = isize::try_into(n).expect("Unable to convert isize value into usize.");
|
|
|
|
Self {
|
|
inner: vec![raw],
|
|
sign,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<&str> for BigInt {
|
|
fn from(s: &str) -> Self {
|
|
Self::from_str(s, 10)
|
|
}
|
|
}
|
|
|
|
impl From<String> for BigInt {
|
|
fn from(s: String) -> Self {
|
|
Self::from_str(&s, 10)
|
|
}
|
|
}
|