about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-04-27 13:09:35 -0700
committerbors <bors@rust-lang.org>2013-04-27 13:09:35 -0700
commitaa38867e4e7da648a85985251f542bee12a64095 (patch)
treea63425d6739dc5cad3d1a09c9e63404a40545ff3 /src/libstd
parent5de74f3e754628fa98c0cdf0b95b39f39db50e19 (diff)
parent9cdf402c80536c7e138d04433ee3f0a0855f08ce (diff)
downloadrust-aa38867e4e7da648a85985251f542bee12a64095.tar.gz
rust-aa38867e4e7da648a85985251f542bee12a64095.zip
auto merge of #6071 : bjz/rust/numeric-traits, r=graydon
As part of the numeric trait reform (see issue #4819), I have added the following traits to `core::num` and implemented them for Rust's primitive numeric types:

~~~rust
pub trait Bitwise: Not<Self>
                 + BitAnd<Self,Self>
                 + BitOr<Self,Self>
                 + BitXor<Self,Self>
                 + Shl<Self,Self>
                 + Shr<Self,Self> {}

pub trait BitCount {
    fn population_count(&self) -> Self;
    fn leading_zeros(&self) -> Self;
    fn trailing_zeros(&self) -> Self;
}

pub trait Bounded {
    fn min_value() -> Self;
    fn max_value() -> Self;
}

pub trait Primitive: Num
                   + NumCast
                   + Bounded
                   + Neg<Self>
                   + Add<Self,Self>
                   + Sub<Self,Self>
                   + Mul<Self,Self>
                   + Quot<Self,Self>
                   + Rem<Self,Self> {
    fn bits() -> uint;
    fn bytes() -> uint;
}

pub trait Int: Integer
             + Primitive
             + Bitwise
             + BitCount {}

pub trait Float: Real
               + Signed
               + Primitive {
    fn NaN() -> Self;
    fn infinity() -> Self;
    fn neg_infinity() -> Self;
    fn neg_zero() -> Self;

    fn is_NaN(&self) -> bool;
    fn is_infinite(&self) -> bool;
    fn is_finite(&self) -> bool;

    fn mantissa_digits() -> uint;
    fn digits() -> uint;
    fn epsilon() -> Self;
    fn min_exp() -> int;
    fn max_exp() -> int;
    fn min_10_exp() -> int;
    fn max_10_exp() -> int;

    fn mul_add(&self, a: Self, b: Self) -> Self;
    fn next_after(&self, other: Self) -> Self;
}
~~~
Note: I'm not sure my implementation for `BitCount::trailing_zeros` and `BitCount::leading_zeros` is correct for uints. I also need some assistance creating appropriate unit tests for them.

More work needs to be done in implementing specialized primitive floating-point and integer methods, but I'm beginning to reach the limits of my knowledge. Please leave your suggestions/critiques/ideas on #4819 if you have them – I'd very much appreciate hearing them.

I have also added an `Orderable` trait:

~~~rust
pub trait Orderable: Ord {
    fn min(&self, other: &Self) -> Self;
    fn max(&self, other: &Self) -> Self;
    fn clamp(&self, mn: &Self, mx: &Self) -> Self;
}
~~~

This is a temporary trait until we have default methods. We don't want to encumber all implementors of Ord by requiring them to implement these functions, but at the same time we want to be able to take advantage of the speed of the specific numeric functions (like the `fmin` and `fmax` intrinsics).
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/num/bigint.rs36
-rw-r--r--src/libstd/num/complex.rs5
-rw-r--r--src/libstd/num/rational.rs5
3 files changed, 27 insertions, 19 deletions
diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs
index 5f0fd76640a..214bb0be0ed 100644
--- a/src/libstd/num/bigint.rs
+++ b/src/libstd/num/bigint.rs
@@ -148,10 +148,12 @@ impl Shr<uint, BigUint> for BigUint {
 
 impl Zero for BigUint {
     fn zero() -> BigUint { BigUint::new(~[]) }
+
+    fn is_zero(&self) -> bool { self.data.is_empty() }
 }
 
 impl One for BigUint {
-    pub fn one() -> BigUint { BigUint::new(~[1]) }
+    fn one() -> BigUint { BigUint::new(~[1]) }
 }
 
 impl Unsigned for BigUint {}
@@ -310,7 +312,7 @@ impl ToStrRadix for BigUint {
                 result += [m0.to_uint() as BigDigit];
                 m = d;
             }
-            if m.is_not_zero() {
+            if !m.is_zero() {
                 result += [m.to_uint() as BigDigit];
             }
             return result;
@@ -470,10 +472,6 @@ pub impl BigUint {
         self.div_mod(other)
     }
 
-    fn is_zero(&self) -> bool { self.data.is_empty() }
-
-    fn is_not_zero(&self) -> bool { !self.data.is_empty() }
-
     fn to_uint(&self) -> uint {
         match self.data.len() {
             0 => 0,
@@ -684,6 +682,8 @@ impl Zero for BigInt {
     pub fn zero() -> BigInt {
         BigInt::from_biguint(Zero, Zero::zero())
     }
+
+    fn is_zero(&self) -> bool { self.sign == Zero }
 }
 
 impl One for BigInt {
@@ -909,8 +909,6 @@ pub impl BigInt {
 
     fn is_zero(&self) -> bool { self.sign == Zero }
 
-    fn is_not_zero(&self) -> bool { self.sign != Zero }
-
     fn to_uint(&self) -> uint {
         match self.sign {
             Plus  => self.data.to_uint(),
@@ -1212,10 +1210,10 @@ mod biguint_tests {
             let b = BigUint::from_slice(bVec);
             let c = BigUint::from_slice(cVec);
 
-            if a.is_not_zero() {
+            if !a.is_zero() {
                 assert!(c.quot_rem(&a) == (b, Zero::zero()));
             }
-            if b.is_not_zero() {
+            if !b.is_zero() {
                 assert!(c.quot_rem(&b) == (a, Zero::zero()));
             }
         }
@@ -1227,7 +1225,7 @@ mod biguint_tests {
             let c = BigUint::from_slice(cVec);
             let d = BigUint::from_slice(dVec);
 
-            if b.is_not_zero() { assert!(a.quot_rem(&b) == (c, d)); }
+            if !b.is_zero() { assert!(a.quot_rem(&b) == (c, d)); }
         }
     }
 
@@ -1577,7 +1575,7 @@ mod bigint_tests {
     fn test_div_mod() {
         fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
             let (d, m) = a.div_mod(b);
-            if m.is_not_zero() {
+            if !m.is_zero() {
                 assert!(m.sign == b.sign);
             }
             assert!(m.abs() <= b.abs());
@@ -1606,8 +1604,8 @@ mod bigint_tests {
             let b = BigInt::from_slice(Plus, bVec);
             let c = BigInt::from_slice(Plus, cVec);
 
-            if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
-            if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+            if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+            if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
         }
 
         for quot_rem_quadruples.each |elm| {
@@ -1617,7 +1615,7 @@ mod bigint_tests {
             let c = BigInt::from_slice(Plus, cVec);
             let d = BigInt::from_slice(Plus, dVec);
 
-            if b.is_not_zero() {
+            if !b.is_zero() {
                 check(&a, &b, &c, &d);
             }
         }
@@ -1628,7 +1626,7 @@ mod bigint_tests {
     fn test_quot_rem() {
         fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
             let (q, r) = a.quot_rem(b);
-            if r.is_not_zero() {
+            if !r.is_zero() {
                 assert!(r.sign == a.sign);
             }
             assert!(r.abs() <= b.abs());
@@ -1649,8 +1647,8 @@ mod bigint_tests {
             let b = BigInt::from_slice(Plus, bVec);
             let c = BigInt::from_slice(Plus, cVec);
 
-            if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
-            if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+            if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+            if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
         }
 
         for quot_rem_quadruples.each |elm| {
@@ -1660,7 +1658,7 @@ mod bigint_tests {
             let c = BigInt::from_slice(Plus, cVec);
             let d = BigInt::from_slice(Plus, dVec);
 
-            if b.is_not_zero() {
+            if !b.is_zero() {
                 check(&a, &b, &c, &d);
             }
         }
diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs
index ef7fa397d7f..fc17cbc678e 100644
--- a/src/libstd/num/complex.rs
+++ b/src/libstd/num/complex.rs
@@ -125,6 +125,11 @@ impl<T: Copy + Num> Zero for Cmplx<T> {
     fn zero() -> Cmplx<T> {
         Cmplx::new(Zero::zero(), Zero::zero())
     }
+
+    #[inline]
+    fn is_zero(&self) -> bool {
+        *self == Zero::zero()
+    }
 }
 
 impl<T: Copy + Num> One for Cmplx<T> {
diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs
index 8af1d99fa47..93b63593a5e 100644
--- a/src/libstd/num/rational.rs
+++ b/src/libstd/num/rational.rs
@@ -191,6 +191,11 @@ impl<T: Copy + Num + Ord>
     fn zero() -> Ratio<T> {
         Ratio::new_raw(Zero::zero(), One::one())
     }
+
+    #[inline]
+    fn is_zero(&self) -> bool {
+        *self == Zero::zero()
+    }
 }
 
 impl<T: Copy + Num + Ord>