Browse Source

pow: avoid unnecessary overflows

The code was performing an extra squaring of the base, which might
trigger an arithmetic overflow that doesn't matter to the result.  Now
this squaring is only attempted when enough exp remains to need it.

A new doctest tries pow(6u8, 3), where an extra square would exceed 256.
Josh Stone 10 năm trước cách đây
mục cha
commit
043a5b2918
1 tập tin đã thay đổi với 7 bổ sung2 xóa
  1. 7 2
      src/lib.rs

+ 7 - 2
src/lib.rs

@@ -121,7 +121,8 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
 /// ```rust
 /// use num;
 ///
-/// assert_eq!(num::pow(2i, 4), 16);
+/// assert_eq!(num::pow(2i8, 4), 16);
+/// assert_eq!(num::pow(6u8, 3), 216);
 /// ```
 #[inline]
 pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
@@ -132,7 +133,11 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
             if (exp & 1) == 1 {
                 acc = acc * base.clone();
             }
-            base = base.clone() * base;
+
+            // avoid overflow if we won't need it
+            if exp > 1 {
+                base = base.clone() * base;
+            }
             exp = exp >> 1;
         }
         acc