@@ -304,48 +304,29 @@ pub trait Real: Signed
304
304
fn to_radians ( & self ) -> Self ;
305
305
}
306
306
307
- /// Raises a value to the power of exp, using
308
- /// exponentiation by squaring.
307
+ /// Raises a value to the power of exp, using exponentiation by squaring.
309
308
///
310
309
/// # Example
311
310
///
312
311
/// ```rust
313
312
/// use std::num;
314
313
///
315
- /// let sixteen = num::pow(2, 4u);
316
- /// assert_eq!(sixteen, 16);
314
+ /// assert_eq!(num::pow(2, 4), 16);
317
315
/// ```
318
316
#[ inline]
319
- pub fn pow < T : Clone +One +Mul < T , T > > ( num : T , exp : uint ) -> T {
320
- let one: uint = One :: one ( ) ;
321
- let num_one: T = One :: one ( ) ;
322
-
323
- if exp. is_zero ( ) { return num_one; }
324
- if exp == one { return num. clone ( ) ; }
325
-
326
- let mut i: uint = exp;
327
- let mut v: T ;
328
- let mut r: T = num_one;
329
-
330
- // This if is to avoid cloning self.
331
- if ( i & one) == one {
332
- r = r * num;
333
- i = i - one;
334
- }
335
-
336
- i = i >> one;
337
- v = num * num;
338
-
339
- while !i. is_zero ( ) {
340
- if ( i & one) == one {
341
- r = r * v;
342
- i = i - one;
317
+ pub fn pow < T : One + Mul < T , T > > ( mut base : T , mut exp : uint ) -> T {
318
+ if exp == 1 { base }
319
+ else {
320
+ let mut acc = one :: < T > ( ) ;
321
+ while exp > 0 {
322
+ if ( exp & 1 ) == 1 {
323
+ acc = acc * base;
324
+ }
325
+ base = base * base;
326
+ exp = exp >> 1 ;
343
327
}
344
- i = i >> one;
345
- v = v * v;
328
+ acc
346
329
}
347
-
348
- r
349
330
}
350
331
351
332
/// Raise a number to a power.
@@ -1670,17 +1651,24 @@ mod tests {
1670
1651
1671
1652
#[ test]
1672
1653
fn test_pow ( ) {
1673
- fn assert_pow < T : Eq +Clone +One +Mul < T , T > > ( num : T , exp : uint ) -> ( ) {
1674
- assert_eq ! ( num:: pow( num. clone( ) , exp) ,
1675
- range( 1 u, exp) . fold( num. clone( ) , |acc, _| acc * num) ) ;
1654
+ fn naive_pow < T : One + Mul < T , T > > ( base : T , exp : uint ) -> T {
1655
+ range ( 0 , exp) . fold ( one :: < T > ( ) , |acc, _| acc * base)
1676
1656
}
1677
-
1678
- assert_eq ! ( num:: pow( 3 , 0 ) , 1 ) ;
1679
- assert_eq ! ( num:: pow( 5 , 1 ) , 5 ) ;
1680
- assert_pow ( -4 , 2 ) ;
1681
- assert_pow ( 8 , 3 ) ;
1682
- assert_pow ( 8 , 5 ) ;
1683
- assert_pow ( 2u64 , 50 ) ;
1657
+ macro_rules! assert_pow(
1658
+ ( ( $num: expr, $exp: expr) => $expected: expr) => { {
1659
+ let result = pow( $num, $exp) ;
1660
+ assert_eq!( result, $expected) ;
1661
+ assert_eq!( result, naive_pow( $num, $exp) ) ;
1662
+ } }
1663
+ )
1664
+ assert_pow ! ( ( 3 , 0 ) => 1 ) ;
1665
+ assert_pow ! ( ( 5 , 1 ) => 5 ) ;
1666
+ assert_pow ! ( ( -4 , 2 ) => 16 ) ;
1667
+ assert_pow ! ( ( 0.5 , 5 ) => 0.03125 ) ;
1668
+ assert_pow ! ( ( 8 , 3 ) => 512 ) ;
1669
+ assert_pow ! ( ( 8.0 , 5 ) => 32768.0 ) ;
1670
+ assert_pow ! ( ( 8.5 , 5 ) => 44370.53125 ) ;
1671
+ assert_pow ! ( ( 2u64 , 50 ) => 1125899906842624 ) ;
1684
1672
}
1685
1673
}
1686
1674
0 commit comments