about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libextra/uuid.rs45
-rw-r--r--src/libstd/bool.rs7
-rw-r--r--src/libstd/char.rs10
-rw-r--r--src/libstd/iter.rs6
-rw-r--r--src/libstd/num/mod.rs134
-rw-r--r--src/libstd/tuple.rs13
-rw-r--r--src/libstd/unit.rs10
-rw-r--r--src/test/run-pass/deriving-zero.rs61
-rw-r--r--src/test/run-pass/issue-5554.rs23
9 files changed, 147 insertions, 162 deletions
diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs
index 2c48a7a4d3e..02930dc9c4c 100644
--- a/src/libextra/uuid.rs
+++ b/src/libextra/uuid.rs
@@ -57,7 +57,7 @@ Examples of string representations:
 
 use std::str;
 use std::vec;
-use std::num::{FromStrRadix, Zero};
+use std::num::FromStrRadix;
 use std::char::Char;
 use std::container::Container;
 use std::to_str::ToStr;
@@ -158,9 +158,8 @@ static UuidGroupLens: [uint, ..5] = [8u, 4u, 4u, 4u, 12u];
 
 /// UUID support
 impl Uuid {
-
     /// Returns a nil or empty UUID (containing all zeroes)
-    pub fn new_nil() -> Uuid {
+    pub fn nil() -> Uuid {
         let uuid = Uuid{ bytes: [0, .. 16] };
         uuid
     }
@@ -423,24 +422,17 @@ impl Uuid {
 
         Ok(Uuid::from_bytes(ub).unwrap())
     }
-}
 
-impl Default for Uuid {
-    /// Returns the nil UUID, which is all zeroes
-    fn default() -> Uuid {
-        Uuid::new_nil()
+    /// Tests if the UUID is nil
+    pub fn is_nil(&self) -> bool {
+        return self.bytes.iter().all(|&b| b == 0);
     }
 }
 
-impl Zero for Uuid {
+impl Default for Uuid {
     /// Returns the nil UUID, which is all zeroes
-    fn zero() -> Uuid {
-        Uuid::new_nil()
-    }
-
-    /// Tests if the UUID is nil or all zeroes
-    fn is_zero(&self) -> bool {
-        return self.bytes.iter().all(|&b| b == 0);
+    fn default() -> Uuid {
+        Uuid::nil()
     }
 }
 
@@ -521,24 +513,15 @@ mod test {
     use super::*;
     use std::str;
     use std::rand;
-    use std::num::Zero;
     use std::io::MemWriter;
 
     #[test]
-    fn test_new_nil() {
-        let nil = Uuid::new_nil();
-        let nb = nil.to_bytes();
-
-        assert!(nb.iter().all(|&b| b == 0));
-    }
-
-    #[test]
-    fn test_zero() {
-        let uz: Uuid = Zero::zero();
-        let nz = Uuid::new_v4();
+    fn test_nil() {
+        let nil = Uuid::nil();
+        let not_nil = Uuid::new_v4();
 
-        assert!(uz.is_zero());
-        assert!(! nz.is_zero());
+        assert!(nil.is_nil());
+        assert!(!not_nil.is_nil());
     }
 
     #[test]
@@ -619,7 +602,7 @@ mod test {
         assert!(Uuid::parse_string("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
 
         // Nil
-        let nil = Uuid::new_nil();
+        let nil = Uuid::nil();
         assert!(Uuid::parse_string("00000000000000000000000000000000").unwrap()  == nil);
         assert!(Uuid::parse_string("00000000-0000-0000-0000-000000000000").unwrap() == nil);
 
diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs
index d080262ccc7..af745f94fb5 100644
--- a/src/libstd/bool.rs
+++ b/src/libstd/bool.rs
@@ -40,7 +40,6 @@ use num::FromPrimitive;
 #[cfg(not(test))] use cmp::{Eq, Ord, TotalOrd, Ordering};
 #[cfg(not(test))] use ops::{Not, BitAnd, BitOr, BitXor};
 #[cfg(not(test))] use default::Default;
-#[cfg(not(test))] use num::Zero;
 
 /////////////////////////////////////////////////////////////////////////////
 // Freestanding functions
@@ -309,12 +308,6 @@ impl Default for bool {
     fn default() -> bool { false }
 }
 
-#[cfg(not(test))]
-impl Zero for bool {
-    fn zero() -> bool { false }
-    fn is_zero(&self) -> bool { *self == false }
-}
-
 #[cfg(test)]
 mod tests {
     use prelude::*;
diff --git a/src/libstd/char.rs b/src/libstd/char.rs
index 4e9c72de618..71a297d7176 100644
--- a/src/libstd/char.rs
+++ b/src/libstd/char.rs
@@ -22,7 +22,6 @@ use str;
 
 #[cfg(not(test))] use cmp::{Eq, Ord};
 #[cfg(not(test))] use default::Default;
-#[cfg(not(test))] use num::Zero;
 
 // UTF-8 ranges and tags for encoding characters
 static TAG_CONT: uint = 128u;
@@ -449,15 +448,6 @@ impl Default for char {
     fn default() -> char { '\x00' }
 }
 
-#[cfg(not(test))]
-impl Zero for char {
-    #[inline]
-    fn zero() -> char { '\x00' }
-
-    #[inline]
-    fn is_zero(&self) -> bool { *self == '\x00' }
-}
-
 #[test]
 fn test_is_lowercase() {
     assert!('a'.is_lowercase());
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index fcf0f4f2444..8081c6ed8db 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -2872,6 +2872,12 @@ mod tests {
             }
         }
 
+        impl Mul<Foo, Foo> for Foo {
+            fn mul(&self, _: &Foo) -> Foo {
+                Foo
+            }
+        }
+
         impl num::One for Foo {
             fn one() -> Foo {
                 Foo
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index c374d6c2157..34dd313d442 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -50,19 +50,59 @@ pub trait Orderable: Ord {
 /// Returns the number constrained within the range `mn <= self <= mx`.
 #[inline(always)] pub fn clamp<T: Orderable>(value: T, mn: T, mx: T) -> T { value.clamp(&mn, &mx) }
 
-pub trait Zero {
-    fn zero() -> Self;      // FIXME (#5527): This should be an associated constant
+/// Defines an additive identity element for `Self`.
+///
+/// # Deriving
+///
+/// This trait can be automatically be derived using `#[deriving(Zero)]`
+/// attribute. If you choose to use this, make sure that the laws outlined in
+/// the documentation for `Zero::zero` still hold.
+pub trait Zero: Add<Self, Self> {
+    /// Returns the additive identity element of `Self`, `0`.
+    ///
+    /// # Laws
+    ///
+    /// ~~~
+    /// a + 0 = a       ∀ a ∈ Self
+    /// 0 + a = a       ∀ a ∈ Self
+    /// ~~~
+    ///
+    /// # Purity
+    ///
+    /// This function should return the same result at all times regardless of
+    /// external mutable state, for example values stored in TLS or in
+    /// `static mut`s.
+    // FIXME (#5527): This should be an associated constant
+    fn zero() -> Self;
+
+    /// Returns `true` if `self` is equal to the additive identity.
     fn is_zero(&self) -> bool;
 }
 
-/// Returns `0` of appropriate type.
+/// Returns the additive identity, `0`.
 #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
 
-pub trait One {
-    fn one() -> Self;       // FIXME (#5527): This should be an associated constant
+/// Defines a multiplicative identity element for `Self`.
+pub trait One: Mul<Self, Self> {
+    /// Returns the multiplicative identity element of `Self`, `1`.
+    ///
+    /// # Laws
+    ///
+    /// ~~~
+    /// a * 1 = a       ∀ a ∈ Self
+    /// 1 * a = a       ∀ a ∈ Self
+    /// ~~~
+    ///
+    /// # Purity
+    ///
+    /// This function should return the same result at all times regardless of
+    /// external mutable state, for example values stored in TLS or in
+    /// `static mut`s.
+    // FIXME (#5527): This should be an associated constant
+    fn one() -> Self;
 }
 
-/// Returns `1` of appropriate type.
+/// Returns the multiplicative identity, `1`.
 #[inline(always)] pub fn one<T: One>() -> T { One::one() }
 
 pub trait Signed: Num
@@ -264,48 +304,29 @@ pub trait Real: Signed
     fn to_radians(&self) -> Self;
 }
 
-/// Raises a value to the power of exp, using
-/// exponentiation by squaring.
+/// Raises a value to the power of exp, using exponentiation by squaring.
 ///
 /// # Example
 ///
 /// ```rust
 /// use std::num;
 ///
-/// let sixteen = num::pow(2, 4u);
-/// assert_eq!(sixteen, 16);
+/// assert_eq!(num::pow(2, 4), 16);
 /// ```
 #[inline]
-pub fn pow<T: Clone+One+Mul<T, T>>(num: T, exp: uint) -> T {
-    let one: uint = One::one();
-    let num_one: T = One::one();
-
-    if exp.is_zero() { return num_one; }
-    if exp == one { return num.clone(); }
-
-    let mut i: uint = exp;
-    let mut v: T;
-    let mut r: T = num_one;
-
-    // This if is to avoid cloning self.
-    if (i & one) == one {
-        r = r * num;
-        i = i - one;
-    }
-
-    i = i >> one;
-    v = num * num;
-
-    while !i.is_zero() {
-        if (i & one) == one {
-            r = r * v;
-            i = i - one;
+pub fn pow<T: One + Mul<T, T>>(mut base: T, mut exp: uint) -> T {
+    if exp == 1 { base }
+    else {
+        let mut acc = one::<T>();
+        while exp > 0 {
+            if (exp & 1) == 1 {
+                acc = acc * base;
+            }
+            base = base * base;
+            exp = exp >> 1;
         }
-        i = i >> one;
-        v = v * v;
+        acc
     }
-
-    r
 }
 
 /// Raise a number to a power.
@@ -993,16 +1014,6 @@ pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
     FromStrRadix::from_str_radix(str, radix)
 }
 
-impl<T: Zero + 'static> Zero for @T {
-    fn zero() -> @T { @Zero::zero() }
-    fn is_zero(&self) -> bool { (**self).is_zero() }
-}
-
-impl<T: Zero> Zero for ~T {
-    fn zero() -> ~T { ~Zero::zero() }
-    fn is_zero(&self) -> bool { (**self).is_zero() }
-}
-
 /// Saturating math operations
 pub trait Saturating {
     /// Saturating addition operator.
@@ -1640,17 +1651,24 @@ mod tests {
 
     #[test]
     fn test_pow() {
-        fn assert_pow<T: Eq+Clone+One+Mul<T, T>>(num: T, exp: uint) -> () {
-            assert_eq!(num::pow(num.clone(), exp),
-                       range(1u, exp).fold(num.clone(), |acc, _| acc * num));
+        fn naive_pow<T: One + Mul<T, T>>(base: T, exp: uint) -> T {
+            range(0, exp).fold(one::<T>(), |acc, _| acc * base)
         }
-
-        assert_eq!(num::pow(3, 0), 1);
-        assert_eq!(num::pow(5, 1), 5);
-        assert_pow(-4, 2);
-        assert_pow(8, 3);
-        assert_pow(8, 5);
-        assert_pow(2u64, 50);
+        macro_rules! assert_pow(
+            (($num:expr, $exp:expr) => $expected:expr) => {{
+                let result = pow($num, $exp);
+                assert_eq!(result, $expected);
+                assert_eq!(result, naive_pow($num, $exp));
+            }}
+        )
+        assert_pow!((3,    0 ) => 1);
+        assert_pow!((5,    1 ) => 5);
+        assert_pow!((-4,   2 ) => 16);
+        assert_pow!((0.5,  5 ) => 0.03125);
+        assert_pow!((8,    3 ) => 512);
+        assert_pow!((8.0,  5 ) => 32768.0);
+        assert_pow!((8.5,  5 ) => 44370.53125);
+        assert_pow!((2u64, 50) => 1125899906842624);
     }
 }
 
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs
index 313fd9c79b4..8e278aeb2ea 100644
--- a/src/libstd/tuple.rs
+++ b/src/libstd/tuple.rs
@@ -15,7 +15,6 @@
 use clone::Clone;
 #[cfg(not(test))] use cmp::*;
 #[cfg(not(test))] use default::Default;
-#[cfg(not(test))] use num::Zero;
 
 /// Method extensions to pairs where both types satisfy the `Clone` bound
 pub trait CopyableTuple<T, U> {
@@ -177,18 +176,6 @@ macro_rules! tuple_impls {
                     ($({ let x: $T = Default::default(); x},)+)
                 }
             }
-
-            #[cfg(not(test))]
-            impl<$($T:Zero),+> Zero for ($($T,)+) {
-                #[inline]
-                fn zero() -> ($($T,)+) {
-                    ($({ let x: $T = Zero::zero(); x},)+)
-                }
-                #[inline]
-                fn is_zero(&self) -> bool {
-                    $(self.$get_ref_fn().is_zero())&&+
-                }
-            }
         )+
     }
 }
diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs
index c27f6e3d086..786a7f42bb3 100644
--- a/src/libstd/unit.rs
+++ b/src/libstd/unit.rs
@@ -12,8 +12,6 @@
 
 #[cfg(not(test))]
 use prelude::*;
-#[cfg(not(test))]
-use num::Zero;
 
 #[cfg(not(test))]
 impl Eq for () {
@@ -46,11 +44,3 @@ impl Default for () {
     #[inline]
     fn default() -> () { () }
 }
-
-#[cfg(not(test))]
-impl Zero for () {
-    #[inline]
-    fn zero() -> () { () }
-    #[inline]
-    fn is_zero(&self) -> bool { true }
-}
diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs
index d28e54d57ad..9ae72038aa9 100644
--- a/src/test/run-pass/deriving-zero.rs
+++ b/src/test/run-pass/deriving-zero.rs
@@ -10,32 +10,55 @@
 
 #[feature(managed_boxes)];
 
-use std::util;
 use std::num::Zero;
 
 #[deriving(Zero)]
-struct A;
-#[deriving(Zero)]
-struct B(int);
-#[deriving(Zero)]
-struct C(int, int);
-#[deriving(Zero)]
-struct D { a: int }
+struct Vector2<T>(T, T);
+
+impl<T: Add<T, T>> Add<Vector2<T>, Vector2<T>> for Vector2<T> {
+    fn add(&self, other: &Vector2<T>) -> Vector2<T> {
+        match (self, other) {
+            (&Vector2(ref x0, ref y0), &Vector2(ref x1, ref y1)) => {
+                Vector2(*x0 + *x1, *y0 + *y1)
+            }
+        }
+    }
+}
+
 #[deriving(Zero)]
-struct E { a: int, b: int }
+struct Vector3<T> {
+    x: T, y: T, z: T,
+}
+
+impl<T: Add<T, T>> Add<Vector3<T>, Vector3<T>> for Vector3<T> {
+    fn add(&self, other: &Vector3<T>) -> Vector3<T> {
+        Vector3 {
+            x: self.x + other.x,
+            y: self.y + other.y,
+            z: self.z + other.z,
+        }
+    }
+}
 
 #[deriving(Zero)]
-struct Lots {
-    d: u8,
-    e: char,
-    f: f64,
-    g: (f32, char),
-    h: @(int, int),
-    i: bool,
-    j: (),
+struct Matrix3x2<T> {
+    x: Vector2<T>,
+    y: Vector2<T>,
+    z: Vector2<T>,
+}
+
+impl<T: Add<T, T>> Add<Matrix3x2<T>, Matrix3x2<T>> for Matrix3x2<T> {
+    fn add(&self, other: &Matrix3x2<T>) -> Matrix3x2<T> {
+        Matrix3x2 {
+            x: self.x + other.x,
+            y: self.y + other.y,
+            z: self.z + other.z,
+        }
+    }
 }
 
 pub fn main() {
-    let lots: Lots = Zero::zero();
-    assert!(lots.is_zero());
+    let _: Vector2<int> = Zero::zero();
+    let _: Vector3<f64> = Zero::zero();
+    let _: Matrix3x2<u8> = Zero::zero();
 }
diff --git a/src/test/run-pass/issue-5554.rs b/src/test/run-pass/issue-5554.rs
index e4ef20a3b0f..25293c4dd1b 100644
--- a/src/test/run-pass/issue-5554.rs
+++ b/src/test/run-pass/issue-5554.rs
@@ -10,30 +10,25 @@
 
 #[feature(macro_rules)];
 
-use std::num::Zero;
+use std::default::Default;
 
 pub struct X<T> {
-  a: T
+    a: T,
 }
 
 // reordering these bounds stops the ICE
-impl<T: Zero + Eq + Zero>
-  Zero for X<T> {
-    fn zero() -> X<T> {
-      X { a: Zero::zero() }
-    }
-    fn is_zero(&self) -> bool {
-        self.a.is_zero()
+impl<T: Default + Eq + Default> Default for X<T> {
+    fn default() -> X<T> {
+        X { a: Default::default() }
     }
 }
 
 macro_rules! constants {
-  () => {
-    let _0 : X<int> = Zero::zero();
-   }
+    () => {
+        let _ : X<int> = Default::default();
+    }
 }
 
-
 pub fn main() {
-  constants!();
+    constants!();
 }