Skip to content

Commit b2acfd2

Browse files
sozelfistvil02
andauthored
Improve bit manipulation algorithm implementations (#788)
* chore[clean_up]: improve bit manipulation algorithm implementations - Add docstring to file and function - Rewrite tests using macro * chore: update tests --------- Co-authored-by: Piotr Idzik <[email protected]>
1 parent 63c4430 commit b2acfd2

File tree

3 files changed

+100
-81
lines changed

3 files changed

+100
-81
lines changed

src/bit_manipulation/counting_bits.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
/*
2-
The counting bits algorithm, also known as the "population count" or "Hamming weight,"
3-
calculates the number of set bits (1s) in the binary representation of an unsigned integer.
4-
It uses a technique known as Brian Kernighan's algorithm, which efficiently clears the least
5-
significant set bit in each iteration.
6-
*/
7-
8-
pub fn count_set_bits(mut n: u32) -> u32 {
1+
//! This module implements a function to count the number of set bits (1s)
2+
//! in the binary representation of an unsigned integer.
3+
//! It uses Brian Kernighan's algorithm, which efficiently clears the least significant
4+
//! set bit in each iteration until all bits are cleared.
5+
//! The algorithm runs in O(k), where k is the number of set bits.
6+
7+
/// Counts the number of set bits in an unsigned integer.
8+
///
9+
/// # Arguments
10+
///
11+
/// * `n` - An unsigned 32-bit integer whose set bits will be counted.
12+
///
13+
/// # Returns
14+
///
15+
/// * `usize` - The number of set bits (1s) in the binary representation of the input number.
16+
pub fn count_set_bits(mut n: usize) -> usize {
917
// Initialize a variable to keep track of the count of set bits
1018
let mut count = 0;
1119
while n > 0 {
@@ -24,23 +32,23 @@ pub fn count_set_bits(mut n: u32) -> u32 {
2432
mod tests {
2533
use super::*;
2634

27-
#[test]
28-
fn test_count_set_bits_zero() {
29-
assert_eq!(count_set_bits(0), 0);
30-
}
31-
32-
#[test]
33-
fn test_count_set_bits_one() {
34-
assert_eq!(count_set_bits(1), 1);
35+
macro_rules! test_count_set_bits {
36+
($($name:ident: $test_case:expr,)*) => {
37+
$(
38+
#[test]
39+
fn $name() {
40+
let (input, expected) = $test_case;
41+
assert_eq!(count_set_bits(input), expected);
42+
}
43+
)*
44+
};
3545
}
36-
37-
#[test]
38-
fn test_count_set_bits_power_of_two() {
39-
assert_eq!(count_set_bits(16), 1); // 16 is 2^4, only one set bit
40-
}
41-
42-
#[test]
43-
fn test_count_set_bits_all_set_bits() {
44-
assert_eq!(count_set_bits(u32::MAX), 32); // Maximum value for u32, all set bits
46+
test_count_set_bits! {
47+
test_count_set_bits_zero: (0, 0),
48+
test_count_set_bits_one: (1, 1),
49+
test_count_set_bits_power_of_two: (16, 1),
50+
test_count_set_bits_all_set_bits: (usize::MAX, std::mem::size_of::<usize>() * 8),
51+
test_count_set_bits_alternating_bits: (0b10101010, 4),
52+
test_count_set_bits_mixed_bits: (0b11011011, 6),
4553
}
4654
}
Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
// Find Highest Set Bit in Rust
2-
// This code provides a function to calculate the position (or index) of the most significant bit set to 1 in a given integer.
3-
4-
// Define a function to find the highest set bit.
5-
pub fn find_highest_set_bit(num: i32) -> Option<i32> {
6-
if num < 0 {
7-
// Input cannot be negative.
8-
panic!("Input cannot be negative");
9-
}
10-
1+
//! This module provides a function to find the position of the most significant bit (MSB)
2+
//! set to 1 in a given positive integer.
3+
4+
/// Finds the position of the highest (most significant) set bit in a positive integer.
5+
///
6+
/// # Arguments
7+
///
8+
/// * `num` - An integer value for which the highest set bit will be determined.
9+
///
10+
/// # Returns
11+
///
12+
/// * Returns `Some(position)` if a set bit exists or `None` if no bit is set.
13+
pub fn find_highest_set_bit(num: usize) -> Option<usize> {
1114
if num == 0 {
12-
return None; // No bit is set, return None.
15+
return None;
1316
}
1417

1518
let mut position = 0;
@@ -27,22 +30,23 @@ pub fn find_highest_set_bit(num: i32) -> Option<i32> {
2730
mod tests {
2831
use super::*;
2932

30-
#[test]
31-
fn test_positive_number() {
32-
let num = 18;
33-
assert_eq!(find_highest_set_bit(num), Some(4));
34-
}
35-
36-
#[test]
37-
fn test_zero() {
38-
let num = 0;
39-
assert_eq!(find_highest_set_bit(num), None);
33+
macro_rules! test_find_highest_set_bit {
34+
($($name:ident: $test_case:expr,)*) => {
35+
$(
36+
#[test]
37+
fn $name() {
38+
let (input, expected) = $test_case;
39+
assert_eq!(find_highest_set_bit(input), expected);
40+
}
41+
)*
42+
};
4043
}
4144

42-
#[test]
43-
#[should_panic(expected = "Input cannot be negative")]
44-
fn test_negative_number() {
45-
let num = -12;
46-
find_highest_set_bit(num);
45+
test_find_highest_set_bit! {
46+
test_positive_number: (18, Some(4)),
47+
test_0: (0, None),
48+
test_1: (1, Some(0)),
49+
test_2: (2, Some(1)),
50+
test_3: (3, Some(1)),
4751
}
4852
}
Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
/**
2-
* This algorithm demonstrates how to add two integers without using the + operator
3-
* but instead relying on bitwise operations, like bitwise XOR and AND, to simulate
4-
* the addition. It leverages bit manipulation to compute the sum efficiently.
5-
*/
1+
//! This module provides a function to add two integers without using the `+` operator.
2+
//! It relies on bitwise operations (XOR and AND) to compute the sum, simulating the addition process.
63
7-
pub fn add_two_integers(a: i32, b: i32) -> i32 {
8-
let mut a = a;
9-
let mut b = b;
4+
/// Adds two integers using bitwise operations.
5+
///
6+
/// # Arguments
7+
///
8+
/// * `a` - The first integer to be added.
9+
/// * `b` - The second integer to be added.
10+
///
11+
/// # Returns
12+
///
13+
/// * `isize` - The result of adding the two integers.
14+
pub fn add_two_integers(mut a: isize, mut b: isize) -> isize {
1015
let mut carry;
11-
let mut sum;
1216

13-
// Iterate until there is no carry left
1417
while b != 0 {
15-
sum = a ^ b; // XOR operation to find the sum without carry
16-
carry = (a & b) << 1; // AND operation to find the carry, shifted left by 1
18+
let sum = a ^ b;
19+
carry = (a & b) << 1;
1720
a = sum;
1821
b = carry;
1922
}
@@ -23,26 +26,30 @@ pub fn add_two_integers(a: i32, b: i32) -> i32 {
2326

2427
#[cfg(test)]
2528
mod tests {
26-
use super::add_two_integers;
29+
use super::*;
2730

28-
#[test]
29-
fn test_add_two_integers_positive() {
30-
assert_eq!(add_two_integers(3, 5), 8);
31-
assert_eq!(add_two_integers(100, 200), 300);
32-
assert_eq!(add_two_integers(65535, 1), 65536);
31+
macro_rules! test_add_two_integers {
32+
($($name:ident: $test_case:expr,)*) => {
33+
$(
34+
#[test]
35+
fn $name() {
36+
let (a, b) = $test_case;
37+
assert_eq!(add_two_integers(a, b), a + b);
38+
assert_eq!(add_two_integers(b, a), a + b);
39+
}
40+
)*
41+
};
3342
}
3443

35-
#[test]
36-
fn test_add_two_integers_negative() {
37-
assert_eq!(add_two_integers(-10, 6), -4);
38-
assert_eq!(add_two_integers(-50, -30), -80);
39-
assert_eq!(add_two_integers(-1, -1), -2);
40-
}
41-
42-
#[test]
43-
fn test_add_two_integers_zero() {
44-
assert_eq!(add_two_integers(0, 0), 0);
45-
assert_eq!(add_two_integers(0, 42), 42);
46-
assert_eq!(add_two_integers(0, -42), -42);
44+
test_add_two_integers! {
45+
test_add_two_integers_positive: (3, 5),
46+
test_add_two_integers_large_positive: (100, 200),
47+
test_add_two_integers_edge_positive: (65535, 1),
48+
test_add_two_integers_negative: (-10, 6),
49+
test_add_two_integers_both_negative: (-50, -30),
50+
test_add_two_integers_edge_negative: (-1, -1),
51+
test_add_two_integers_zero: (0, 0),
52+
test_add_two_integers_zero_with_positive: (0, 42),
53+
test_add_two_integers_zero_with_negative: (0, -42),
4754
}
4855
}

0 commit comments

Comments
 (0)