Skip to content

Commit 92b8f48

Browse files
Merge #175
175: added BigUint::count_ones(), trailing_ones() r=cuviper a=BartMassey Added `BigUint::count_ones()`, `BigUint::trailing_ones()`. Also minimal tests for these and `BigUint::trailing_zeros()`. Closes Issue #174 Co-authored-by: Bart Massey <[email protected]>
2 parents 38d6973 + 7a1814f commit 92b8f48

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/biguint.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,24 @@ impl BigUint {
26892689
let zeros: u64 = self.data[i].trailing_zeros().into();
26902690
Some(i as u64 * u64::from(big_digit::BITS) + zeros)
26912691
}
2692+
2693+
/// Returns the number of least-significant bits that are ones.
2694+
pub fn trailing_ones(&self) -> u64 {
2695+
if let Some(i) = self.data.iter().position(|&digit| !digit != 0) {
2696+
// XXX u64::trailing_ones() introduced in Rust 1.46,
2697+
// but we need to be compatible further back.
2698+
// Thanks to cuviper for this workaround.
2699+
let ones: u64 = (!self.data[i]).trailing_zeros().into();
2700+
i as u64 * u64::from(big_digit::BITS) + ones
2701+
} else {
2702+
self.data.len() as u64 * u64::from(big_digit::BITS)
2703+
}
2704+
}
2705+
2706+
/// Returns the number of one bits.
2707+
pub fn count_ones(&self) -> u64 {
2708+
self.data.iter().map(|&d| u64::from(d.count_ones())).sum()
2709+
}
26922710
}
26932711

26942712
fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> BigUint {

tests/biguint.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,3 +1775,34 @@ fn test_pow() {
17751775
check!(u128);
17761776
check!(usize);
17771777
}
1778+
1779+
#[test]
1780+
fn test_trailing_zeros() {
1781+
assert!(BigUint::from(0u8).trailing_zeros().is_none());
1782+
assert_eq!(BigUint::from(1u8).trailing_zeros().unwrap(), 0);
1783+
assert_eq!(BigUint::from(2u8).trailing_zeros().unwrap(), 1);
1784+
let x: BigUint = BigUint::one() << 128;
1785+
assert_eq!(x.trailing_zeros().unwrap(), 128);
1786+
}
1787+
1788+
#[test]
1789+
fn test_trailing_ones() {
1790+
assert_eq!(BigUint::from(0u8).trailing_ones(), 0);
1791+
assert_eq!(BigUint::from(1u8).trailing_ones(), 1);
1792+
assert_eq!(BigUint::from(2u8).trailing_ones(), 0);
1793+
assert_eq!(BigUint::from(3u8).trailing_ones(), 2);
1794+
let x: BigUint = (BigUint::from(3u8) << 128) | BigUint::from(3u8);
1795+
assert_eq!(x.trailing_ones(), 2);
1796+
let x: BigUint = (BigUint::one() << 128) - BigUint::one();
1797+
assert_eq!(x.trailing_ones(), 128);
1798+
}
1799+
1800+
#[test]
1801+
fn test_count_ones() {
1802+
assert_eq!(BigUint::from(0u8).count_ones(), 0);
1803+
assert_eq!(BigUint::from(1u8).count_ones(), 1);
1804+
assert_eq!(BigUint::from(2u8).count_ones(), 1);
1805+
assert_eq!(BigUint::from(3u8).count_ones(), 2);
1806+
let x: BigUint = (BigUint::from(3u8) << 128) | BigUint::from(3u8);
1807+
assert_eq!(x.count_ones(), 4);
1808+
}

0 commit comments

Comments
 (0)