@@ -10,50 +10,47 @@ pub fn leapfrog_into<'a, Tuple: Ord, Val: Ord+'a, Result: Ord>(
10
10
mut logic : impl FnMut ( & Tuple , & Val ) ->Result ) {
11
11
12
12
let mut result = Vec :: new ( ) ;
13
+ let mut values = Vec :: new ( ) ;
13
14
14
15
for tuple in source. recent . borrow ( ) . iter ( ) {
15
16
16
- for leaper in leapers. iter_mut ( ) {
17
- leaper. seek_prefix ( tuple) ;
17
+ let mut min_index = usize:: max_value ( ) ;
18
+ let mut min_count = usize:: max_value ( ) ;
19
+ for index in 0 .. leapers. len ( ) {
20
+ let count = leapers[ index] . count ( tuple) ;
21
+ if min_count > count {
22
+ min_count = count;
23
+ min_index = index;
24
+ }
18
25
}
19
26
20
- while !leapers. iter ( ) . any ( |l| l. is_empty ( ) ) {
21
- // for leaper in leapers.iter() { println!("{:?}, {:?}", leaper.peek_val().is_some(), leaper.is_empty()); }
22
- let val = leapers. iter_mut ( ) . flat_map ( |l| l. peek_val ( ) ) . max ( ) . expect ( "No maximum found" ) ;
23
- let mut present = true ;
24
- for leaper in leapers. iter_mut ( ) {
25
- if !leaper. seek_val ( & val) { present = false ; }
27
+ assert ! ( min_count < usize :: max_value( ) ) ;
28
+ if min_count > 0 {
29
+ leapers[ min_index] . propose ( tuple, & mut values) ;
30
+
31
+ for index in 0 .. leapers. len ( ) {
32
+ if index != min_index {
33
+ leapers[ index] . intersect ( tuple, & mut values) ;
34
+ }
26
35
}
27
- if present {
28
- result. push ( logic ( & tuple, & val) ) ;
36
+
37
+ for val in values. drain ( ..) {
38
+ result. push ( logic ( tuple, val) ) ;
29
39
}
30
40
}
31
-
32
41
}
33
42
34
43
output. insert ( result. into ( ) ) ;
35
44
}
36
45
37
46
/// Methods to support leapfrog navigation.
38
47
pub trait LeapFrog < ' a , Tuple , Val > {
39
- /// Sets the cursor for a specific key.
40
- fn seek_prefix ( & mut self , prefix : & Tuple ) ;
41
- /// Seeks a specific key and value pair.
42
- ///
43
- /// This method positions the cursor just after `val`,
44
- /// under the assumption that we will not seek for the
45
- /// same value immediately afterwards.
46
- fn seek_val ( & mut self , val : & Val ) -> bool ;
47
- /// Proposes a next value.
48
- ///
49
- /// It is not mandatory that this method return a value,
50
- /// but we will only observe extensions in the union of
51
- /// peeked values. This allows antijoin implementations
52
- /// to implement this interface, as long as at least one
53
- /// normal join participates.
54
- fn peek_val ( & self ) -> Option < & ' a Val > ;
55
- /// Indicates no further values available.
56
- fn is_empty ( & self ) -> bool ;
48
+ /// Estimates the number of proposed values.
49
+ fn count ( & mut self , prefix : & Tuple ) -> usize ;
50
+ /// Populates `values` with proposed values.
51
+ fn propose ( & mut self , prefix : & Tuple , values : & mut Vec < & ' a Val > ) ;
52
+ /// Restricts `values` to proposed values.
53
+ fn intersect ( & mut self , prefix : & Tuple , values : & mut Vec < & ' a Val > ) ;
57
54
}
58
55
59
56
/// Extension method for relations.
@@ -110,42 +107,25 @@ mod extend_with {
110
107
}
111
108
112
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 > {
113
- fn seek_prefix ( & mut self , tuple : & Tuple ) {
114
- let key = ( self . key_func ) ( tuple) ;
110
+
111
+ fn count ( & mut self , prefix : & Tuple ) -> usize {
112
+ let key = ( self . key_func ) ( prefix) ;
115
113
let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
116
114
let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
117
115
self . start = self . relation . len ( ) - slice1. len ( ) ;
118
116
self . end = self . relation . len ( ) - slice2. len ( ) ;
119
- assert ! ( self . start <= self . end) ;
120
- }
121
- fn seek_val ( & mut self , val : & Val ) -> bool {
122
- assert ! ( self . start <= self . end) ;
123
- // Attempt to position the cursor at (key, val).
124
- if !self . is_empty ( ) {
125
- let slice = gallop ( & self . relation [ self . start .. self . end ] , |x| & x. 1 < val) ;
126
- self . start = self . end - slice. len ( ) ;
127
- }
128
- // If the cursor is positioned at something that yields `val`, then success.
129
- if self . peek_val ( ) == Some ( val) {
130
- self . start += 1 ;
131
- true
132
- }
133
- else {
134
- false
135
- }
117
+ slice1. len ( ) - slice2. len ( )
136
118
}
137
- fn peek_val ( & self ) -> Option < & ' a Val > {
138
- assert ! ( self . start <= self . end) ;
139
- if self . start < self . end {
140
- Some ( & self . relation [ self . start ] . 1 )
141
- }
142
- else {
143
- None
144
- }
119
+ fn propose ( & mut self , _prefix : & Tuple , values : & mut Vec < & ' a Val > ) {
120
+ let slice = & self . relation [ self . start .. self . end ] ;
121
+ values. extend ( slice. iter ( ) . map ( |& ( _, ref val) | val) ) ;
145
122
}
146
- fn is_empty ( & self ) -> bool {
147
- assert ! ( self . start <= self . end) ;
148
- self . start == self . end
123
+ fn intersect ( & mut self , _prefix : & Tuple , values : & mut Vec < & ' a Val > ) {
124
+ let mut slice = & self . relation [ self . start .. self . end ] ;
125
+ values. retain ( |v| {
126
+ slice = gallop ( slice, |kv| & kv. 1 < v) ;
127
+ slice. get ( 0 ) . map ( |kv| & kv. 1 ) == Some ( v)
128
+ } ) ;
149
129
}
150
130
}
151
131
}
@@ -157,8 +137,6 @@ mod extend_anti {
157
137
/// Wraps a Relation<Tuple> as a leaper.
158
138
pub struct ExtendAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->Key > {
159
139
relation : & ' a Relation < ( Key , Val ) > ,
160
- start : usize ,
161
- end : usize ,
162
140
key_func : Func ,
163
141
phantom : :: std:: marker:: PhantomData < Tuple > ,
164
142
}
@@ -168,44 +146,30 @@ mod extend_anti {
168
146
pub fn from ( relation : & ' a Relation < ( Key , Val ) > , key_func : Func ) -> Self {
169
147
ExtendAnti {
170
148
relation,
171
- start : 0 ,
172
- end : 0 ,
173
149
key_func,
174
150
phantom : :: std:: marker:: PhantomData ,
175
151
}
176
152
}
177
153
}
178
154
179
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 > {
180
- fn seek_prefix ( & mut self , tuple : & Tuple ) {
181
- let key = ( self . key_func ) ( tuple) ;
156
+ fn count ( & mut self , _prefix : & Tuple ) -> usize {
157
+ usize:: max_value ( )
158
+ }
159
+ fn propose ( & mut self , _prefix : & Tuple , _values : & mut Vec < & ' a Val > ) {
160
+ panic ! ( "ExtendAnti::propose(): variable apparently unbound." ) ;
161
+ }
162
+ fn intersect ( & mut self , prefix : & Tuple , values : & mut Vec < & ' a Val > ) {
163
+ let key = ( self . key_func ) ( prefix) ;
182
164
let slice1 = gallop ( & self . relation [ ..] , |x| & x. 0 < & key) ;
183
165
let slice2 = gallop ( slice1, |x| & x. 0 <= & key) ;
184
- self . start = self . relation . len ( ) - slice1. len ( ) ;
185
- self . end = self . relation . len ( ) - slice2. len ( ) ;
186
- assert ! ( self . start <= self . end) ;
187
- }
188
- fn seek_val ( & mut self , val : & Val ) -> bool {
189
- assert ! ( self . start <= self . end) ;
190
- // Attempt to position the cursor at (key, val).
191
- if !self . is_empty ( ) {
192
- let slice = gallop ( & self . relation [ self . start .. self . end ] , |x| & x. 1 < val) ;
193
- self . start = self . end - slice. len ( ) ;
194
- }
195
- // If the cursor is positioned at something that yields `val`, then success.
196
- if self . start < self . end && & self . relation [ self . start ] . 1 == val {
197
- self . start += 1 ;
198
- false
166
+ let mut slice = & slice1[ .. ( slice1. len ( ) - slice2. len ( ) ) ] ;
167
+ if !slice. is_empty ( ) {
168
+ values. retain ( |v| {
169
+ slice = gallop ( slice, |kv| & kv. 1 < v) ;
170
+ slice. get ( 0 ) . map ( |kv| & kv. 1 ) != Some ( v)
171
+ } ) ;
199
172
}
200
- else {
201
- true
202
- }
203
- }
204
- fn peek_val ( & self ) -> Option < & ' a Val > {
205
- None
206
- }
207
- fn is_empty ( & self ) -> bool {
208
- false
209
173
}
210
174
}
211
175
}
@@ -218,7 +182,6 @@ mod filter_with {
218
182
pub struct FilterWith < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
219
183
relation : & ' a Relation < ( Key , Val ) > ,
220
184
key_func : Func ,
221
- found : bool ,
222
185
phantom : :: std:: marker:: PhantomData < Tuple > ,
223
186
}
224
187
@@ -228,25 +191,26 @@ mod filter_with {
228
191
FilterWith {
229
192
relation,
230
193
key_func,
231
- found : false ,
232
194
phantom : :: std:: marker:: PhantomData ,
233
195
}
234
196
}
235
197
}
236
198
237
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 > {
238
- fn seek_prefix ( & mut self , tuple : & Tuple ) {
239
- let key_val = ( self . key_func ) ( tuple) ;
240
- self . found = self . relation . binary_search ( & key_val) . is_ok ( ) ;
241
- }
242
- fn seek_val ( & mut self , _val : & Val2 ) -> bool {
243
- self . found
200
+ fn count ( & mut self , prefix : & Tuple ) -> usize {
201
+ let key_val = ( self . key_func ) ( prefix) ;
202
+ if self . relation . binary_search ( & key_val) . is_ok ( ) {
203
+ usize:: max_value ( )
204
+ }
205
+ else {
206
+ 0
207
+ }
244
208
}
245
- fn peek_val ( & self ) -> Option < & ' a Val2 > {
246
- None
209
+ fn propose ( & mut self , _prefix : & Tuple , _values : & mut Vec < & ' a Val2 > ) {
210
+ panic ! ( "FilterWith::propose(): variable apparently unbound." ) ;
247
211
}
248
- fn is_empty ( & self ) -> bool {
249
- ! self . found
212
+ fn intersect ( & mut self , _prefix : & Tuple , _values : & mut Vec < & ' a Val2 > ) {
213
+ // Only here because we didn't return zero above, right?
250
214
}
251
215
}
252
216
}
@@ -259,7 +223,6 @@ mod filter_anti {
259
223
pub struct FilterAnti < ' a , Key : Ord +' a , Val : Ord +' a , Tuple : Ord , Func : Fn ( & Tuple ) ->( Key , Val ) > {
260
224
relation : & ' a Relation < ( Key , Val ) > ,
261
225
key_func : Func ,
262
- found : bool ,
263
226
phantom : :: std:: marker:: PhantomData < Tuple > ,
264
227
}
265
228
@@ -269,25 +232,26 @@ mod filter_anti {
269
232
FilterAnti {
270
233
relation,
271
234
key_func,
272
- found : false ,
273
235
phantom : :: std:: marker:: PhantomData ,
274
236
}
275
237
}
276
238
}
277
239
278
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 > {
279
- fn seek_prefix ( & mut self , tuple : & Tuple ) {
280
- let key_val = ( self . key_func ) ( tuple) ;
281
- self . found = self . relation . binary_search ( & key_val) . is_ok ( ) ;
282
- }
283
- fn seek_val ( & mut self , _val : & Val2 ) -> bool {
284
- !self . found
241
+ fn count ( & mut self , prefix : & Tuple ) -> usize {
242
+ let key_val = ( self . key_func ) ( prefix) ;
243
+ if self . relation . binary_search ( & key_val) . is_ok ( ) {
244
+ 0
245
+ }
246
+ else {
247
+ usize:: max_value ( )
248
+ }
285
249
}
286
- fn peek_val ( & self ) -> Option < & ' a Val2 > {
287
- None
250
+ fn propose ( & mut self , _prefix : & Tuple , _values : & mut Vec < & ' a Val2 > ) {
251
+ panic ! ( "FilterWith::propose(): variable apparently unbound." ) ;
288
252
}
289
- fn is_empty ( & self ) -> bool {
290
- self . found
253
+ fn intersect ( & mut self , _prefix : & Tuple , _values : & mut Vec < & ' a Val2 > ) {
254
+ // Only here because we didn't return zero above, right?
291
255
}
292
256
}
293
257
}
0 commit comments