Skip to content

Commit

Permalink
bigint: add From implementations
Browse files Browse the repository at this point in the history
From all primative unsigned ints to BigUint
From all primative ints to BigInt
From BigUint to BigInt

Closes: rust-num#117
  • Loading branch information
ollie27 committed Dec 12, 2015
1 parent f2ea30d commit ec77b0a
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 22 deletions.
33 changes: 32 additions & 1 deletion benches/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ extern crate test;
extern crate num;
extern crate rand;

use std::{i64, u64};
use std::mem::replace;
use test::Bencher;
use num::{BigUint, Zero, One, FromPrimitive};
use num::{BigInt, BigUint, Zero, One, FromPrimitive};
use num::bigint::RandBigInt;
use rand::{SeedableRng, StdRng};

Expand Down Expand Up @@ -115,3 +116,33 @@ fn shr(b: &mut Bencher) {
}
})
}

macro_rules! bench_from {
($name:ident, $ty:ty, $start:expr, $end:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
b.iter(|| {
for n in $start..$end {
test::black_box(<$ty>::from(n));
}
})
}
}
}

bench_from!(from_u8_biguint, BigUint, 0u8, 255);
bench_from!(from_u16_biguint, BigUint, 0u16, 255);
bench_from!(from_u32_biguint, BigUint, 0u32, 255);
bench_from!(from_u64_biguint, BigUint, 0u64, 255);
bench_from!(from_u64_biguint_max, BigUint, u64::MAX - 255, u64::MAX);
bench_from!(from_u8_bigint, BigInt, 0u8, 255);
bench_from!(from_u16_bigint, BigInt, 0u16, 255);
bench_from!(from_u32_bigint, BigInt, 0u32, 255);
bench_from!(from_u64_bigint, BigInt, 0u64, 255);
bench_from!(from_u64_bigint_max, BigInt, u64::MAX - 255, u64::MAX);
bench_from!(from_i8_bigint, BigInt, -128i8, 127);
bench_from!(from_i16_bigint, BigInt, -128i16, 127);
bench_from!(from_i32_bigint, BigInt, -128i32, 127);
bench_from!(from_i64_bigint, BigInt, -128i64, 127);
bench_from!(from_i64_bigint_min, BigInt, i64::MIN, i64::MIN + 255);
bench_from!(from_i64_bigint_max, BigInt, i64::MAX - 255, i64::MAX);
115 changes: 94 additions & 21 deletions src/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,27 +1105,47 @@ impl ToPrimitive for BigUint {
impl FromPrimitive for BigUint {
#[inline]
fn from_i64(n: i64) -> Option<BigUint> {
if n > 0 {
FromPrimitive::from_u64(n as u64)
} else if n == 0 {
Some(Zero::zero())
if n >= 0 {
Some(BigUint::from(n as u64))
} else {
None
}
}

// `DoubleBigDigit` size dependent
#[inline]
fn from_u64(n: u64) -> Option<BigUint> {
let n = match big_digit::from_doublebigdigit(n) {
(0, 0) => Zero::zero(),
(0, n0) => BigUint::new(vec!(n0)),
(n1, n0) => BigUint::new(vec!(n0, n1))
};
Some(n)
Some(BigUint::from(n))
}
}

impl From<u64> for BigUint {
// `DoubleBigDigit` size dependent
#[inline]
fn from(n: u64) -> Self {
match big_digit::from_doublebigdigit(n) {
(0, 0) => BigUint::zero(),
(0, n0) => BigUint { data: vec![n0] },
(n1, n0) => BigUint { data: vec![n0, n1] },
}
}
}

macro_rules! impl_biguint_from_uint {
($T:ty) => {
impl From<$T> for BigUint {
#[inline]
fn from(n: $T) -> Self {
BigUint::from(n as u64)
}
}
}
}

impl_biguint_from_uint!(u8);
impl_biguint_from_uint!(u16);
impl_biguint_from_uint!(u32);
impl_biguint_from_uint!(usize);

/// A generic trait for converting a value to a `BigUint`.
pub trait ToBigUint {
/// Converts the value of `self` to a `BigUint`.
Expand Down Expand Up @@ -1973,24 +1993,77 @@ impl ToPrimitive for BigInt {
impl FromPrimitive for BigInt {
#[inline]
fn from_i64(n: i64) -> Option<BigInt> {
Some(BigInt::from(n))
}

#[inline]
fn from_u64(n: u64) -> Option<BigInt> {
Some(BigInt::from(n))
}
}

impl From<i64> for BigInt {
#[inline]
fn from(n: i64) -> Self {
if n >= 0 {
FromPrimitive::from_u64(n as u64)
BigInt::from(n as u64)
} else {
let u = u64::MAX - (n as u64) + 1;
FromPrimitive::from_u64(u).map(|n| {
BigInt::from_biguint(Minus, n)
})
BigInt { sign: Minus, data: BigUint::from(u) }
}
}
}

macro_rules! impl_bigint_from_int {
($T:ty) => {
impl From<$T> for BigInt {
#[inline]
fn from(n: $T) -> Self {
BigInt::from(n as i64)
}
}
}
}

impl_bigint_from_int!(i8);
impl_bigint_from_int!(i16);
impl_bigint_from_int!(i32);
impl_bigint_from_int!(isize);

impl From<u64> for BigInt {
#[inline]
fn from_u64(n: u64) -> Option<BigInt> {
if n == 0 {
Some(Zero::zero())
fn from(n: u64) -> Self {
if n > 0 {
BigInt { sign: Plus, data: BigUint::from(n) }
} else {
BigInt::zero()
}
}
}

macro_rules! impl_bigint_from_uint {
($T:ty) => {
impl From<$T> for BigInt {
#[inline]
fn from(n: $T) -> Self {
BigInt::from(n as u64)
}
}
}
}

impl_bigint_from_uint!(u8);
impl_bigint_from_uint!(u16);
impl_bigint_from_uint!(u32);
impl_bigint_from_uint!(usize);

impl From<BigUint> for BigInt {
#[inline]
fn from(n: BigUint) -> Self {
if n.is_zero() {
BigInt::zero()
} else {
FromPrimitive::from_u64(n).map(|n| {
BigInt::from_biguint(Plus, n)
})
BigInt { sign: Plus, data: n }
}
}
}
Expand Down

0 comments on commit ec77b0a

Please sign in to comment.