bigint: apply a consistent order of conversion methods

This commit is contained in:
Josh Stone 2017-06-21 17:52:24 -07:00
parent 8dd6890ddc
commit 8964c65f38
2 changed files with 135 additions and 135 deletions

View File

@ -926,49 +926,6 @@ impl BigInt {
BigInt::from_biguint(sign, BigUint::new(digits))
}
/// Creates and initializes a `BigInt` from an array of bytes in two's complement.
///
/// The digits are in little-endian base 2^8.
#[inline]
pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt {
let sign = match digits.last() {
Some(v) if *v > 0x7f => Sign::Minus,
Some(_) => Sign::Plus,
None => return BigInt::zero(),
};
if sign == Sign::Minus {
// two's-complement the content to retrieve the magnitude
let mut digits = Vec::from(digits);
twos_complement_le(&mut digits);
BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits))
} else {
BigInt::from_biguint(sign, BigUint::from_bytes_le(digits))
}
}
/// Creates and initializes a `BigInt` from an array of bytes in
/// two's complement binary representation.
///
/// The digits are in big-endian base 2^8.
#[inline]
pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt {
let sign = match digits.first() {
Some(v) if *v > 0x7f => Sign::Minus,
Some(_) => Sign::Plus,
None => return BigInt::zero(),
};
if sign == Sign::Minus {
// two's-complement the content to retrieve the magnitude
let mut digits = Vec::from(digits);
twos_complement_be(&mut digits);
BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits))
} else {
BigInt::from_biguint(sign, BigUint::from_bytes_be(digits))
}
}
/// Creates and initializes a `BigInt`.
///
/// The digits are in little-endian base 2^32.
@ -1023,6 +980,65 @@ impl BigInt {
BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes))
}
/// Creates and initializes a `BigInt` from an array of bytes in
/// two's complement binary representation.
///
/// The digits are in big-endian base 2^8.
#[inline]
pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt {
let sign = match digits.first() {
Some(v) if *v > 0x7f => Sign::Minus,
Some(_) => Sign::Plus,
None => return BigInt::zero(),
};
if sign == Sign::Minus {
// two's-complement the content to retrieve the magnitude
let mut digits = Vec::from(digits);
twos_complement_be(&mut digits);
BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits))
} else {
BigInt::from_biguint(sign, BigUint::from_bytes_be(digits))
}
}
/// Creates and initializes a `BigInt` from an array of bytes in two's complement.
///
/// The digits are in little-endian base 2^8.
#[inline]
pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt {
let sign = match digits.last() {
Some(v) if *v > 0x7f => Sign::Minus,
Some(_) => Sign::Plus,
None => return BigInt::zero(),
};
if sign == Sign::Minus {
// two's-complement the content to retrieve the magnitude
let mut digits = Vec::from(digits);
twos_complement_le(&mut digits);
BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits))
} else {
BigInt::from_biguint(sign, BigUint::from_bytes_le(digits))
}
}
/// Creates and initializes a `BigInt`.
///
/// # Examples
///
/// ```
/// use num_bigint::{BigInt, ToBigInt};
///
/// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234));
/// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD));
/// assert_eq!(BigInt::parse_bytes(b"G", 16), None);
/// ```
#[inline]
pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok())
}
/// Creates and initializes a `BigInt`. Each u8 of the input slice is
/// interpreted as one digit of the number
/// and must therefore be less than `radix`.
@ -1063,45 +1079,6 @@ impl BigInt {
BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u))
}
/// Returns the sign and the byte representation of the `BigInt` in little-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::{ToBigInt, Sign};
///
/// let i = -1125.to_bigint().unwrap();
/// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4]));
/// ```
#[inline]
pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
(self.sign, self.data.to_bytes_le())
}
/// Returns the two's complement byte representation of the `BigInt` in little-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::ToBigInt;
///
/// let i = -1125.to_bigint().unwrap();
/// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]);
/// ```
#[inline]
pub fn to_signed_bytes_le(&self) -> Vec<u8> {
let mut bytes = self.data.to_bytes_le();
let last_byte = bytes.last().map(|v| *v).unwrap_or(0);
if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) {
// msb used by magnitude, extend by 1 byte
bytes.push(0);
}
if self.sign == Sign::Minus {
twos_complement_le(&mut bytes);
}
bytes
}
/// Returns the sign and the byte representation of the `BigInt` in big-endian byte order.
///
/// # Examples
@ -1117,6 +1094,21 @@ impl BigInt {
(self.sign, self.data.to_bytes_be())
}
/// Returns the sign and the byte representation of the `BigInt` in little-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::{ToBigInt, Sign};
///
/// let i = -1125.to_bigint().unwrap();
/// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4]));
/// ```
#[inline]
pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
(self.sign, self.data.to_bytes_le())
}
/// Returns the two's complement byte representation of the `BigInt` in big-endian byte order.
///
/// # Examples
@ -1137,7 +1129,31 @@ impl BigInt {
}
if self.sign == Sign::Minus {
twos_complement_be(&mut bytes);
}
}
bytes
}
/// Returns the two's complement byte representation of the `BigInt` in little-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::ToBigInt;
///
/// let i = -1125.to_bigint().unwrap();
/// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]);
/// ```
#[inline]
pub fn to_signed_bytes_le(&self) -> Vec<u8> {
let mut bytes = self.data.to_bytes_le();
let last_byte = bytes.last().map(|v| *v).unwrap_or(0);
if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) {
// msb used by magnitude, extend by 1 byte
bytes.push(0);
}
if self.sign == Sign::Minus {
twos_complement_le(&mut bytes);
}
bytes
}
@ -1218,22 +1234,6 @@ impl BigInt {
self.sign
}
/// Creates and initializes a `BigInt`.
///
/// # Examples
///
/// ```
/// use num_bigint::{BigInt, ToBigInt};
///
/// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234));
/// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD));
/// assert_eq!(BigInt::parse_bytes(b"G", 16), None);
/// ```
#[inline]
pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok())
}
/// Determines the fewest bits necessary to express the `BigInt`,
/// not including the sign.
#[inline]

