Skip to content

Commit 32d962d

Browse files
committed
Auto merge of #31420 - bluss:deque-equality, r=Gankro
collections: Use slice parts in PartialEq for VecDeque This improves == for VecDeque by using the slice representation. This will also improve further if codegen for slice comparison improves. Benchmark run of 1000 u64 elements, comparing for equality (all equal). Cpu time to compare the vecdeques is reduced to less than 50% of what it was before. ``` test test_eq_u64 ... bench: 1,885 ns/iter (+/- 163) = 4244 MB/s test test_eq_new_u64 ... bench: 802 ns/iter (+/- 100) = 9975 MB/s ```
2 parents 523fa13 + aeb3aba commit 32d962d

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/libcollections/vec_deque.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -1968,7 +1968,39 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
19681968
#[stable(feature = "rust1", since = "1.0.0")]
19691969
impl<A: PartialEq> PartialEq for VecDeque<A> {
19701970
fn eq(&self, other: &VecDeque<A>) -> bool {
1971-
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq(b))
1971+
if self.len() != other.len() {
1972+
return false;
1973+
}
1974+
let (sa, sb) = self.as_slices();
1975+
let (oa, ob) = other.as_slices();
1976+
if sa.len() == oa.len() {
1977+
sa == oa && sb == ob
1978+
} else if sa.len() < oa.len() {
1979+
// Always divisible in three sections, for example:
1980+
// self: [a b c|d e f]
1981+
// other: [0 1 2 3|4 5]
1982+
// front = 3, mid = 1,
1983+
// [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5]
1984+
let front = sa.len();
1985+
let mid = oa.len() - front;
1986+
1987+
let (oa_front, oa_mid) = oa.split_at(front);
1988+
let (sb_mid, sb_back) = sb.split_at(mid);
1989+
debug_assert_eq!(sa.len(), oa_front.len());
1990+
debug_assert_eq!(sb_mid.len(), oa_mid.len());
1991+
debug_assert_eq!(sb_back.len(), ob.len());
1992+
sa == oa_front && sb_mid == oa_mid && sb_back == ob
1993+
} else {
1994+
let front = oa.len();
1995+
let mid = sa.len() - front;
1996+
1997+
let (sa_front, sa_mid) = sa.split_at(front);
1998+
let (ob_mid, ob_back) = ob.split_at(mid);
1999+
debug_assert_eq!(sa_front.len(), oa.len());
2000+
debug_assert_eq!(sa_mid.len(), ob_mid.len());
2001+
debug_assert_eq!(sb.len(), ob_back.len());
2002+
sa_front == oa && sa_mid == ob_mid && sb == ob_back
2003+
}
19722004
}
19732005
}
19742006

src/libcollectionstest/vec_deque.rs

+27
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,33 @@ fn test_hash_after_rotation() {
624624
}
625625
}
626626

627+
#[test]
628+
fn test_eq_after_rotation() {
629+
// test that two deques are equal even if elements are laid out differently
630+
let len = 28;
631+
let mut ring: VecDeque<i32> = (0..len as i32).collect();
632+
let mut shifted = ring.clone();
633+
for _ in 0..10 {
634+
// shift values 1 step to the right by pop, sub one, push
635+
ring.pop_front();
636+
for elt in &mut ring {
637+
*elt -= 1;
638+
}
639+
ring.push_back(len - 1);
640+
}
641+
642+
// try every shift
643+
for _ in 0..shifted.capacity() {
644+
shifted.pop_front();
645+
for elt in &mut shifted {
646+
*elt -= 1;
647+
}
648+
shifted.push_back(len - 1);
649+
assert_eq!(shifted, ring);
650+
assert_eq!(ring, shifted);
651+
}
652+
}
653+
627654
#[test]
628655
fn test_ord() {
629656
let x = VecDeque::new();

0 commit comments

Comments
 (0)