Просмотр исходного кода

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 лет назад
Родитель
Сommit
043a5b2918
1 измененных файлов с 7 добавлено и 2 удалено
  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