Move std::num::Integer to libnum

This commit is contained in:
Brendan Zabarauskas 2014-02-17 07:20:01 +11:00
parent 2fa7d6b44f
commit 3a9eca3a7b
12 changed files with 439 additions and 421 deletions

View File

@ -85,7 +85,7 @@ syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator Cloneabl
syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize
syn keyword rustTrait Algebraic Trigonometric Exponential Hyperbolic
syn keyword rustTrait Bitwise Bounded Integer
syn keyword rustTrait Bitwise Bounded Fractional
syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv
syn keyword rustTrait Orderable Signed Unsigned Round
syn keyword rustTrait Primitive Int Float ToStrRadix ToPrimitive FromPrimitive

View File

@ -16,6 +16,8 @@ A `BigUint` is represented as an array of `BigDigit`s.
A `BigInt` is a combination of `BigUint` and `Sign`.
*/
use Integer;
use std::cmp;
use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use std::num::{Zero, One, ToStrRadix, FromStrRadix};
@ -461,7 +463,7 @@ impl Integer for BigUint {
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline]
fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
fn divides(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
/// Returns `true` if the number is divisible by `2`
#[inline]
@ -1118,7 +1120,7 @@ impl Integer for BigInt {
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline]
fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
fn divides(&self, other: &BigInt) -> bool { self.data.divides(&other.data) }
/// Returns `true` if the number is divisible by `2`
#[inline]
@ -1388,6 +1390,7 @@ impl BigInt {
#[cfg(test)]
mod biguint_tests {
use Integer;
use super::{BigDigit, BigUint, ToBigUint};
use super::{Plus, BigInt, RandBigInt, ToBigInt};
@ -2045,6 +2048,7 @@ mod biguint_tests {
#[cfg(test)]
mod bigint_tests {
use Integer;
use super::{BigDigit, BigUint, ToBigUint};
use super::{Sign, Minus, Zero, Plus, BigInt, RandBigInt, ToBigInt};

View File

@ -20,3 +20,403 @@ extern crate extra;
pub mod bigint;
pub mod rational;
pub mod complex;
pub trait Integer: Num + Ord
+ Div<Self, Self>
+ Rem<Self, Self> {
/// Simultaneous truncated integer division and modulus
#[inline]
fn div_rem(&self, other: &Self) -> (Self, Self) {
(*self / *other, *self % *other)
}
/// Floored integer division
///
/// # Examples
///
/// ~~~
/// # use num::Integer;
/// assert!(( 8i).div_floor(& 3) == 2);
/// assert!(( 8i).div_floor(&-3) == -3);
/// assert!((-8i).div_floor(& 3) == -3);
/// assert!((-8i).div_floor(&-3) == 2);
///
/// assert!(( 1i).div_floor(& 2) == 0);
/// assert!(( 1i).div_floor(&-2) == -1);
/// assert!((-1i).div_floor(& 2) == -1);
/// assert!((-1i).div_floor(&-2) == 0);
/// ~~~
fn div_floor(&self, other: &Self) -> Self;
/// Floored integer modulo, satisfying:
///
/// ~~~
/// # use num::Integer;
/// # let n = 1i; let d = 1i;
/// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
/// ~~~
///
/// # Examples
///
/// ~~~
/// # use num::Integer;
/// assert!(( 8i).mod_floor(& 3) == 2);
/// assert!(( 8i).mod_floor(&-3) == -1);
/// assert!((-8i).mod_floor(& 3) == 1);
/// assert!((-8i).mod_floor(&-3) == -2);
///
/// assert!(( 1i).mod_floor(& 2) == 1);
/// assert!(( 1i).mod_floor(&-2) == -1);
/// assert!((-1i).mod_floor(& 2) == 1);
/// assert!((-1i).mod_floor(&-2) == -1);
/// ~~~
fn mod_floor(&self, other: &Self) -> Self;
/// Simultaneous floored integer division and modulus
fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
(self.div_floor(other), self.mod_floor(other))
}
/// Greatest Common Divisor (GCD)
fn gcd(&self, other: &Self) -> Self;
/// Lowest Common Multiple (LCM)
fn lcm(&self, other: &Self) -> Self;
/// Returns `true` if `other` divides evenly into `self`
fn divides(&self, other: &Self) -> bool;
/// Returns `true` if the number is even
fn is_even(&self) -> bool;
/// Returns `true` if the number is odd
fn is_odd(&self) -> bool;
}
/// Simultaneous integer division and modulus
#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
/// Floored integer division
#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
/// Floored integer modulus
#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
/// Simultaneous floored integer division and modulus
#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
/// result is always positive.
#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
macro_rules! impl_integer_for_int {
($T:ty, $test_mod:ident) => (
impl Integer for $T {
/// Floored integer division
#[inline]
fn div_floor(&self, other: &$T) -> $T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.div_rem(other) {
(d, r) if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => d - 1,
(d, _) => d,
}
}
/// Floored integer modulo
#[inline]
fn mod_floor(&self, other: &$T) -> $T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match *self % *other {
r if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => r + *other,
r => r,
}
}
/// Calculates `div_floor` and `mod_floor` simultaneously
#[inline]
fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.div_rem(other) {
(d, r) if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => (d - 1, r + *other),
(d, r) => (d, r),
}
}
/// Calculates the Greatest Common Divisor (GCD) of the number and
/// `other`. The result is always positive.
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
n = temp;
}
n.abs()
}
/// Calculates the Lowest Common Multiple (LCM) of the number and
/// `other`.
#[inline]
fn lcm(&self, other: &$T) -> $T {
// should not have to recaluculate abs
((*self * *other) / self.gcd(other)).abs()
}
/// Returns `true` if the number can be divided by `other` without
/// leaving a remainder
#[inline]
fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline]
fn is_even(&self) -> bool { self & 1 == 0 }
/// Returns `true` if the number is not divisible by `2`
#[inline]
fn is_odd(&self) -> bool { !self.is_even() }
}
#[cfg(test)]
mod $test_mod {
use Integer;
/// Checks that the division rule holds for:
///
/// - `n`: numerator (dividend)
/// - `d`: denominator (divisor)
/// - `qr`: quotient and remainder
#[cfg(test)]
fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
assert_eq!(d * q + r, n);
}
#[test]
fn test_div_rem() {
fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
let (n,d) = nd;
let separate_div_rem = (n / d, n % d);
let combined_div_rem = n.div_rem(&d);
assert_eq!(separate_div_rem, qr);
assert_eq!(combined_div_rem, qr);
test_division_rule(nd, separate_div_rem);
test_division_rule(nd, combined_div_rem);
}
test_nd_dr(( 8, 3), ( 2, 2));
test_nd_dr(( 8, -3), (-2, 2));
test_nd_dr((-8, 3), (-2, -2));
test_nd_dr((-8, -3), ( 2, -2));
test_nd_dr(( 1, 2), ( 0, 1));
test_nd_dr(( 1, -2), ( 0, 1));
test_nd_dr((-1, 2), ( 0, -1));
test_nd_dr((-1, -2), ( 0, -1));
}
#[test]
fn test_div_mod_floor() {
fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
let (n,d) = nd;
let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
let combined_div_mod_floor = n.div_mod_floor(&d);
assert_eq!(separate_div_mod_floor, dm);
assert_eq!(combined_div_mod_floor, dm);
test_division_rule(nd, separate_div_mod_floor);
test_division_rule(nd, combined_div_mod_floor);
}
test_nd_dm(( 8, 3), ( 2, 2));
test_nd_dm(( 8, -3), (-3, -1));
test_nd_dm((-8, 3), (-3, 1));
test_nd_dm((-8, -3), ( 2, -2));
test_nd_dm(( 1, 2), ( 0, 1));
test_nd_dm(( 1, -2), (-1, -1));
test_nd_dm((-1, 2), (-1, 1));
test_nd_dm((-1, -2), ( 0, -1));
}
#[test]
fn test_gcd() {
assert_eq!((10 as $T).gcd(&2), 2 as $T);
assert_eq!((10 as $T).gcd(&3), 1 as $T);
assert_eq!((0 as $T).gcd(&3), 3 as $T);
assert_eq!((3 as $T).gcd(&3), 3 as $T);
assert_eq!((56 as $T).gcd(&42), 14 as $T);
assert_eq!((3 as $T).gcd(&-3), 3 as $T);
assert_eq!((-6 as $T).gcd(&3), 3 as $T);
assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
}
#[test]
fn test_lcm() {
assert_eq!((1 as $T).lcm(&0), 0 as $T);
assert_eq!((0 as $T).lcm(&1), 0 as $T);
assert_eq!((1 as $T).lcm(&1), 1 as $T);
assert_eq!((-1 as $T).lcm(&1), 1 as $T);
assert_eq!((1 as $T).lcm(&-1), 1 as $T);
assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
assert_eq!((8 as $T).lcm(&9), 72 as $T);
assert_eq!((11 as $T).lcm(&5), 55 as $T);
}
#[test]
fn test_even() {
assert_eq!((-4 as $T).is_even(), true);
assert_eq!((-3 as $T).is_even(), false);
assert_eq!((-2 as $T).is_even(), true);
assert_eq!((-1 as $T).is_even(), false);
assert_eq!((0 as $T).is_even(), true);
assert_eq!((1 as $T).is_even(), false);
assert_eq!((2 as $T).is_even(), true);
assert_eq!((3 as $T).is_even(), false);
assert_eq!((4 as $T).is_even(), true);
}
#[test]
fn test_odd() {
assert_eq!((-4 as $T).is_odd(), false);
assert_eq!((-3 as $T).is_odd(), true);
assert_eq!((-2 as $T).is_odd(), false);
assert_eq!((-1 as $T).is_odd(), true);
assert_eq!((0 as $T).is_odd(), false);
assert_eq!((1 as $T).is_odd(), true);
assert_eq!((2 as $T).is_odd(), false);
assert_eq!((3 as $T).is_odd(), true);
assert_eq!((4 as $T).is_odd(), false);
}
}
)
}
impl_integer_for_int!(i8, test_integer_i8)
impl_integer_for_int!(i16, test_integer_i16)
impl_integer_for_int!(i32, test_integer_i32)
impl_integer_for_int!(i64, test_integer_i64)
impl_integer_for_int!(int, test_integer_int)
macro_rules! impl_integer_for_uint {
($T:ty, $test_mod:ident) => (
impl Integer for $T {
/// Unsigned integer division. Returns the same result as `div` (`/`).
#[inline]
fn div_floor(&self, other: &$T) -> $T { *self / *other }
/// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
#[inline]
fn mod_floor(&self, other: &$T) -> $T { *self % *other }
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
n = temp;
}
n
}
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
#[inline]
fn lcm(&self, other: &$T) -> $T {
(*self * *other) / self.gcd(other)
}
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline]
fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline]
fn is_even(&self) -> bool { self & 1 == 0 }
/// Returns `true` if the number is not divisible by `2`
#[inline]
fn is_odd(&self) -> bool { !self.is_even() }
}
#[cfg(test)]
mod $test_mod {
use Integer;
#[test]
fn test_div_mod_floor() {
assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
}
#[test]
fn test_gcd() {
assert_eq!((10 as $T).gcd(&2), 2 as $T);
assert_eq!((10 as $T).gcd(&3), 1 as $T);
assert_eq!((0 as $T).gcd(&3), 3 as $T);
assert_eq!((3 as $T).gcd(&3), 3 as $T);
assert_eq!((56 as $T).gcd(&42), 14 as $T);
}
#[test]
fn test_lcm() {
assert_eq!((1 as $T).lcm(&0), 0 as $T);
assert_eq!((0 as $T).lcm(&1), 0 as $T);
assert_eq!((1 as $T).lcm(&1), 1 as $T);
assert_eq!((8 as $T).lcm(&9), 72 as $T);
assert_eq!((11 as $T).lcm(&5), 55 as $T);
assert_eq!((99 as $T).lcm(&17), 1683 as $T);
}
#[test]
fn test_divides() {
assert!((6 as $T).divides(&(6 as $T)));
assert!((6 as $T).divides(&(3 as $T)));
assert!((6 as $T).divides(&(1 as $T)));
}
#[test]
fn test_even() {
assert_eq!((0 as $T).is_even(), true);
assert_eq!((1 as $T).is_even(), false);
assert_eq!((2 as $T).is_even(), true);
assert_eq!((3 as $T).is_even(), false);
assert_eq!((4 as $T).is_even(), true);
}
#[test]
fn test_odd() {
assert_eq!((0 as $T).is_odd(), false);
assert_eq!((1 as $T).is_odd(), true);
assert_eq!((2 as $T).is_odd(), false);
assert_eq!((3 as $T).is_odd(), true);
assert_eq!((4 as $T).is_odd(), false);
}
}
)
}
impl_integer_for_uint!(u8, test_integer_u8)
impl_integer_for_uint!(u16, test_integer_u16)
impl_integer_for_uint!(u32, test_integer_u32)
impl_integer_for_uint!(u64, test_integer_u64)
impl_integer_for_uint!(uint, test_integer_uint)

