|
@@ -67,7 +67,7 @@ use std::num::{ToPrimitive, FromPrimitive};
|
|
use std::num::{Zero, One, FromStrRadix};
|
|
use std::num::{Zero, One, FromStrRadix};
|
|
use std::str;
|
|
use std::str;
|
|
use std::string::String;
|
|
use std::string::String;
|
|
-use std::{uint, i64, u64};
|
|
|
|
|
|
+use std::{i64, u64};
|
|
|
|
|
|
/// A `BigDigit` is a `BigUint`'s composing element.
|
|
/// A `BigDigit` is a `BigUint`'s composing element.
|
|
pub type BigDigit = u32;
|
|
pub type BigDigit = u32;
|
|
@@ -294,8 +294,8 @@ impl Mul<BigUint, BigUint> for BigUint {
|
|
if self.is_zero() || other.is_zero() { return Zero::zero(); }
|
|
if self.is_zero() || other.is_zero() { return Zero::zero(); }
|
|
|
|
|
|
let (s_len, o_len) = (self.data.len(), other.data.len());
|
|
let (s_len, o_len) = (self.data.len(), other.data.len());
|
|
- if s_len == 1 { return mul_digit(other, self.data.as_slice()[0]); }
|
|
|
|
- if o_len == 1 { return mul_digit(self, other.data.as_slice()[0]); }
|
|
|
|
|
|
+ if s_len == 1 { return mul_digit(other, self.data[0]); }
|
|
|
|
+ if o_len == 1 { return mul_digit(self, other.data[0]); }
|
|
|
|
|
|
// Using Karatsuba multiplication
|
|
// Using Karatsuba multiplication
|
|
// (a1 * base + a0) * (b1 * base + b0)
|
|
// (a1 * base + a0) * (b1 * base + b0)
|
|
@@ -340,8 +340,8 @@ impl Mul<BigUint, BigUint> for BigUint {
|
|
#[inline]
|
|
#[inline]
|
|
fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
|
|
fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
|
|
let mid = cmp::min(a.data.len(), n);
|
|
let mid = cmp::min(a.data.len(), n);
|
|
- return (BigUint::from_slice(a.data.slice(mid, a.data.len())),
|
|
|
|
- BigUint::from_slice(a.data.slice(0, mid)));
|
|
|
|
|
|
+ (BigUint::from_slice(a.data[mid ..]),
|
|
|
|
+ BigUint::from_slice(a.data[.. mid]))
|
|
}
|
|
}
|
|
|
|
|
|
#[inline]
|
|
#[inline]
|
|
@@ -488,7 +488,7 @@ impl Integer for BigUint {
|
|
return (Zero::zero(), Zero::zero(), (*a).clone());
|
|
return (Zero::zero(), Zero::zero(), (*a).clone());
|
|
}
|
|
}
|
|
|
|
|
|
- let an = a.data.slice_from(a.data.len() - n);
|
|
|
|
|
|
+ let an = a.data[a.data.len() - n ..];
|
|
let bn = *b.data.last().unwrap();
|
|
let bn = *b.data.last().unwrap();
|
|
let mut d = Vec::with_capacity(an.len());
|
|
let mut d = Vec::with_capacity(an.len());
|
|
let mut carry = 0;
|
|
let mut carry = 0;
|
|
@@ -545,7 +545,7 @@ impl Integer for BigUint {
|
|
#[inline]
|
|
#[inline]
|
|
fn is_even(&self) -> bool {
|
|
fn is_even(&self) -> bool {
|
|
// Considering only the last digit.
|
|
// Considering only the last digit.
|
|
- match self.data.as_slice().head() {
|
|
|
|
|
|
+ match self.data.head() {
|
|
Some(x) => x.is_even(),
|
|
Some(x) => x.is_even(),
|
|
None => true
|
|
None => true
|
|
}
|
|
}
|
|
@@ -574,8 +574,8 @@ impl ToPrimitive for BigUint {
|
|
fn to_u64(&self) -> Option<u64> {
|
|
fn to_u64(&self) -> Option<u64> {
|
|
match self.data.len() {
|
|
match self.data.len() {
|
|
0 => Some(0),
|
|
0 => Some(0),
|
|
- 1 => Some(self.data.as_slice()[0] as u64),
|
|
|
|
- 2 => Some(BigDigit::to_doublebigdigit(self.data.as_slice()[1], self.data.as_slice()[0])
|
|
|
|
|
|
+ 1 => Some(self.data[0] as u64),
|
|
|
|
+ 2 => Some(BigDigit::to_doublebigdigit(self.data[1], self.data[0])
|
|
as u64),
|
|
as u64),
|
|
_ => None
|
|
_ => None
|
|
}
|
|
}
|
|
@@ -658,9 +658,9 @@ fn to_str_radix(me: &BigUint, radix: uint) -> String {
|
|
assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
|
|
assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
|
|
let (base, max_len) = get_radix_base(radix);
|
|
let (base, max_len) = get_radix_base(radix);
|
|
if base == BigDigit::base {
|
|
if base == BigDigit::base {
|
|
- return fill_concat(me.data.as_slice(), radix, max_len)
|
|
|
|
|
|
+ return fill_concat(me.data[], radix, max_len)
|
|
}
|
|
}
|
|
- return fill_concat(convert_base(me, base).as_slice(), radix, max_len);
|
|
|
|
|
|
+ return fill_concat(convert_base(me, base)[], radix, max_len);
|
|
|
|
|
|
fn convert_base(n: &BigUint, base: DoubleBigDigit) -> Vec<BigDigit> {
|
|
fn convert_base(n: &BigUint, base: DoubleBigDigit) -> Vec<BigDigit> {
|
|
let divider = base.to_biguint().unwrap();
|
|
let divider = base.to_biguint().unwrap();
|
|
@@ -684,10 +684,10 @@ fn to_str_radix(me: &BigUint, radix: uint) -> String {
|
|
let mut s = String::with_capacity(v.len() * l);
|
|
let mut s = String::with_capacity(v.len() * l);
|
|
for n in v.iter().rev() {
|
|
for n in v.iter().rev() {
|
|
let ss = fmt::radix(*n as uint, radix as u8).to_string();
|
|
let ss = fmt::radix(*n as uint, radix as u8).to_string();
|
|
- s.push_str("0".repeat(l - ss.len()).as_slice());
|
|
|
|
- s.push_str(ss.as_slice());
|
|
|
|
|
|
+ s.push_str("0".repeat(l - ss.len())[]);
|
|
|
|
+ s.push_str(ss[]);
|
|
}
|
|
}
|
|
- s.as_slice().trim_left_chars('0').to_string()
|
|
|
|
|
|
+ s.trim_left_chars('0').to_string()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -703,46 +703,18 @@ impl FromStrRadix for BigUint {
|
|
/// Creates and initializes a `BigUint`.
|
|
/// Creates and initializes a `BigUint`.
|
|
#[inline]
|
|
#[inline]
|
|
fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
|
|
fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
|
|
- BigUint::parse_bytes(s.as_bytes(), radix)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl BigUint {
|
|
|
|
- /// Creates and initializes a `BigUint`.
|
|
|
|
- ///
|
|
|
|
- /// The digits are be in base 2^32.
|
|
|
|
- #[inline]
|
|
|
|
- pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
|
|
|
|
- // omit trailing zeros
|
|
|
|
- let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
|
|
|
|
- digits.truncate(new_len);
|
|
|
|
- BigUint { data: digits }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Creates and initializes a `BigUint`.
|
|
|
|
- ///
|
|
|
|
- /// The digits are be in base 2^32.
|
|
|
|
- #[inline]
|
|
|
|
- pub fn from_slice(slice: &[BigDigit]) -> BigUint {
|
|
|
|
- BigUint::new(slice.to_vec())
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Creates and initializes a `BigUint`.
|
|
|
|
- pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigUint> {
|
|
|
|
let (base, unit_len) = get_radix_base(radix);
|
|
let (base, unit_len) = get_radix_base(radix);
|
|
let base_num = match base.to_biguint() {
|
|
let base_num = match base.to_biguint() {
|
|
Some(base_num) => base_num,
|
|
Some(base_num) => base_num,
|
|
None => { return None; }
|
|
None => { return None; }
|
|
};
|
|
};
|
|
|
|
|
|
- let mut end = buf.len();
|
|
|
|
- let mut n: BigUint = Zero::zero();
|
|
|
|
- let mut power: BigUint = One::one();
|
|
|
|
|
|
+ let mut end = s.len();
|
|
|
|
+ let mut n: BigUint = Zero::zero();
|
|
|
|
+ let mut power: BigUint = One::one();
|
|
loop {
|
|
loop {
|
|
let start = cmp::max(end, unit_len) - unit_len;
|
|
let start = cmp::max(end, unit_len) - unit_len;
|
|
- match str::from_utf8(buf.slice(start, end)).and_then(|s| {
|
|
|
|
- FromStrRadix::from_str_radix(s, radix)
|
|
|
|
- }) {
|
|
|
|
|
|
+ match FromStrRadix::from_str_radix(s[start .. end], radix) {
|
|
Some(d) => {
|
|
Some(d) => {
|
|
let d: Option<BigUint> = FromPrimitive::from_uint(d);
|
|
let d: Option<BigUint> = FromPrimitive::from_uint(d);
|
|
match d {
|
|
match d {
|
|
@@ -765,13 +737,40 @@ impl BigUint {
|
|
power = power * base_num;
|
|
power = power * base_num;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl BigUint {
|
|
|
|
+ /// Creates and initializes a `BigUint`.
|
|
|
|
+ ///
|
|
|
|
+ /// The digits are be in base 2^32.
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
|
|
|
|
+ // omit trailing zeros
|
|
|
|
+ let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
|
|
|
|
+ digits.truncate(new_len);
|
|
|
|
+ BigUint { data: digits }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Creates and initializes a `BigUint`.
|
|
|
|
+ ///
|
|
|
|
+ /// The digits are be in base 2^32.
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn from_slice(slice: &[BigDigit]) -> BigUint {
|
|
|
|
+ BigUint::new(slice.to_vec())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Creates and initializes a `BigUint`.
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigUint> {
|
|
|
|
+ str::from_utf8(buf).and_then(|s| FromStrRadix::from_str_radix(s, radix))
|
|
|
|
+ }
|
|
|
|
|
|
#[inline]
|
|
#[inline]
|
|
fn shl_unit(&self, n_unit: uint) -> BigUint {
|
|
fn shl_unit(&self, n_unit: uint) -> BigUint {
|
|
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
|
|
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
|
|
|
|
|
|
let mut v = Vec::from_elem(n_unit, ZERO_BIG_DIGIT);
|
|
let mut v = Vec::from_elem(n_unit, ZERO_BIG_DIGIT);
|
|
- v.push_all(self.data.as_slice());
|
|
|
|
|
|
+ v.push_all(self.data[]);
|
|
BigUint::new(v)
|
|
BigUint::new(v)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -795,9 +794,7 @@ impl BigUint {
|
|
fn shr_unit(&self, n_unit: uint) -> BigUint {
|
|
fn shr_unit(&self, n_unit: uint) -> BigUint {
|
|
if n_unit == 0 { return (*self).clone(); }
|
|
if n_unit == 0 { return (*self).clone(); }
|
|
if self.data.len() < n_unit { return Zero::zero(); }
|
|
if self.data.len() < n_unit { return Zero::zero(); }
|
|
- return BigUint::from_slice(
|
|
|
|
- self.data.slice(n_unit, self.data.len())
|
|
|
|
- );
|
|
|
|
|
|
+ BigUint::from_slice(self.data[n_unit ..])
|
|
}
|
|
}
|
|
|
|
|
|
#[inline]
|
|
#[inline]
|
|
@@ -1280,7 +1277,15 @@ impl FromStrRadix for BigInt {
|
|
/// Creates and initializes a BigInt.
|
|
/// Creates and initializes a BigInt.
|
|
#[inline]
|
|
#[inline]
|
|
fn from_str_radix(s: &str, radix: uint) -> Option<BigInt> {
|
|
fn from_str_radix(s: &str, radix: uint) -> Option<BigInt> {
|
|
- BigInt::parse_bytes(s.as_bytes(), radix)
|
|
|
|
|
|
+ if s.is_empty() { return None; }
|
|
|
|
+ let mut sign = Plus;
|
|
|
|
+ let mut start = 0;
|
|
|
|
+ if s.starts_with("-") {
|
|
|
|
+ sign = Minus;
|
|
|
|
+ start = 1;
|
|
|
|
+ }
|
|
|
|
+ FromStrRadix::from_str_radix(s[start ..], radix)
|
|
|
|
+ .map(|bu| BigInt::from_biguint(sign, bu))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1396,18 +1401,12 @@ impl BigInt {
|
|
}
|
|
}
|
|
|
|
|
|
/// Creates and initializes a `BigInt`.
|
|
/// Creates and initializes a `BigInt`.
|
|
|
|
+ #[inline]
|
|
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
|
|
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
|
|
- if buf.is_empty() { return None; }
|
|
|
|
- let mut sign = Plus;
|
|
|
|
- let mut start = 0;
|
|
|
|
- if buf[0] == b'-' {
|
|
|
|
- sign = Minus;
|
|
|
|
- start = 1;
|
|
|
|
- }
|
|
|
|
- return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
|
|
|
|
- .map(|bu| BigInt::from_biguint(sign, bu));
|
|
|
|
|
|
+ str::from_utf8(buf).and_then(|s| FromStrRadix::from_str_radix(s, radix))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
/// Converts this `BigInt` into a `BigUint`, if it's not negative.
|
|
/// Converts this `BigInt` into a `BigUint`, if it's not negative.
|
|
#[inline]
|
|
#[inline]
|
|
pub fn to_biguint(&self) -> Option<BigUint> {
|
|
pub fn to_biguint(&self) -> Option<BigUint> {
|