about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-02-10 10:04:46 +0000
committerbors <bors@rust-lang.org>2016-02-10 10:04:46 +0000
commit32d962d16fc0abcb63fd705b3cde35025da77a13 (patch)
tree83c11b86f064ec9855dc31811d8eb082b5e6f4d3
parent523fa1331eda875136d3a980a5d51c7706f23f30 (diff)
parentaeb3aba951bca3307a1cbb7d1882437091e8070b (diff)
downloadrust-32d962d16fc0abcb63fd705b3cde35025da77a13.tar.gz
rust-32d962d16fc0abcb63fd705b3cde35025da77a13.zip
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
```
-rw-r--r--src/libcollections/vec_deque.rs34
-rw-r--r--src/libcollectionstest/vec_deque.rs27
2 files changed, 60 insertions, 1 deletions
diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs
index f434053390e..f34fe2da7e8 100644
--- a/src/libcollections/vec_deque.rs
+++ b/src/libcollections/vec_deque.rs
@@ -1968,7 +1968,39 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialEq> PartialEq for VecDeque<A> {
     fn eq(&self, other: &VecDeque<A>) -> bool {
-        self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq(b))
+        if self.len() != other.len() {
+            return false;
+        }
+        let (sa, sb) = self.as_slices();
+        let (oa, ob) = other.as_slices();
+        if sa.len() == oa.len() {
+            sa == oa && sb == ob
+        } else if sa.len() < oa.len() {
+            // Always divisible in three sections, for example:
+            // self:  [a b c|d e f]
+            // other: [0 1 2 3|4 5]
+            // front = 3, mid = 1,
+            // [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5]
+            let front = sa.len();
+            let mid = oa.len() - front;
+
+            let (oa_front, oa_mid) = oa.split_at(front);
+            let (sb_mid, sb_back) = sb.split_at(mid);
+            debug_assert_eq!(sa.len(), oa_front.len());
+            debug_assert_eq!(sb_mid.len(), oa_mid.len());
+            debug_assert_eq!(sb_back.len(), ob.len());
+            sa == oa_front && sb_mid == oa_mid && sb_back == ob
+        } else {
+            let front = oa.len();
+            let mid = sa.len() - front;
+
+            let (sa_front, sa_mid) = sa.split_at(front);
+            let (ob_mid, ob_back) = ob.split_at(mid);
+            debug_assert_eq!(sa_front.len(), oa.len());
+            debug_assert_eq!(sa_mid.len(), ob_mid.len());
+            debug_assert_eq!(sb.len(), ob_back.len());
+            sa_front == oa && sa_mid == ob_mid && sb == ob_back
+        }
     }
 }
 
diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs
index a50886bfdf3..742205df8d7 100644
--- a/src/libcollectionstest/vec_deque.rs
+++ b/src/libcollectionstest/vec_deque.rs
@@ -625,6 +625,33 @@ fn test_hash_after_rotation() {
 }
 
 #[test]
+fn test_eq_after_rotation() {
+    // test that two deques are equal even if elements are laid out differently
+    let len = 28;
+    let mut ring: VecDeque<i32> = (0..len as i32).collect();
+    let mut shifted = ring.clone();
+    for _ in 0..10 {
+        // shift values 1 step to the right by pop, sub one, push
+        ring.pop_front();
+        for elt in &mut ring {
+            *elt -= 1;
+        }
+        ring.push_back(len - 1);
+    }
+
+    // try every shift
+    for _ in 0..shifted.capacity() {
+        shifted.pop_front();
+        for elt in &mut shifted {
+            *elt -= 1;
+        }
+        shifted.push_back(len - 1);
+        assert_eq!(shifted, ring);
+        assert_eq!(ring, shifted);
+    }
+}
+
+#[test]
 fn test_ord() {
     let x = VecDeque::new();
     let mut y = VecDeque::new();