View File

@ -1088,6 +1088,23 @@ impl BigUint {
}
/// Returns the byte representation of the `BigUint` in big-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::BigUint;
///
/// let i = BigUint::parse_bytes(b"1125", 10).unwrap();
/// assert_eq!(i.to_bytes_be(), vec![4, 101]);
/// ```
#[inline]
pub fn to_bytes_be(&self) -> Vec<u8> {
let mut v = self.to_bytes_le();
v.reverse();
v
}
/// Returns the byte representation of the `BigUint` in little-endian byte order.
///
/// # Examples
@ -1107,23 +1124,6 @@ impl BigUint {
}
}
/// Returns the byte representation of the `BigUint` in big-endian byte order.
///
/// # Examples
///
/// ```
/// use num_bigint::BigUint;
///
/// let i = BigUint::parse_bytes(b"1125", 10).unwrap();
/// assert_eq!(i.to_bytes_be(), vec![4, 101]);
/// ```
#[inline]
pub fn to_bytes_be(&self) -> Vec<u8> {
let mut v = self.to_bytes_le();
v.reverse();
v
}
/// Returns the integer formatted as a string in the given radix.
/// `radix` must be in the range `2...36`.
///
@ -1142,25 +1142,6 @@ impl BigUint {
unsafe { String::from_utf8_unchecked(v) }
}
/// Returns the integer in the requested base in little-endian digit order.
/// The output is not given in a human readable alphabet but as a zero
/// based u8 number.
/// `radix` must be in the range `2...256`.
///
/// # Examples
///
/// ```
/// use num_bigint::BigUint;
///
/// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159),
/// vec![27, 94, 2]);
/// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2)
/// ```
#[inline]
pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
to_radix_le(self, radix)
}
/// Returns the integer in the requested base in big-endian digit order.
/// The output is not given in a human readable alphabet but as a zero
/// based u8 number.
@ -1182,6 +1163,25 @@ impl BigUint {
v
}
/// Returns the integer in the requested base in little-endian digit order.
/// The output is not given in a human readable alphabet but as a zero
/// based u8 number.
/// `radix` must be in the range `2...256`.
///
/// # Examples
///
/// ```
/// use num_bigint::BigUint;
///
/// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159),
/// vec![27, 94, 2]);
/// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2)
/// ```
#[inline]
pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
to_radix_le(self, radix)
}
/// Determines the fewest bits necessary to express the `BigUint`.
#[inline]
pub fn bits(&self) -> usize {