about summary refs log tree commit diff
path: root/src/libcore/num
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-02-19 15:14:48 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-03-03 12:10:57 +0100
commitc8db89aa82573b89481fde598da6e54371f266cb (patch)
treebf3fda792aca94eeca3c413b64c0837a896bf448 /src/libcore/num
parent4394720dae12c119a9b1aed492b1b24ee089d808 (diff)
downloadrust-c8db89aa82573b89481fde598da6e54371f266cb.tar.gz
rust-c8db89aa82573b89481fde598da6e54371f266cb.zip
Accommodate arith-overflow in `core::num`, `std::num`, `coretest::num`.
 * `core::num`: adjust `UnsignedInt::is_power_of_two`,
   `UnsignedInt::next_power_of_two`, `Int::pow`.

   In particular for `Int::pow`: (1.) do not panic when `base`
   overflows if `acc` never observes the overflowed `base`, and (2.)
   if `acc` does observe the overflowed `base`, make sure we only
   panic if we would have otherwise (e.g. during a computation of
   `base * base`).

 * also in `core::num`: avoid underflow during computation of `uint::MAX`.

 * `std::num`: adjust tests `uint::test_uint_from_str_overflow`,
   `uint::test_uint_to_str_overflow`, `strconv`

 * `coretest::num`: adjust `test::test_int_from_str_overflow`.
Diffstat (limited to 'src/libcore/num')
-rw-r--r--src/libcore/num/mod.rs26
-rw-r--r--src/libcore/num/uint_macros.rs2
2 files changed, 22 insertions, 6 deletions
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 3ed059520b1..92cdd84160b 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -15,6 +15,8 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
+use self::wrapping::{OverflowingOps, WrappingOps};
+
 use char::CharExt;
 use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord};
@@ -51,6 +53,8 @@ pub trait Int
     + BitXor<Output=Self>
     + Shl<uint, Output=Self>
     + Shr<uint, Output=Self>
+    + WrappingOps
+    + OverflowingOps
 {
     /// Returns the `0` value of this integer type.
     // FIXME (#5527): Should be an associated constant
@@ -379,11 +383,23 @@ pub trait Int
         let mut base = self;
         let mut acc: Self = Int::one();
 
+        let mut prev_base = self;
+        let mut base_oflo = false;
         while exp > 0 {
             if (exp & 1) == 1 {
-                acc = acc * base;
+                if base_oflo {
+                    // ensure overflow occurs in the same manner it
+                    // would have otherwise (i.e. signal any exception
+                    // it would have otherwise).
+                    acc = acc * (prev_base * prev_base);
+                } else {
+                    acc = acc * base;
+                }
             }
-            base = base * base;
+            prev_base = base;
+            let (new_base, new_base_oflo) = base.overflowing_mul(base);
+            base = new_base;
+            base_oflo = new_base_oflo;
             exp /= 2;
         }
         acc
@@ -694,12 +710,12 @@ signed_int_impl! { int }
 
 /// A built-in unsigned integer.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait UnsignedInt: Int {
+pub trait UnsignedInt: Int + WrappingOps {
     /// Returns `true` iff `self == 2^k` for some `k`.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn is_power_of_two(self) -> bool {
-        (self - Int::one()) & self == Int::zero() && !(self == Int::zero())
+        (self.wrapping_sub(Int::one())) & self == Int::zero() && !(self == Int::zero())
     }
 
     /// Returns the smallest power of two greater than or equal to `self`.
@@ -709,7 +725,7 @@ pub trait UnsignedInt: Int {
     fn next_power_of_two(self) -> Self {
         let bits = size_of::<Self>() * 8;
         let one: Self = Int::one();
-        one << ((bits - (self - one).leading_zeros() as usize) % bits)
+        one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits)
     }
 
     /// Returns the smallest power of two greater than or equal to `n`. If the
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
index 330f0b91bf1..d0c4885ad00 100644
--- a/src/libcore/num/uint_macros.rs
+++ b/src/libcore/num/uint_macros.rs
@@ -20,6 +20,6 @@ pub const BYTES : u32 = ($bits / 8);
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: $T = 0 as $T;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub const MAX: $T = 0 as $T - 1 as $T;
+pub const MAX: $T = !0 as $T;
 
 ) }