2
2
3
3
use super :: { Variable , Relation } ;
4
4
5
- /// Performs leapfrog join using a list of leapers.
6
- pub fn leapfrog_into < ' a , Tuple : Ord , Val : Ord +' a , Result : Ord > (
5
+ /// Performs treefrog leapjoin using a list of leapers.
6
+ pub fn leapjoin_into < ' a , Tuple : Ord , Val : Ord +' a , Result : Ord > (
7
7
source : & Variable < Tuple > ,
8
- leapers : & mut [ & mut LeapFrog < ' a , Tuple , Val > ] ,
8
+ leapers : & mut [ & mut Leaper < ' a , Tuple , Val > ] ,
9
9
output : & Variable < Result > ,
10
10
mut logic : impl FnMut ( & Tuple , & Val ) ->Result ) {
11
11
12
- let mut result = Vec :: new ( ) ;
13
- let mut values = Vec :: new ( ) ;
12
+ let mut result = Vec :: new ( ) ; // temp output storage.
13
+ let mut values = Vec :: new ( ) ; // temp value storage.
14
14
15
15
for tuple in source. recent . borrow ( ) . iter ( ) {
16
16
17
+ // Determine which leaper would propose the fewest values.
17
18
let mut min_index = usize:: max_value ( ) ;
18
19
let mut min_count = usize:: max_value ( ) ;
19
20
for index in 0 .. leapers. len ( ) {
@@ -24,16 +25,23 @@ pub fn leapfrog_into<'a, Tuple: Ord, Val: Ord+'a, Result: Ord>(
24
25
}
25
26
}
26
27
28
+ // We had best have at least one relation restricting values.
27
29
assert ! ( min_count < usize :: max_value( ) ) ;
30
+
31
+ // If there are values to propose ..
28
32
if min_count > 0 {
33
+
34
+ // Propose them, ..
29
35
leapers[ min_index] . propose ( tuple, & mut values) ;
30
36
37
+ // Intersect them, ..
31
38
for index in 0 .. leapers. len ( ) {
32
39
if index != min_index {
33
40
leapers[ index] . intersect ( tuple, & mut values) ;
34
41
}
35
42
}
36
43
44
+ // Respond to each of them.
37
45
for val in values. drain ( ..) {
38
46
result. push ( logic ( tuple, val) ) ;
39
47
}
@@ -43,8 +51,8 @@ pub fn leapfrog_into<'a, Tuple: Ord, Val: Ord+'a, Result: Ord>(
43
51
output. insert ( result. into ( ) ) ;
44
52
}
45
53
46
- /// Methods to support leapfrog navigation .
47
- pub trait LeapFrog < ' a , Tuple , Val > {
54
+ /// Methods to support treefrog leapjoin .
55
+ pub trait Leaper < ' a , Tuple , Val > {
48
56
/// Estimates the number of proposed values.
49
57
fn count ( & mut self , prefix : & Tuple ) -> usize ;
50
58
/// Populates `values` with proposed values.
@@ -54,7 +62,7 @@ pub trait LeapFrog<'a,Tuple,Val> {
54
62
}
55
63
56
64
/// Extension method for relations.
57
- pub trait Leaper < Key : Ord , Val : Ord > {
65
+ pub trait RelationLeaper < Key : Ord , Val : Ord > {
58
66
/// Extend with `Val` using the elements of the relation.
59
67
fn extend_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_with:: ExtendWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
60
68
/// Extend with `Val` using the complement of the relation.
@@ -65,7 +73,7 @@ pub trait Leaper<Key: Ord, Val: Ord> {
65
73
fn filter_anti < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > ( & ' a self , key_func : Func ) -> filter_anti:: FilterAnti < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a ;
66
74
}
67
75
68
- impl < Key : Ord , Val : Ord > Leaper < Key , Val > for Relation < ( Key , Val ) > {
76
+ impl < Key : Ord , Val : Ord > RelationLeaper < Key , Val > for Relation < ( Key , Val ) > {
69
77
fn extend_with < ' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > ( & ' a self , key_func : Func ) -> extend_with:: ExtendWith < ' a , Key , Val , Tuple , Func > where Key : ' a , Val : ' a {
70
78
extend_with:: ExtendWith :: from ( self , key_func)
71
79
}
@@ -82,7 +90,7 @@ impl<Key: Ord, Val: Ord> Leaper<Key, Val> for Relation<(Key, Val)> {
82
90
83
91
mod extend_with {
84
92
85
- use super :: { Relation , LeapFrog , gallop} ;
93
+ use super :: { Relation , Leaper , gallop, binary_search } ;
86
94
87
95
/// Wraps a Relation<Tuple> as a leaper.
88
96
pub struct ExtendWith < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > {
@@ -106,13 +114,13 @@ mod extend_with {
106
114
}
107
115
}
108
116
109
- impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > LeapFrog < ' a , Tuple , Val > for ExtendWith < ' a , Key , Val , Tuple , Func > {
117
+ impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > Leaper < ' a , Tuple , Val > for ExtendWith < ' a , Key , Val , Tuple , Func > {
110
118
111
119
fn count ( & mut self , prefix : & Tuple ) -> usize {
112
120
let key = ( self . key_func ) ( prefix) ;
113
- let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
121
+ self . start = binary_search ( & self . relation [ ..] , |x| & x. 0 < & key) ;
122
+ let slice1 = & self . relation [ self . start ..] ;
114
123
let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
115
- self . start = self . relation . len ( ) - slice1. len ( ) ;
116
124
self . end = self . relation . len ( ) - slice2. len ( ) ;
117
125
slice1. len ( ) - slice2. len ( )
118
126
}
@@ -132,7 +140,7 @@ mod extend_with {
132
140
133
141
mod extend_anti {
134
142
135
- use super :: { Relation , LeapFrog , gallop} ;
143
+ use super :: { Relation , Leaper , gallop, binary_search } ;
136
144
137
145
/// Wraps a Relation<Tuple> as a leaper.
138
146
pub struct ExtendAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > {
@@ -152,7 +160,7 @@ mod extend_anti {
152
160
}
153
161
}
154
162
155
- impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > LeapFrog < ' a , Tuple , Val > for ExtendAnti < ' a , Key , Val , Tuple , Func > {
163
+ impl < ' a , Key : Ord , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > Leaper < ' a , Tuple , Val > for ExtendAnti < ' a , Key , Val , Tuple , Func > {
156
164
fn count ( & mut self , _prefix : & Tuple ) -> usize {
157
165
usize:: max_value ( )
158
166
}
@@ -161,7 +169,8 @@ mod extend_anti {
161
169
}
162
170
fn intersect ( & mut self , prefix : & Tuple , values : & mut Vec < & ' a Val > ) {
163
171
let key = ( self . key_func ) ( prefix) ;
164
- let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
172
+ let start = binary_search ( & self . relation [ ..] , |x| & x. 0 < & key) ;
173
+ let slice1 = & self . relation [ start..] ;
165
174
let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
166
175
let mut slice = & slice1[ .. ( slice1. len ( ) - slice2. len ( ) ) ] ;
167
176
if !slice. is_empty ( ) {
@@ -176,7 +185,7 @@ mod extend_anti {
176
185
177
186
mod filter_with {
178
187
179
- use super :: { Relation , LeapFrog } ;
188
+ use super :: { Relation , Leaper } ;
180
189
181
190
/// Wraps a Relation<Tuple> as a leaper.
182
191
pub struct FilterWith < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
@@ -196,7 +205,7 @@ mod filter_with {
196
205
}
197
206
}
198
207
199
- impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > LeapFrog < ' a , Tuple , Val2 > for FilterWith < ' a , Key , Val , Tuple , Func > {
208
+ impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > Leaper < ' a , Tuple , Val2 > for FilterWith < ' a , Key , Val , Tuple , Func > {
200
209
fn count ( & mut self , prefix : & Tuple ) -> usize {
201
210
let key_val = ( self . key_func ) ( prefix) ;
202
211
if self . relation . binary_search ( & key_val) . is_ok ( ) {
@@ -217,7 +226,7 @@ mod filter_with {
217
226
218
227
mod filter_anti {
219
228
220
- use super :: { Relation , LeapFrog } ;
229
+ use super :: { Relation , Leaper } ;
221
230
222
231
/// Wraps a Relation<Tuple> as a leaper.
223
232
pub struct FilterAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
@@ -237,7 +246,7 @@ mod filter_anti {
237
246
}
238
247
}
239
248
240
- impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > LeapFrog < ' a , Tuple , Val2 > for FilterAnti < ' a , Key , Val , Tuple , Func > {
249
+ impl < ' a , Key : Ord , Val : Ord +' a , Val2 , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > Leaper < ' a , Tuple , Val2 > for FilterAnti < ' a , Key , Val , Tuple , Func > {
241
250
fn count ( & mut self , prefix : & Tuple ) -> usize {
242
251
let key_val = ( self . key_func ) ( prefix) ;
243
252
if self . relation . binary_search ( & key_val) . is_ok ( ) {
@@ -256,6 +265,24 @@ mod filter_anti {
256
265
}
257
266
}
258
267
268
+ fn binary_search < T > ( slice : & [ T ] , mut cmp : impl FnMut ( & T ) ->bool ) -> usize {
269
+
270
+ // we maintain the invariant that `lo` many elements of `slice` satisfy `cmp`.
271
+ // `hi` is maintained at the first element we know does not satisfy `cmp`.
272
+
273
+ let mut hi = slice. len ( ) ;
274
+ let mut lo = 0 ;
275
+ while lo < hi {
276
+ let mid = lo + ( hi - lo) /2 ;
277
+ if cmp ( & slice[ mid] ) {
278
+ lo = mid + 1 ;
279
+ }
280
+ else {
281
+ hi = mid;
282
+ }
283
+ }
284
+ lo
285
+ }
259
286
260
287
fn gallop < T > ( mut slice : & [ T ] , mut cmp : impl FnMut ( & T ) ->bool ) -> & [ T ] {
261
288
// if empty slice, or already >= element, return
0 commit comments