auto merge of #9014 : dcrewi/rust/convert-between-bigints, r=anasazi
This commit is contained in:
commit
91ab8a3f52
@ -503,7 +503,7 @@ fn is_odd(&self) -> bool { !self.is_even() }
|
||||
impl IntConvertible for BigUint {
|
||||
#[inline]
|
||||
fn to_int(&self) -> int {
|
||||
num::min(self.to_uint(), int::max_value as uint) as int
|
||||
self.to_int_opt().expect("BigUint conversion would overflow int")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -615,18 +615,43 @@ pub fn parse_bytes(buf: &[u8], radix: uint)
|
||||
}
|
||||
|
||||
|
||||
/// Converts this big integer into a uint, returning the uint::max_value if
|
||||
/// it's too large to fit in a uint.
|
||||
/// Converts this BigUint into a uint, failing if the conversion
|
||||
/// would overflow.
|
||||
#[inline]
|
||||
pub fn to_uint(&self) -> uint {
|
||||
self.to_uint_opt().expect("BigUint conversion would overflow uint")
|
||||
}
|
||||
|
||||
/// Converts this BigUint into a uint, unless it would overflow.
|
||||
#[inline]
|
||||
pub fn to_uint_opt(&self) -> Option<uint> {
|
||||
match self.data.len() {
|
||||
0 => 0,
|
||||
1 => self.data[0] as uint,
|
||||
2 => BigDigit::to_uint(self.data[1], self.data[0]),
|
||||
_ => uint::max_value
|
||||
0 => Some(0),
|
||||
1 => Some(self.data[0] as uint),
|
||||
2 => Some(BigDigit::to_uint(self.data[1], self.data[0])),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
// Converts this BigUint into an int, unless it would overflow.
|
||||
pub fn to_int_opt(&self) -> Option<int> {
|
||||
self.to_uint_opt().chain(|n| {
|
||||
// If top bit of uint is set, it's too large to convert to
|
||||
// int.
|
||||
if (n >> (2*BigDigit::bits - 1) != 0) {
|
||||
None
|
||||
} else {
|
||||
Some(n as int)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts this BigUint into a BigInt.
|
||||
#[inline]
|
||||
pub fn to_bigint(&self) -> BigInt {
|
||||
BigInt::from_biguint(Plus, self.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shl_unit(&self, n_unit: uint) -> BigUint {
|
||||
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
|
||||
@ -1048,12 +1073,7 @@ fn is_odd(&self) -> bool { self.data.is_odd() }
|
||||
impl IntConvertible for BigInt {
|
||||
#[inline]
|
||||
fn to_int(&self) -> int {
|
||||
match self.sign {
|
||||
Plus => num::min(self.to_uint(), int::max_value as uint) as int,
|
||||
Zero => 0,
|
||||
Minus => num::min((-self).to_uint(),
|
||||
(int::max_value as uint) + 1) as int
|
||||
}
|
||||
self.to_int_opt().expect("BigInt conversion would overflow int")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1179,12 +1199,55 @@ pub fn parse_bytes(buf: &[u8], radix: uint)
|
||||
.map_move(|bu| BigInt::from_biguint(sign, bu));
|
||||
}
|
||||
|
||||
/// Converts this BigInt into a uint, failing if the conversion
|
||||
/// would overflow.
|
||||
#[inline]
|
||||
pub fn to_uint(&self) -> uint {
|
||||
self.to_uint_opt().expect("BigInt conversion would overflow uint")
|
||||
}
|
||||
|
||||
/// Converts this BigInt into a uint, unless it would overflow.
|
||||
#[inline]
|
||||
pub fn to_uint_opt(&self) -> Option<uint> {
|
||||
match self.sign {
|
||||
Plus => self.data.to_uint(),
|
||||
Zero => 0,
|
||||
Minus => 0
|
||||
Plus => self.data.to_uint_opt(),
|
||||
Zero => Some(0),
|
||||
Minus => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this BigInt into an int, unless it would overflow.
|
||||
pub fn to_int_opt(&self) -> Option<int> {
|
||||
match self.sign {
|
||||
Plus => self.data.to_int_opt(),
|
||||
Zero => Some(0),
|
||||
Minus => self.data.to_uint_opt().chain(|n| {
|
||||
let m: uint = 1 << (2*BigDigit::bits-1);
|
||||
if (n > m) {
|
||||
None
|
||||
} else if (n == m) {
|
||||
Some(int::min_value)
|
||||
} else {
|
||||
Some(-(n as int))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this BigInt into a BigUint, failing if BigInt is
|
||||
/// negative.
|
||||
#[inline]
|
||||
pub fn to_biguint(&self) -> BigUint {
|
||||
self.to_biguint_opt().expect("negative BigInt cannot convert to BigUint")
|
||||
}
|
||||
|
||||
/// Converts this BigInt into a BigUint, if it's not negative.
|
||||
#[inline]
|
||||
pub fn to_biguint_opt(&self) -> Option<BigUint> {
|
||||
match self.sign {
|
||||
Plus => Some(self.data.clone()),
|
||||
Zero => Some(Zero::zero()),
|
||||
Minus => None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1385,9 +1448,9 @@ fn check(v: ~[BigDigit], i: int) {
|
||||
check(~[ 0, 1], ((uint::max_value >> BigDigit::bits) + 1) as int);
|
||||
check(~[-1, -1 >> 1], int::max_value);
|
||||
|
||||
assert_eq!(BigUint::new(~[0, -1]).to_int(), int::max_value);
|
||||
assert_eq!(BigUint::new(~[0, 0, 1]).to_int(), int::max_value);
|
||||
assert_eq!(BigUint::new(~[0, 0, -1]).to_int(), int::max_value);
|
||||
assert_eq!(BigUint::new(~[0, -1]).to_int_opt(), None);
|
||||
assert_eq!(BigUint::new(~[0, 0, 1]).to_int_opt(), None);
|
||||
assert_eq!(BigUint::new(~[0, 0, -1]).to_int_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1405,8 +1468,19 @@ fn check(v: ~[BigDigit], u: uint) {
|
||||
check(~[ 0, -1], uint::max_value << BigDigit::bits);
|
||||
check(~[-1, -1], uint::max_value);
|
||||
|
||||
assert_eq!(BigUint::new(~[0, 0, 1]).to_uint(), uint::max_value);
|
||||
assert_eq!(BigUint::new(~[0, 0, -1]).to_uint(), uint::max_value);
|
||||
assert_eq!(BigUint::new(~[0, 0, 1]).to_uint_opt(), None);
|
||||
assert_eq!(BigUint::new(~[0, 0, -1]).to_uint_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_to_bigint() {
|
||||
fn check(n: BigUint, ans: BigInt) {
|
||||
assert_eq!(n.to_bigint(), ans);
|
||||
assert_eq!(n.to_bigint().to_biguint(), n);
|
||||
}
|
||||
check(Zero::zero(), Zero::zero());
|
||||
check(BigUint::new(~[1,2,3]),
|
||||
BigInt::from_biguint(Plus, BigUint::new(~[1,2,3])));
|
||||
}
|
||||
|
||||
static sum_triples: &'static [(&'static [BigDigit],
|
||||
@ -1793,22 +1867,21 @@ fn check(b: BigInt, i: int) {
|
||||
Plus, BigUint::from_uint(int::max_value as uint)
|
||||
), int::max_value);
|
||||
|
||||
assert!(BigInt::from_biguint(
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Plus, BigUint::from_uint(int::max_value as uint + 1)
|
||||
).to_int() == int::max_value);
|
||||
assert!(BigInt::from_biguint(
|
||||
).to_int_opt(), None);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Plus, BigUint::new(~[1, 2, 3])
|
||||
).to_int() == int::max_value);
|
||||
).to_int_opt(), None);
|
||||
|
||||
check(BigInt::from_biguint(
|
||||
Minus, BigUint::from_uint(-int::min_value as uint)
|
||||
Minus, BigUint::new(~[0, 1<<(BigDigit::bits-1)])
|
||||
), int::min_value);
|
||||
assert!(BigInt::from_biguint(
|
||||
Minus, BigUint::from_uint(-int::min_value as uint + 1)
|
||||
).to_int() == int::min_value);
|
||||
assert!(BigInt::from_biguint(
|
||||
Minus, BigUint::new(~[1, 2, 3])
|
||||
).to_int() == int::min_value);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Minus, BigUint::new(~[1, 1<<(BigDigit::bits-1)])
|
||||
).to_int_opt(), None);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Minus, BigUint::new(~[1, 2, 3])).to_int_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1824,16 +1897,31 @@ fn check(b: BigInt, u: uint) {
|
||||
check(
|
||||
BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)),
|
||||
uint::max_value);
|
||||
assert!(BigInt::from_biguint(
|
||||
Plus, BigUint::new(~[1, 2, 3])
|
||||
).to_uint() == uint::max_value);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Plus, BigUint::new(~[1, 2, 3])).to_uint_opt(), None);
|
||||
|
||||
assert!(BigInt::from_biguint(
|
||||
Minus, BigUint::from_uint(uint::max_value)
|
||||
).to_uint() == 0);
|
||||
assert!(BigInt::from_biguint(
|
||||
Minus, BigUint::new(~[1, 2, 3])
|
||||
).to_uint() == 0);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Minus, BigUint::from_uint(uint::max_value)).to_uint_opt(), None);
|
||||
assert_eq!(BigInt::from_biguint(
|
||||
Minus, BigUint::new(~[1, 2, 3])).to_uint_opt(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_convert_to_biguint() {
|
||||
fn check(n: BigInt, ans_1: BigUint) {
|
||||
assert_eq!(n.to_biguint(), ans_1);
|
||||
assert_eq!(n.to_biguint().to_bigint(), n);
|
||||
}
|
||||
let zero: BigInt = Zero::zero();
|
||||
let unsigned_zero: BigUint = Zero::zero();
|
||||
let positive = BigInt::from_biguint(
|
||||
Plus, BigUint::new(~[1,2,3]));
|
||||
let negative = -positive;
|
||||
|
||||
check(zero, unsigned_zero);
|
||||
check(positive, BigUint::new(~[1,2,3]));
|
||||
|
||||
assert_eq!(negative.to_biguint_opt(), None);
|
||||
}
|
||||
|
||||
static sum_triples: &'static [(&'static [BigDigit],
|
||||
|
Loading…
Reference in New Issue
Block a user