소스 검색

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 년 전
부모
커밋
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