13
13
14
14
use std:: rc:: Rc ;
15
15
use std:: cell:: RefCell ;
16
+ use std:: cmp:: Ordering ;
16
17
17
18
mod map;
18
19
mod join;
@@ -34,27 +35,51 @@ impl<Tuple: Ord> Relation<Tuple> {
34
35
let mut elements1 = self . elements ;
35
36
let mut elements2 = other. elements ;
36
37
37
- // Ensure elements1.cap() >= elements2.cap().
38
- if elements1. capacity ( ) < elements2. capacity ( ) {
39
- :: std:: mem:: swap ( & mut elements1, & mut elements2) ;
38
+ // If one of the element lists is zero-length, we don't need to do any work
39
+ if elements1. len ( ) == 0 {
40
+ return Relation { elements : elements2 } ;
41
+ }
42
+ if elements2. len ( ) == 0 {
43
+ return Relation { elements : elements1 } ;
44
+ }
45
+
46
+ // Make sure that elements1 starts with the lower element
47
+ // Will not panic since both collections must have at least 1 element at this point
48
+ if elements1[ 0 ] > elements2[ 0 ] {
49
+ std:: mem:: swap ( & mut elements1, & mut elements2) ;
40
50
}
41
51
42
- // Merge results either in spare capacity or new vector.
43
- let mut elements =
44
- if elements1. len ( ) + elements2. len ( ) < elements1. capacity ( ) {
52
+ // Fast path for when all the new elements are after the exiting ones
53
+ if elements1[ elements1. len ( ) - 1 ] < elements2[ 0 ] {
45
54
elements1. extend ( elements2. into_iter ( ) ) ;
46
- elements1
55
+ // println!("fast path");
56
+ return Relation { elements : elements1 } ;
47
57
}
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 ( ) ;
58
+
59
+ let mut elements = Vec :: with_capacity ( elements1. len ( ) + elements2. len ( ) ) ;
60
+ let mut elements1 = elements1. drain ( ..) ;
61
+ let mut elements2 = elements2. drain ( ..) . peekable ( ) ;
62
+
63
+ elements. push ( elements1. next ( ) . unwrap ( ) ) ;
64
+ if & elements[ 0 ] == elements2. peek ( ) . unwrap ( ) {
65
+ elements2. next ( ) ;
66
+ }
67
+
68
+ for elem in elements1 {
69
+ while elements2. peek ( ) . map ( |x| x. cmp ( & elem) ) == Some ( Ordering :: Less ) {
70
+ elements. push ( elements2. next ( ) . unwrap ( ) ) ;
71
+ }
72
+ if elements2. peek ( ) . map ( |x| x. cmp ( & elem) ) == Some ( Ordering :: Equal ) {
73
+ elements2. next ( ) ;
74
+ }
75
+ elements. push ( elem) ;
76
+ }
77
+
78
+ // Finish draining second list
79
+ for elem in elements2 {
80
+ elements. push ( elem) ;
81
+ }
82
+
58
83
Relation { elements }
59
84
}
60
85
0 commit comments