@@ -5,7 +5,7 @@ use super::Relation;
55/// Performs treefrog leapjoin using a list of leapers.
66pub ( crate ) fn leapjoin < ' a , Tuple : Ord , Val : Ord + ' a , Result : Ord > (
77 source : & [ Tuple ] ,
8- leapers : & mut [ & mut dyn Leaper < ' a , Tuple , Val > ] ,
8+ mut leapers : & mut [ & mut dyn Leaper < ' a , Tuple , Val > ] ,
99 mut logic : impl FnMut ( & Tuple , & Val ) -> Result ,
1010) -> Relation < Result > {
1111 let mut result = Vec :: new ( ) ; // temp output storage.
@@ -15,30 +15,26 @@ pub(crate) fn leapjoin<'a, Tuple: Ord, Val: Ord + 'a, Result: Ord>(
1515 // Determine which leaper would propose the fewest values.
1616 let mut min_index = usize:: max_value ( ) ;
1717 let mut min_count = usize:: max_value ( ) ;
18- for index in 0 ..leapers. len ( ) {
19- let count = leapers[ index] . count ( tuple) ;
18+ leapers. for_each_count ( tuple, |index, count| {
2019 if min_count > count {
2120 min_count = count;
2221 min_index = index;
2322 }
24- }
23+ } ) ;
2524
2625 // We had best have at least one relation restricting values.
2726 assert ! ( min_count < usize :: max_value( ) ) ;
2827
29- // If there are values to propose ..
28+ // If there are values to propose:
3029 if min_count > 0 {
31- // Propose them, ..
32- leapers[ min_index] . propose ( tuple, & mut values) ;
33-
34- // Intersect them, ..
35- for index in 0 ..leapers. len ( ) {
36- if index != min_index {
37- leapers[ index] . intersect ( tuple, & mut values) ;
38- }
39- }
30+ // Push the values that `min_index` "proposes" into `values`.
31+ leapers. propose ( tuple, min_index, & mut values) ;
32+
33+ // Give other leapers a chance to remove values from
34+ // anti-joins or filters.
35+ leapers. intersect ( tuple, min_index, & mut values) ;
4036
41- // Respond to each of them .
37+ // Push remaining items into result .
4238 for val in values. drain ( ..) {
4339 result. push ( logic ( tuple, val) ) ;
4440 }
@@ -48,6 +44,35 @@ pub(crate) fn leapjoin<'a, Tuple: Ord, Val: Ord + 'a, Result: Ord>(
4844 Relation :: from_vec ( result)
4945}
5046
47+ pub trait Leapers < ' a , Tuple , Val > {
48+ fn for_each_count ( & mut self , tuple : & Tuple , op : impl FnMut ( usize , usize ) ) ;
49+
50+ fn propose ( & mut self , tuple : & Tuple , min_index : usize , values : & mut Vec < & ' a Val > ) ;
51+
52+ fn intersect ( & mut self , tuple : & Tuple , min_index : usize , values : & mut Vec < & ' a Val > ) ;
53+ }
54+
55+ impl < ' a , Tuple , Val > Leapers < ' a , Tuple , Val > for & mut [ & mut dyn Leaper < ' a , Tuple , Val > ] {
56+ fn for_each_count ( & mut self , tuple : & Tuple , mut op : impl FnMut ( usize , usize ) ) {
57+ for ( index, leaper) in self . iter_mut ( ) . enumerate ( ) {
58+ let count = leaper. count ( tuple) ;
59+ op ( index, count) ;
60+ }
61+ }
62+
63+ fn propose ( & mut self , tuple : & Tuple , min_index : usize , values : & mut Vec < & ' a Val > ) {
64+ self [ min_index] . propose ( tuple, values) ;
65+ }
66+
67+ fn intersect ( & mut self , tuple : & Tuple , min_index : usize , values : & mut Vec < & ' a Val > ) {
68+ for ( index, leaper) in self . iter_mut ( ) . enumerate ( ) {
69+ if index != min_index {
70+ leaper. intersect ( tuple, values) ;
71+ }
72+ }
73+ }
74+ }
75+
5176/// Methods to support treefrog leapjoin.
5277pub trait Leaper < ' a , Tuple , Val > {
5378 /// Estimates the number of proposed values.
0 commit comments