Skip to content

Commit f09cfcc

Browse files
authored
Optimized Clone::clone_from implementation (#127)
1 parent ca4dd26 commit f09cfcc

3 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/block/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#![allow(clippy::undocumented_unsafe_blocks)]
22
#![allow(dead_code)]
3+
// TODO: Remove once the transmutes are fixed
4+
#![allow(unknown_lints)]
5+
#![allow(clippy::missing_transmute_annotations)]
36

47
use core::cmp::Ordering;
58
use core::hash::{Hash, Hasher};
@@ -66,7 +69,7 @@ pub use self::wasm::*;
6669
impl Block {
6770
pub const USIZE_COUNT: usize = core::mem::size_of::<Self>() / core::mem::size_of::<usize>();
6871
pub const NONE: Self = Self::from_usize_array([0; Self::USIZE_COUNT]);
69-
pub const ALL: Self = Self::from_usize_array([core::usize::MAX; Self::USIZE_COUNT]);
72+
pub const ALL: Self = Self::from_usize_array([usize::MAX; Self::USIZE_COUNT]);
7073
pub const BITS: usize = core::mem::size_of::<Self>() * 8;
7174

7275
#[inline]

src/lib.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ impl Hash for FixedBitSet {
990990

991991
impl PartialEq for FixedBitSet {
992992
fn eq(&self, other: &Self) -> bool {
993-
self.as_simd_slice().eq(other.as_simd_slice()) && self.length == other.length
993+
self.length == other.length && self.as_simd_slice().eq(other.as_simd_slice())
994994
}
995995
}
996996

@@ -1201,9 +1201,9 @@ impl Masks {
12011201

12021202
Masks {
12031203
first_block,
1204-
first_mask: usize::max_value() << first_rem,
1204+
first_mask: usize::MAX << first_rem,
12051205
last_block,
1206-
last_mask: (usize::max_value() >> 1) >> (BITS - last_rem - 1),
1206+
last_mask: (usize::MAX >> 1) >> (BITS - last_rem - 1),
12071207
// this is equivalent to `MAX >> (BITS - x)` with correct semantics when x == 0.
12081208
}
12091209
}
@@ -1406,6 +1406,31 @@ impl Clone for FixedBitSet {
14061406
fn clone(&self) -> Self {
14071407
Self::from_blocks_and_len(Vec::from(self.as_simd_slice()), self.length)
14081408
}
1409+
1410+
#[inline]
1411+
fn clone_from(&mut self, source: &Self) {
1412+
{
1413+
let me = self.as_mut_simd_slice();
1414+
let them = source.as_simd_slice();
1415+
match me.len().cmp(&them.len()) {
1416+
Ordering::Greater => {
1417+
let (head, tail) = me.split_at_mut(them.len());
1418+
head.copy_from_slice(them);
1419+
tail.fill(SimdBlock::NONE);
1420+
self.length = source.length;
1421+
return;
1422+
}
1423+
Ordering::Equal => {
1424+
me.copy_from_slice(them);
1425+
self.length = source.length;
1426+
return;
1427+
}
1428+
// Self is smaller than the source, this requires allocation.
1429+
Ordering::Less => {}
1430+
}
1431+
}
1432+
*self = source.clone();
1433+
}
14091434
}
14101435

14111436
/// Return **true** if the bit is enabled in the bitset,

tests/tests.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,3 +1284,30 @@ fn test_is_full() {
12841284
fb.insert_range(..);
12851285
assert!(fb.is_full());
12861286
}
1287+
1288+
#[test]
1289+
fn clone() {
1290+
let mut fb = FixedBitSet::with_capacity(10000);
1291+
fb.set(11, true);
1292+
fb.set(12, true);
1293+
fb.set(7, true);
1294+
fb.set(35, true);
1295+
fb.set(40, true);
1296+
fb.set(77, true);
1297+
fb.set(95, true);
1298+
fb.set(50, true);
1299+
fb.set(99, true);
1300+
1301+
let fb_clone = fb.clone();
1302+
let mut fb_clone_from_smaller = FixedBitSet::with_capacity(1000000);
1303+
let mut fb_clone_from_same = FixedBitSet::with_capacity(10000);
1304+
let mut fb_clone_from_bigger = FixedBitSet::with_capacity(100);
1305+
fb_clone_from_smaller.clone_from(&fb);
1306+
fb_clone_from_same.clone_from(&fb);
1307+
fb_clone_from_bigger.clone_from(&fb);
1308+
1309+
assert_eq!(&fb, &fb_clone);
1310+
assert_eq!(&fb, &fb_clone_from_smaller);
1311+
assert_eq!(&fb, &fb_clone_from_same);
1312+
assert_eq!(&fb, &fb_clone_from_bigger);
1313+
}

0 commit comments

Comments
 (0)