rusty-numbers/src/bigint/from.rs

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)
}
}