@@ -234,7 +234,9 @@ pub trait PrimInt:
234
234
/// assert_eq!(n.reverse_bits(), m);
235
235
/// assert_eq!(0u32.reverse_bits(), 0);
236
236
/// ```
237
- fn reverse_bits ( self ) -> Self ;
237
+ fn reverse_bits ( self ) -> Self {
238
+ reverse_bits_fallback ( self )
239
+ }
238
240
239
241
/// Convert an integer from big endian to the target's endianness.
240
242
///
@@ -324,6 +326,39 @@ pub trait PrimInt:
324
326
fn pow ( self , exp : u32 ) -> Self ;
325
327
}
326
328
329
+ fn one_per_byte < P : PrimInt > ( ) -> P {
330
+ // i8, u8: return 0x01
331
+ // i16, u16: return 0x0101 = (0x01 << 8) | 0x01
332
+ // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101
333
+ // ...
334
+ let mut ret = P :: one ( ) ;
335
+ let mut shift = 8 ;
336
+ let mut b = ret. count_zeros ( ) >> 3 ;
337
+ while b != 0 {
338
+ ret = ( ret << shift) | ret;
339
+ shift <<= 1 ;
340
+ b >>= 1 ;
341
+ }
342
+ ret
343
+ }
344
+
345
+ fn reverse_bits_fallback < P : PrimInt > ( i : P ) -> P {
346
+ let rep_01: P = one_per_byte ( ) ;
347
+ let rep_03 = ( rep_01 << 1 ) | rep_01;
348
+ let rep_05 = ( rep_01 << 2 ) | rep_01;
349
+ let rep_0f = ( rep_03 << 2 ) | rep_03;
350
+ let rep_33 = ( rep_03 << 4 ) | rep_03;
351
+ let rep_55 = ( rep_05 << 4 ) | rep_05;
352
+
353
+ // code above only used to determine rep_0f, rep_33, rep_55;
354
+ // optimizer should be able to do it in compile time
355
+ let mut ret = i. swap_bytes ( ) ;
356
+ ret = ( ( ret & rep_0f) << 4 ) | ( ( ret >> 4 ) & rep_0f) ;
357
+ ret = ( ( ret & rep_33) << 2 ) | ( ( ret >> 2 ) & rep_33) ;
358
+ ret = ( ( ret & rep_55) << 1 ) | ( ( ret >> 1 ) & rep_55) ;
359
+ ret
360
+ }
361
+
327
362
macro_rules! prim_int_impl {
328
363
( $T: ty, $S: ty, $U: ty) => {
329
364
impl PrimInt for $T {
@@ -382,6 +417,7 @@ macro_rules! prim_int_impl {
382
417
<$T>:: swap_bytes( self )
383
418
}
384
419
420
+ #[ cfg( has_reverse_bits) ]
385
421
#[ inline]
386
422
fn reverse_bits( self ) -> Self {
387
423
<$T>:: reverse_bits( self )
0 commit comments