mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 02:33:55 +00:00
Add BitCount trait
This commit is contained in:
parent
4c07f5e457
commit
d0737451fc
@ -106,7 +106,7 @@ pub use iter::{ExtendedMutableIter};
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Round, Fractional, Real, RealExt};
|
||||
pub use num::{Bitwise, Bounded};
|
||||
pub use num::{Bitwise, BitCount, Bounded};
|
||||
pub use num::{Primitive, PrimitiveInt};
|
||||
pub use num::{Int, Uint, Float};
|
||||
pub use ptr::Ptr;
|
||||
|
@ -646,7 +646,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
fn test_bitwise() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
|
||||
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
|
||||
@ -655,6 +655,11 @@ mod tests {
|
||||
assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitcount() {
|
||||
assert_eq!((0b010101 as T).population_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `i16`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i16;
|
||||
pub static bits: uint = ::u16::bits;
|
||||
@ -23,4 +24,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i16>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i16 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `i32`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i32;
|
||||
pub static bits: uint = ::u32::bits;
|
||||
@ -23,4 +24,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i32>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i32 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `i64`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i64;
|
||||
pub static bits: uint = ::u64::bits;
|
||||
@ -23,4 +24,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i64>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i64 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `i8`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i8;
|
||||
pub static bits: uint = ::u8::bits;
|
||||
@ -23,4 +24,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i8>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i8 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
pub use self::inst::pow;
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
|
||||
pub type T = int;
|
||||
pub static bits: uint = ::uint::bits;
|
||||
@ -31,12 +31,79 @@ mod inst {
|
||||
#[cfg(not(target_word_size = "32"),
|
||||
not(target_word_size = "64"))]
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { sys::size_of::<int>() * 8 }
|
||||
fn bits() -> uint { ::sys::size_of::<int>() * 8 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<int>() / 8 }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
impl BitCount for int {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> int { (*self as i32).population_count() as uint }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as uint }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as uint }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
impl BitCount for int {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> int { (*self as i64).population_count() as int }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
|
||||
}
|
||||
|
||||
// fallback if we don't have access to the current word size
|
||||
#[cfg(not(target_word_size = "32"),
|
||||
not(target_word_size = "64"))]
|
||||
impl BitCount for int {
|
||||
/// Counts the number of bits set.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> int {
|
||||
match ::sys::size_of::<int>() {
|
||||
8 => (*self as i64).population_count() as int,
|
||||
4 => (*self as i32).population_count() as int,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts the number of leading zeros.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> int {
|
||||
match ::sys::size_of::<int>() {
|
||||
8 => (*self as i64).leading_zeros() as int,
|
||||
4 => (*self as i32).leading_zeros() as int,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts the number of trailing zeros.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> int {
|
||||
match ::sys::size_of::<int>() {
|
||||
8 => (*self as i64).trailing_zeros() as int,
|
||||
4 => (*self as i32).trailing_zeros() as int,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `base` raised to the power of `exponent`
|
||||
pub fn pow(base: int, exponent: uint) -> int {
|
||||
if exponent == 0u {
|
||||
|
@ -184,6 +184,12 @@ pub trait Bitwise: Not<Self>
|
||||
+ Shl<Self,Self>
|
||||
+ Shr<Self,Self> {}
|
||||
|
||||
pub trait BitCount {
|
||||
fn population_count(&self) -> Self;
|
||||
fn leading_zeros(&self) -> Self;
|
||||
fn trailing_zeros(&self) -> Self;
|
||||
}
|
||||
|
||||
pub trait Bounded {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn min_value() -> Self;
|
||||
@ -214,7 +220,8 @@ pub trait Primitive: Num
|
||||
pub trait PrimitiveInt: Integer
|
||||
+ Primitive
|
||||
+ Bounded
|
||||
+ Bitwise {}
|
||||
+ Bitwise
|
||||
+ BitCount {}
|
||||
|
||||
///
|
||||
/// Specialisation of `PrimitiveInt` for unsigned integers
|
||||
|
@ -389,7 +389,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
fn test_bitwise() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
|
||||
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
|
||||
@ -398,6 +398,11 @@ mod tests {
|
||||
assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitcount() {
|
||||
assert_eq!((0b010101 as T).population_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `u16`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u16;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -25,4 +26,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u16>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u16 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `u32`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u32;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -25,4 +26,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u32>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u32 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `u64`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u64;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -25,4 +26,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u64>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u64 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
//! Operations and constants for `u8`
|
||||
|
||||
mod inst {
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u8;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -25,4 +26,18 @@ mod inst {
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u8>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u8 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } }
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub use self::inst::{
|
||||
pub mod inst {
|
||||
use sys;
|
||||
use iter;
|
||||
use num::Primitive;
|
||||
use num::{Primitive, BitCount};
|
||||
|
||||
pub type T = uint;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -51,6 +51,73 @@ pub mod inst {
|
||||
fn bytes() -> uint { Primitive::bits::<uint>() / 8 }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
impl BitCount for uint {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> uint { (*self as i32).population_count() as uint }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> uint { (*self as i32).leading_zeros() as uint }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
impl BitCount for uint {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> uint { (*self as i64).population_count() as uint }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> uint { (*self as i64).leading_zeros() as uint }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint }
|
||||
}
|
||||
|
||||
// fallback if we don't have access to the current word size
|
||||
#[cfg(not(target_word_size = "32"),
|
||||
not(target_word_size = "64"))]
|
||||
impl BitCount for uint {
|
||||
/// Counts the number of bits set.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> uint {
|
||||
match sys::size_of::<uint>() {
|
||||
8 => (*self as i64).population_count() as uint,
|
||||
4 => (*self as i32).population_count() as uint,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts the number of leading zeros.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> uint {
|
||||
match sys::size_of::<uint>() {
|
||||
8 => (*self as i64).leading_zeros() as uint,
|
||||
4 => (*self as i32).leading_zeros() as uint,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts the number of trailing zeros.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> uint {
|
||||
match sys::size_of::<uint>() {
|
||||
8 => (*self as i64).trailing_zeros() as uint,
|
||||
4 => (*self as i32).trailing_zeros() as uint,
|
||||
s => fail!(fmt!("unsupported word size: %?", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Divide two numbers, return the result, rounded up.
|
||||
///
|
||||
|
@ -40,7 +40,7 @@ pub use iter::{Times, ExtendedMutableIter};
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Round, Fractional, Real, RealExt};
|
||||
pub use num::{Bitwise, Bounded};
|
||||
pub use num::{Bitwise, BitCount, Bounded};
|
||||
pub use num::{Primitive, PrimitiveInt};
|
||||
pub use num::{Int, Uint, Float};
|
||||
pub use path::GenericPath;
|
||||
|
Loading…
Reference in New Issue
Block a user