Skip to content

Commit d073745

Browse files
committed
Add BitCount trait
1 parent 4c07f5e commit d073745

File tree

15 files changed

+287
-16
lines changed

15 files changed

+287
-16
lines changed

src/libcore/core.rc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub use iter::{ExtendedMutableIter};
106106
pub use num::{Num, NumCast};
107107
pub use num::{Signed, Unsigned, Integer};
108108
pub use num::{Round, Fractional, Real, RealExt};
109-
pub use num::{Bitwise, Bounded};
109+
pub use num::{Bitwise, BitCount, Bounded};
110110
pub use num::{Primitive, PrimitiveInt};
111111
pub use num::{Int, Uint, Float};
112112
pub use ptr::Ptr;

src/libcore/num/int-template.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ mod tests {
646646
}
647647
648648
#[test]
649-
fn test_bitwise_ops() {
649+
fn test_bitwise() {
650650
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
651651
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
652652
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
@@ -655,6 +655,11 @@ mod tests {
655655
assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not());
656656
}
657657
658+
#[test]
659+
fn test_bitcount() {
660+
assert_eq!((0b010101 as T).population_count(), 3);
661+
}
662+
658663
#[test]
659664
fn test_primitive() {
660665
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);

src/libcore/num/int-template/i16.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `i16`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = i16;
1718
pub static bits: uint = ::u16::bits;
@@ -23,4 +24,18 @@ mod inst {
2324
#[inline(always)]
2425
fn bytes() -> uint { Primitive::bits::<i16>() / 8 }
2526
}
27+
28+
impl BitCount for i16 {
29+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
30+
#[inline(always)]
31+
fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
32+
33+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
34+
#[inline(always)]
35+
fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
36+
37+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
38+
#[inline(always)]
39+
fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
40+
}
2641
}

src/libcore/num/int-template/i32.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `i32`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = i32;
1718
pub static bits: uint = ::u32::bits;
@@ -23,4 +24,18 @@ mod inst {
2324
#[inline(always)]
2425
fn bytes() -> uint { Primitive::bits::<i32>() / 8 }
2526
}
27+
28+
impl BitCount for i32 {
29+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
30+
#[inline(always)]
31+
fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
32+
33+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
34+
#[inline(always)]
35+
fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
36+
37+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
38+
#[inline(always)]
39+
fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
40+
}
2641
}

src/libcore/num/int-template/i64.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `i64`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = i64;
1718
pub static bits: uint = ::u64::bits;
@@ -23,4 +24,18 @@ mod inst {
2324
#[inline(always)]
2425
fn bytes() -> uint { Primitive::bits::<i64>() / 8 }
2526
}
27+
28+
impl BitCount for i64 {
29+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
30+
#[inline(always)]
31+
fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
32+
33+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
34+
#[inline(always)]
35+
fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
36+
37+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
38+
#[inline(always)]
39+
fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
40+
}
2641
}

src/libcore/num/int-template/i8.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `i8`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = i8;
1718
pub static bits: uint = ::u8::bits;
@@ -23,4 +24,18 @@ mod inst {
2324
#[inline(always)]
2425
fn bytes() -> uint { Primitive::bits::<i8>() / 8 }
2526
}
27+
28+
impl BitCount for i8 {
29+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
30+
#[inline(always)]
31+
fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
32+
33+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
34+
#[inline(always)]
35+
fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
36+
37+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
38+
#[inline(always)]
39+
fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
40+
}
2641
}

src/libcore/num/int-template/int.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
pub use self::inst::pow;
1414

1515
mod inst {
16-
use num::Primitive;
16+
use num::{Primitive, BitCount};
1717

1818
pub type T = int;
1919
pub static bits: uint = ::uint::bits;
@@ -31,12 +31,79 @@ mod inst {
3131
#[cfg(not(target_word_size = "32"),
3232
not(target_word_size = "64"))]
3333
#[inline(always)]
34-
fn bits() -> uint { sys::size_of::<int>() * 8 }
34+
fn bits() -> uint { ::sys::size_of::<int>() * 8 }
3535

3636
#[inline(always)]
3737
fn bytes() -> uint { Primitive::bits::<int>() / 8 }
3838
}
3939

