about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-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
6 files changed, 82 insertions, 98 deletions
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 }
-}