View File

@ -10,6 +10,8 @@
//! Rational numbers
use Integer;
use std::cmp;
use std::from_str::FromStr;
use std::num::{Zero,One,ToStrRadix,FromStrRadix,Round};

View File

@ -65,7 +65,7 @@ the rest of the rust manuals.
*/
use cmp;
use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating, ToPrimitive};
use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int};
use option::{Option, Some, None};
use ops::{Add, Mul, Sub};
use cmp::{Eq, Ord};
@ -2005,9 +2005,9 @@ impl<A: Add<A, A> + Ord + Clone + ToPrimitive> Iterator<A> for Range<A> {
}
}
/// `Integer` is required to ensure the range will be the same regardless of
/// `Int` is required to ensure the range will be the same regardless of
/// the direction it is consumed.
impl<A: Integer + Ord + Clone + ToPrimitive> DoubleEndedIterator<A> for Range<A> {
impl<A: Int + Ord + Clone + ToPrimitive> DoubleEndedIterator<A> for Range<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
if self.stop > self.state {
@ -2065,7 +2065,7 @@ impl<A: Add<A, A> + Eq + Ord + Clone + ToPrimitive> Iterator<A> for RangeInclusi
}
}
impl<A: Sub<A, A> + Integer + Ord + Clone + ToPrimitive> DoubleEndedIterator<A>
impl<A: Sub<A, A> + Int + Ord + Clone + ToPrimitive> DoubleEndedIterator<A>
for RangeInclusive<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
@ -2381,7 +2381,7 @@ mod tests {
#[test]
fn test_filter_map() {
let mut it = count(0u, 1u).take(10)
.filter_map(|x| if x.is_even() { Some(x*x) } else { None });
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
}
@ -2648,7 +2648,7 @@ mod tests {
fn test_all() {
let v: ~&[int] = ~&[1, 2, 3, 4, 5];
assert!(v.iter().all(|&x| x < 10));
assert!(!v.iter().all(|&x| x.is_even()));
assert!(!v.iter().all(|&x| x % 2 == 0));
assert!(!v.iter().all(|&x| x > 100));
assert!(v.slice(0, 0).iter().all(|_| fail!()));
}
@ -2657,7 +2657,7 @@ mod tests {
fn test_any() {
let v: ~&[int] = ~&[1, 2, 3, 4, 5];
assert!(v.iter().any(|&x| x < 10));
assert!(v.iter().any(|&x| x.is_even()));
assert!(v.iter().any(|&x| x % 2 == 0));
assert!(!v.iter().any(|&x| x > 100));
assert!(!v.slice(0, 0).iter().any(|_| fail!()));
}

View File

@ -91,53 +91,48 @@ impl Mul<$T,$T> for $T {
#[cfg(not(test))]
impl Div<$T,$T> for $T {
///
/// Integer division, truncated towards 0. As this behaviour reflects the underlying
/// machine implementation it is more efficient than `Integer::div_floor`.
/// Integer division, truncated towards 0.
///
/// # Examples
///
/// ```
/// ~~~
/// assert!( 8 / 3 == 2);
/// assert!( 8 / -3 == -2);
/// assert!(-8 / 3 == -2);
/// assert!(-8 / -3 == 2);
///
/// assert!( 1 / 2 == 0);
/// assert!( 1 / -2 == 0);
/// assert!(-1 / 2 == 0);
/// assert!(-1 / -2 == 0);
/// ```
///
/// ~~~
#[inline]
fn div(&self, other: &$T) -> $T { *self / *other }
}
#[cfg(not(test))]
impl Rem<$T,$T> for $T {
///
/// Returns the integer remainder after division, satisfying:
///
/// ```
/// ~~~
/// # let n = 1;
/// # let d = 2;
/// assert!((n / d) * d + (n % d) == n)
/// ```
/// ~~~
///
/// # Examples
///
/// ```
/// ~~~
/// assert!( 8 % 3 == 2);
/// assert!( 8 % -3 == 2);
/// assert!(-8 % 3 == -2);
/// assert!(-8 % -3 == -2);
///
/// assert!( 1 % 2 == 1);
/// assert!( 1 % -2 == 1);
/// assert!(-1 % 2 == -1);
/// assert!(-1 % -2 == -1);
/// ```
///
/// ~~~
#[inline]
fn rem(&self, other: &$T) -> $T { *self % *other }
}
@ -189,125 +184,6 @@ impl Signed for $T {
fn is_negative(&self) -> bool { *self < 0 }
}
impl Integer for $T {
///
/// Floored integer division
///
/// # Examples
///
/// ```
/// assert!(( 8i).div_floor(& 3) == 2);
/// assert!(( 8i).div_floor(&-3) == -3);
/// assert!((-8i).div_floor(& 3) == -3);
/// assert!((-8i).div_floor(&-3) == 2);
///
/// assert!(( 1i).div_floor(& 2) == 0);
/// assert!(( 1i).div_floor(&-2) == -1);
/// assert!((-1i).div_floor(& 2) == -1);
/// assert!((-1i).div_floor(&-2) == 0);
/// ```
///
#[inline]
fn div_floor(&self, other: &$T) -> $T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.div_rem(other) {
(d, r) if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => d - 1,
(d, _) => d,
}
}
///
/// Integer modulo, satisfying:
///
/// ```
/// # let n = 1i; let d = 1i;
/// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
/// ```
///
/// # Examples
///
/// ```
/// assert!(( 8i).mod_floor(& 3) == 2);
/// assert!(( 8i).mod_floor(&-3) == -1);
/// assert!((-8i).mod_floor(& 3) == 1);
/// assert!((-8i).mod_floor(&-3) == -2);
///
/// assert!(( 1i).mod_floor(& 2) == 1);
/// assert!(( 1i).mod_floor(&-2) == -1);
/// assert!((-1i).mod_floor(& 2) == 1);
/// assert!((-1i).mod_floor(&-2) == -1);
/// ```
///
#[inline]
fn mod_floor(&self, other: &$T) -> $T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match *self % *other {
r if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => r + *other,
r => r,
}
}
/// Calculates `div_floor` and `mod_floor` simultaneously
#[inline]
fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.div_rem(other) {
(d, r) if (r > 0 && *other < 0)
|| (r < 0 && *other > 0) => (d - 1, r + *other),
(d, r) => (d, r),
}
}
/// Calculates `div` (`/`) and `rem` (`%`) simultaneously
#[inline]
fn div_rem(&self, other: &$T) -> ($T,$T) {
(*self / *other, *self % *other)
}
///
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
///
/// The result is always positive
///
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
n = temp;
}
n.abs()
}
///
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
///
#[inline]
fn lcm(&self, other: &$T) -> $T {
((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs
}
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline]
fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline]
fn is_even(&self) -> bool { self & 1 == 0 }
/// Returns `true` if the number is not divisible by `2`
#[inline]
fn is_odd(&self) -> bool { !self.is_even() }
}
#[cfg(not(test))]
impl BitOr<$T,$T> for $T {
#[inline]
@ -481,92 +357,6 @@ mod tests {
assert!((-1 as $T).is_negative());
}
///
/// Checks that the division rule holds for:
///
/// - `n`: numerator (dividend)
/// - `d`: denominator (divisor)
/// - `qr`: quotient and remainder
///
#[cfg(test)]
fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
assert_eq!(d * q + r, n);
}
#[test]
fn test_div_rem() {
fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
let (n,d) = nd;
let separate_div_rem = (n / d, n % d);
let combined_div_rem = n.div_rem(&d);
assert_eq!(separate_div_rem, qr);
assert_eq!(combined_div_rem, qr);
test_division_rule(nd, separate_div_rem);
test_division_rule(nd, combined_div_rem);
}
test_nd_dr(( 8, 3), ( 2, 2));
test_nd_dr(( 8, -3), (-2, 2));
test_nd_dr((-8, 3), (-2, -2));
test_nd_dr((-8, -3), ( 2, -2));
test_nd_dr(( 1, 2), ( 0, 1));
test_nd_dr(( 1, -2), ( 0, 1));
test_nd_dr((-1, 2), ( 0, -1));
test_nd_dr((-1, -2), ( 0, -1));
}
#[test]
fn test_div_mod_floor() {
fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
let (n,d) = nd;
let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
let combined_div_mod_floor = n.div_mod_floor(&d);
assert_eq!(separate_div_mod_floor, dm);
assert_eq!(combined_div_mod_floor, dm);
test_division_rule(nd, separate_div_mod_floor);
test_division_rule(nd, combined_div_mod_floor);
}
test_nd_dm(( 8, 3), ( 2, 2));
test_nd_dm(( 8, -3), (-3, -1));
test_nd_dm((-8, 3), (-3, 1));
test_nd_dm((-8, -3), ( 2, -2));
test_nd_dm(( 1, 2), ( 0, 1));
test_nd_dm(( 1, -2), (-1, -1));
test_nd_dm((-1, 2), (-1, 1));
test_nd_dm((-1, -2), ( 0, -1));
}
#[test]
fn test_gcd() {
assert_eq!((10 as $T).gcd(&2), 2 as $T);
assert_eq!((10 as $T).gcd(&3), 1 as $T);
assert_eq!((0 as $T).gcd(&3), 3 as $T);
assert_eq!((3 as $T).gcd(&3), 3 as $T);
assert_eq!((56 as $T).gcd(&42), 14 as $T);
assert_eq!((3 as $T).gcd(&-3), 3 as $T);
assert_eq!((-6 as $T).gcd(&3), 3 as $T);
assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
}
#[test]
fn test_lcm() {
assert_eq!((1 as $T).lcm(&0), 0 as $T);
assert_eq!((0 as $T).lcm(&1), 0 as $T);
assert_eq!((1 as $T).lcm(&1), 1 as $T);
assert_eq!((-1 as $T).lcm(&1), 1 as $T);
assert_eq!((1 as $T).lcm(&-1), 1 as $T);
assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
assert_eq!((8 as $T).lcm(&9), 72 as $T);
assert_eq!((11 as $T).lcm(&5), 55 as $T);
}
#[test]
fn test_bitwise() {
assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(&(0b1010 as $T)));
@ -577,42 +367,6 @@ mod tests {
assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
}
#[test]
fn test_multiple_of() {
assert!((6 as $T).is_multiple_of(&(6 as $T)));
assert!((6 as $T).is_multiple_of(&(3 as $T)));
assert!((6 as $T).is_multiple_of(&(1 as $T)));
assert!((-8 as $T).is_multiple_of(&(4 as $T)));
assert!((8 as $T).is_multiple_of(&(-1 as $T)));
assert!((-8 as $T).is_multiple_of(&(-2 as $T)));
}
#[test]
fn test_even() {
assert_eq!((-4 as $T).is_even(), true);
assert_eq!((-3 as $T).is_even(), false);
assert_eq!((-2 as $T).is_even(), true);
assert_eq!((-1 as $T).is_even(), false);
assert_eq!((0 as $T).is_even(), true);
assert_eq!((1 as $T).is_even(), false);
assert_eq!((2 as $T).is_even(), true);
assert_eq!((3 as $T).is_even(), false);
assert_eq!((4 as $T).is_even(), true);
}
#[test]
fn test_odd() {
assert_eq!((-4 as $T).is_odd(), false);
assert_eq!((-3 as $T).is_odd(), true);
assert_eq!((-2 as $T).is_odd(), false);
assert_eq!((-1 as $T).is_odd(), true);
assert_eq!((0 as $T).is_odd(), false);
assert_eq!((1 as $T).is_odd(), true);
assert_eq!((2 as $T).is_odd(), false);
assert_eq!((3 as $T).is_odd(), true);
assert_eq!((4 as $T).is_odd(), false);
}
#[test]
fn test_count_ones() {
assert_eq!((0b0101100 as $T).count_ones(), 3);

View File

@ -33,6 +33,12 @@ pub trait Num: Eq + Zero + One
+ Div<Self,Self>
+ Rem<Self,Self> {}
/// Simultaneous division and remainder
#[inline]
pub fn div_rem<T: Div<T, T> + Rem<T, T>>(x: T, y: T) -> (T, T) {
(x / y, x % y)
}
/// Defines an additive identity element for `Self`.
///
/// # Deriving
@ -122,31 +128,6 @@ pub trait Signed: Num
pub trait Unsigned: Num {}
pub trait Integer: Num
+ Ord
+ Div<Self,Self>
+ Rem<Self,Self> {
fn div_rem(&self, other: &Self) -> (Self,Self);
fn div_floor(&self, other: &Self) -> Self;
fn mod_floor(&self, other: &Self) -> Self;
fn div_mod_floor(&self, other: &Self) -> (Self,Self);
fn gcd(&self, other: &Self) -> Self;
fn lcm(&self, other: &Self) -> Self;
fn is_multiple_of(&self, other: &Self) -> bool;
fn is_even(&self) -> bool;
fn is_odd(&self) -> bool;
}
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`.
///
/// The result is always positive.
#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
/// A collection of rounding operations.
pub trait Round {
/// Return the largest integer less than or equal to a number.
@ -270,8 +251,7 @@ pub trait Primitive: Clone
+ Bounded {}
/// A collection of traits relevant to primitive signed and unsigned integers
pub trait Int: Integer
+ Primitive
pub trait Int: Primitive
+ Bitwise
+ CheckedAdd
+ CheckedSub

View File

@ -21,7 +21,7 @@ use str;
use vec::{CloneableVector, ImmutableVector, MutableVector};
use vec::OwnedVector;
use num;
use num::{NumCast, Zero, One, cast, Integer};
use num::{NumCast, Zero, One, cast, Int};
use num::{Round, Float, FPNaN, FPInfinite, ToPrimitive};
pub enum ExponentFormat {
@ -133,19 +133,7 @@ static NAN_BUF: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
* # Failure
* - Fails if `radix` < 2 or `radix` > 36.
*/
pub fn int_to_str_bytes_common<T:NumCast
+Zero
+Eq
+Ord
+Integer
+Div<T,T>
+Neg<T>
+Rem<T,T>
+Mul<T,T>>(
num: T,
radix: uint,
sign: SignFormat,
f: |u8|) {
pub fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
assert!(2 <= radix && radix <= 36);
let _0: T = Zero::zero();

View File

@ -100,60 +100,6 @@ impl Neg<$T> for $T {
impl Unsigned for $T {}
impl Integer for $T {
/// Calculates `div` (`/`) and `rem` (`%`) simultaneously
#[inline]
fn div_rem(&self, other: &$T) -> ($T,$T) {
(*self / *other, *self % *other)
}
/// Unsigned integer division. Returns the same result as `div` (`/`).
#[inline]
fn div_floor(&self, other: &$T) -> $T { *self / *other }
/// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
#[inline]
fn mod_floor(&self, other: &$T) -> $T { *self % *other }
/// Calculates `div_floor` and `mod_floor` simultaneously
#[inline]
fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
(*self / *other, *self % *other)
}
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
n = temp;
}
n
}
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
#[inline]
fn lcm(&self, other: &$T) -> $T {
(*self * *other) / self.gcd(other)
}
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline]
fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline]
fn is_even(&self) -> bool { self & 1 == 0 }
/// Returns `true` if the number is not divisible by `2`
#[inline]
fn is_odd(&self) -> bool { !self.is_even() }
}
#[cfg(not(test))]
impl BitOr<$T,$T> for $T {
#[inline]
@ -309,63 +255,6 @@ mod tests {
num::test_num(10 as $T, 2 as $T);
}
#[test]
fn test_div_mod_floor() {
assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
}
#[test]
fn test_gcd() {
assert_eq!((10 as $T).gcd(&2), 2 as $T);
assert_eq!((10 as $T).gcd(&3), 1 as $T);
assert_eq!((0 as $T).gcd(&3), 3 as $T);
assert_eq!((3 as $T).gcd(&3), 3 as $T);
assert_eq!((56 as $T).gcd(&42), 14 as $T);
}
#[test]
fn test_lcm() {
assert_eq!((1 as $T).lcm(&0), 0 as $T);
assert_eq!((0 as $T).lcm(&1), 0 as $T);
assert_eq!((1 as $T).lcm(&1), 1 as $T);
assert_eq!((8 as $T).lcm(&9), 72 as $T);
assert_eq!((11 as $T).lcm(&5), 55 as $T);
assert_eq!((99 as $T).lcm(&17), 1683 as $T);
}
#[test]
fn test_multiple_of() {
assert!((6 as $T).is_multiple_of(&(6 as $T)));
assert!((6 as $T).is_multiple_of(&(3 as $T)));
assert!((6 as $T).is_multiple_of(&(1 as $T)));
}
#[test]
fn test_even() {
assert_eq!((0 as $T).is_even(), true);
assert_eq!((1 as $T).is_even(), false);
assert_eq!((2 as $T).is_even(), true);
assert_eq!((3 as $T).is_even(), false);
assert_eq!((4 as $T).is_even(), true);
}
#[test]
fn test_odd() {
assert_eq!((0 as $T).is_odd(), false);
assert_eq!((1 as $T).is_odd(), true);
assert_eq!((2 as $T).is_odd(), false);
assert_eq!((3 as $T).is_odd(), true);
assert_eq!((4 as $T).is_odd(), false);
}
#[test]
fn test_bitwise() {
assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(&(0b1010 as $T)));

View File

@ -49,7 +49,7 @@ pub use hash::Hash;
pub use iter::{FromIterator, Extendable};
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
pub use num::{Integer, Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Signed, Unsigned, Round};
pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
pub use path::{GenericPath, Path, PosixPath, WindowsPath};

View File

@ -111,7 +111,7 @@ use cmp;
use default::Default;
use fmt;
use iter::*;
use num::{Integer, CheckedAdd, Saturating, checked_next_power_of_two};
use num::{CheckedAdd, Saturating, checked_next_power_of_two, div_rem};
use option::{None, Option, Some};
use ptr;
use ptr::RawPtr;
@ -575,7 +575,7 @@ impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> {
if self.v.len() == 0 {
(0, Some(0))
} else {
let (n, rem) = self.v.len().div_rem(&self.size);
let (n, rem) = div_rem(self.v.len(), self.size);
let n = if rem > 0 { n+1 } else { n };
(n, Some(n))
}
@ -2859,7 +2859,7 @@ impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
if self.v.len() == 0 {
(0, Some(0))
} else {
let (n, rem) = self.v.len().div_rem(&self.chunk_size);
let (n, rem) = div_rem(self.v.len(), self.chunk_size);
let n = if rem > 0 { n + 1 } else { n };
(n, Some(n))
}

View File

@ -14,6 +14,7 @@ use std::from_str::FromStr;
use std::num::One;
use std::num::Zero;
use std::num::FromPrimitive;
use num::Integer;
use num::bigint::BigInt;
struct Context {