40+
#[cfg(target_word_size = "32")]
41+
#[inline(always)]
42+
impl BitCount for int {
43+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
44+
#[inline(always)]
45+
fn population_count(&self) -> int { (*self as i32).population_count() as uint }
46+
47+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
48+
#[inline(always)]
49+
fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as uint }
50+
51+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
52+
#[inline(always)]
53+
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as uint }
54+
}
55+
56+
#[cfg(target_word_size = "64")]
57+
#[inline(always)]
58+
impl BitCount for int {
59+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
60+
#[inline(always)]
61+
fn population_count(&self) -> int { (*self as i64).population_count() as int }
62+
63+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
64+
#[inline(always)]
65+
fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
66+
67+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
68+
#[inline(always)]
69+
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
70+
}
71+
72+
// fallback if we don't have access to the current word size
73+
#[cfg(not(target_word_size = "32"),
74+
not(target_word_size = "64"))]
75+
impl BitCount for int {
76+
/// Counts the number of bits set.
77+
#[inline(always)]
78+
fn population_count(&self) -> int {
79+
match ::sys::size_of::<int>() {
80+
8 => (*self as i64).population_count() as int,
81+
4 => (*self as i32).population_count() as int,
82+
s => fail!(fmt!("unsupported word size: %?", s)),
83+
}
84+
}
85+
86+
/// Counts the number of leading zeros.
87+
#[inline(always)]
88+
fn leading_zeros(&self) -> int {
89+
match ::sys::size_of::<int>() {
90+
8 => (*self as i64).leading_zeros() as int,
91+
4 => (*self as i32).leading_zeros() as int,
92+
s => fail!(fmt!("unsupported word size: %?", s)),
93+
}
94+
}
95+
96+
/// Counts the number of trailing zeros.
97+
#[inline(always)]
98+
fn trailing_zeros(&self) -> int {
99+
match ::sys::size_of::<int>() {
100+
8 => (*self as i64).trailing_zeros() as int,
101+
4 => (*self as i32).trailing_zeros() as int,
102+
s => fail!(fmt!("unsupported word size: %?", s)),
103+
}
104+
}
105+
}
106+
40107
/// Returns `base` raised to the power of `exponent`
41108
pub fn pow(base: int, exponent: uint) -> int {
42109
if exponent == 0u {

src/libcore/num/num.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ pub trait Bitwise: Not<Self>
184184
+ Shl<Self,Self>
185185
+ Shr<Self,Self> {}
186186

187+
pub trait BitCount {
188+
fn population_count(&self) -> Self;
189+
fn leading_zeros(&self) -> Self;
190+
fn trailing_zeros(&self) -> Self;
191+
}
192+
187193
pub trait Bounded {
188194
// FIXME (#5527): These should be associated constants
189195
fn min_value() -> Self;
@@ -214,7 +220,8 @@ pub trait Primitive: Num
214220
pub trait PrimitiveInt: Integer
215221
+ Primitive
216222
+ Bounded
217-
+ Bitwise {}
223+
+ Bitwise
224+
+ BitCount {}
218225

219226
///
220227
/// Specialisation of `PrimitiveInt` for unsigned integers

src/libcore/num/uint-template.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ mod tests {
389389
}
390390
391391
#[test]
392-
fn test_bitwise_ops() {
392+
fn test_bitwise() {
393393
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
394394
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
395395
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
@@ -398,6 +398,11 @@ mod tests {
398398
assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
399399
}
400400
401+
#[test]
402+
fn test_bitcount() {
403+
assert_eq!((0b010101 as T).population_count(), 3);
404+
}
405+
401406
#[test]
402407
fn test_primitive() {
403408
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);

src/libcore/num/uint-template/u16.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `u16`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = u16;
1718
#[allow(non_camel_case_types)]
@@ -25,4 +26,18 @@ mod inst {
2526
#[inline(always)]
2627
fn bytes() -> uint { Primitive::bits::<u16>() / 8 }
2728
}
29+
30+
impl BitCount for u16 {
31+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
32+
#[inline(always)]
33+
fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } }
34+
35+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
36+
#[inline(always)]
37+
fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } }
38+
39+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
40+
#[inline(always)]
41+
fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } }
42+
}
2843
}

src/libcore/num/uint-template/u32.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `u32`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = u32;
1718
#[allow(non_camel_case_types)]
@@ -25,4 +26,18 @@ mod inst {
2526
#[inline(always)]
2627
fn bytes() -> uint { Primitive::bits::<u32>() / 8 }
2728
}
29+
30+
impl BitCount for u32 {
31+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
32+
#[inline(always)]
33+
fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } }
34+
35+
/// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic.
36+
#[inline(always)]
37+
fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } }
38+
39+
/// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic.
40+
#[inline(always)]
41+
fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } }
42+
}
2843
}

src/libcore/num/uint-template/u64.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `u64`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = u64;
1718
#[allow(non_camel_case_types)]
@@ -25,4 +26,18 @@ mod inst {
2526
#[inline(always)]
2627
fn bytes() -> uint { Primitive::bits::<u64>() / 8 }
2728
}
29+
30+
impl BitCount for u64 {
31+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
32+
#[inline(always)]
33+
fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } }
34+
35+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
36+
#[inline(always)]
37+
fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } }
38+
39+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
40+
#[inline(always)]
41+
fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } }
42+
}
2843
}

src/libcore/num/uint-template/u8.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Operations and constants for `u8`
1212
1313
mod inst {
14-
use num::Primitive;
14+
use num::{Primitive, BitCount};
15+
use unstable::intrinsics;
1516

1617
pub type T = u8;
1718
#[allow(non_camel_case_types)]
@@ -25,4 +26,18 @@ mod inst {
2526
#[inline(always)]
2627
fn bytes() -> uint { Primitive::bits::<u8>() / 8 }
2728
}
29+
30+
impl BitCount for u8 {
31+
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
32+
#[inline(always)]
33+
fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } }
34+
35+
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
36+
#[inline(always)]
37+
fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } }
38+
39+
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
40+
#[inline(always)]
41+
fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } }
42+
}
2843
}

0 commit comments

Comments
 (0)