@@ -34,27 +34,77 @@ impl<Tuple: Ord> Relation<Tuple> {
34
34
let mut elements1 = self . elements ;
35
35
let mut elements2 = other. elements ;
36
36
37
- // Ensure elements1.cap() >= elements2.cap().
38
- if elements1. capacity ( ) < elements2. capacity ( ) {
39
- :: std:: mem:: swap ( & mut elements1, & mut elements2) ;
37
+ // If one of the element lists is zero-length, we don't need to do any work
38
+ if elements1. len ( ) == 0 {
39
+ return Relation { elements : elements2 } ;
40
+ }
41
+ if elements2. len ( ) == 0 {
42
+ return Relation { elements : elements1 } ;
43
+ }
44
+
45
+ // Make sure that elements1 starts with the lower element
46
+ // Will not panic since both collections must have at least 1 element at this point
47
+ if elements1[ 0 ] > elements2[ 0 ] {
48
+ std:: mem:: swap ( & mut elements1, & mut elements2) ;
40
49
}
41
50
42
- // Merge results either in spare capacity or new vector.
43
- let mut elements =
44
- if elements1. len ( ) + elements2. len ( ) < elements1. capacity ( ) {
51
+ // Fast path for when all the new elements are after the exiting ones
52
+ if elements1[ elements1. len ( ) - 1 ] < elements2[ 0 ] {
45
53
elements1. extend ( elements2. into_iter ( ) ) ;
46
- elements1
54
+ // println!("fast path");
55
+ return Relation { elements : elements1 } ;
47
56
}
48
- else {
49
- let mut vec = Vec :: with_capacity ( elements1. len ( ) + elements2. len ( ) ) ;
50
- vec. extend ( elements1. into_iter ( ) ) ;
51
- vec. extend ( elements2. into_iter ( ) ) ;
52
- vec
53
- } ;
54
-
55
- // Sort, dedup, and return.
56
- elements. sort ( ) ;
57
- elements. dedup ( ) ;
57
+
58
+ let mut elements = Vec :: with_capacity ( elements1. len ( ) + elements2. len ( ) ) ;
59
+ let mut elements1 = elements1. drain ( ..) ;
60
+ let mut elements2 = elements2. drain ( ..) . peekable ( ) ;
61
+ // let mut from_1 = 0;
62
+ // let mut from_2 = 0;
63
+
64
+ elements. push ( elements1. next ( ) . unwrap ( ) ) ;
65
+ // from_1 += 1;
66
+
67
+ for elem in elements1 {
68
+ loop {
69
+ // Pull everything out of elements2 that is less than the thing
70
+ // we're about to insert into elements from elements1
71
+ use std:: cmp:: Ordering ;
72
+ let cmpres = match elements2. peek ( ) {
73
+ None => Ordering :: Greater ,
74
+ Some ( e2) => e2. cmp ( & elem)
75
+ } ;
76
+
77
+ match cmpres {
78
+ Ordering :: Greater => break ,
79
+ Ordering :: Equal => {
80
+ // consume without pushing
81
+ elements2. next ( ) ;
82
+ } ,
83
+ Ordering :: Less => {
84
+ let tp = elements2. next ( ) . unwrap ( ) ;
85
+ if elements[ elements. len ( ) - 1 ] == tp {
86
+ // Don't push duplicates
87
+ continue ;
88
+ }
89
+ elements. push ( tp) ;
90
+ }
91
+ }
92
+ }
93
+ if elements[ elements. len ( ) - 1 ] == elem {
94
+ // Don't push duplicates
95
+ continue ;
96
+ }
97
+ elements. push ( elem) ;
98
+ }
99
+ // Finish draining second list
100
+ for elem in elements2 {
101
+ if elements[ elements. len ( ) - 1 ] == elem {
102
+ continue ;
103
+ }
104
+ // from_2 += 1;
105
+ elements. push ( elem) ;
106
+ }
107
+
58
108
Relation { elements }
59
109
}
60
110
0 commit comments