@@ -22,6 +22,7 @@ use crate::difference::{IsZero, Semigroup};
22
22
/// This method will sort `vec` and then consolidate runs of more than one entry with
23
23
/// identical first elements by accumulating the second elements of the pairs. Should the final
24
24
/// accumulation be zero, the element is discarded.
25
+ #[ inline]
25
26
pub fn consolidate < T : Ord , R : Semigroup > ( vec : & mut Vec < ( T , R ) > ) {
26
27
consolidate_from ( vec, 0 ) ;
27
28
}
@@ -31,55 +32,61 @@ pub fn consolidate<T: Ord, R: Semigroup>(vec: &mut Vec<(T, R)>) {
31
32
/// This method will sort `vec[offset..]` and then consolidate runs of more than one entry with
32
33
/// identical first elements by accumulating the second elements of the pairs. Should the final
33
34
/// accumulation be zero, the element is discarded.
35
+ #[ inline]
34
36
pub fn consolidate_from < T : Ord , R : Semigroup > ( vec : & mut Vec < ( T , R ) > , offset : usize ) {
35
37
let length = consolidate_slice ( & mut vec[ offset..] ) ;
36
38
vec. truncate ( offset + length) ;
37
39
}
38
40
39
41
/// Sorts and consolidates a slice, returning the valid prefix length.
42
+ #[ inline]
40
43
pub fn consolidate_slice < T : Ord , R : Semigroup > ( slice : & mut [ ( T , R ) ] ) -> usize {
41
-
42
44
if slice. len ( ) > 1 {
45
+ consolidate_slice_slow ( slice)
46
+ }
47
+ else {
48
+ slice. iter ( ) . filter ( |x| !x. 1 . is_zero ( ) ) . count ( )
49
+ }
50
+ }
43
51
44
- // We could do an insertion-sort like initial scan which builds up sorted, consolidated runs.
45
- // In a world where there are not many results, we may never even need to call in to merge sort.
46
- slice. sort_by ( |x, y| x. 0 . cmp ( & y. 0 ) ) ;
52
+ /// Part of `consolidate_slice` that handles slices of length greater than 1.
53
+ fn consolidate_slice_slow < T : Ord , R : Semigroup > ( slice : & mut [ ( T , R ) ] ) -> usize {
54
+ // We could do an insertion-sort like initial scan which builds up sorted, consolidated runs.
55
+ // In a world where there are not many results, we may never even need to call in to merge sort.
56
+ slice. sort_by ( |x, y| x. 0 . cmp ( & y. 0 ) ) ;
47
57
48
- // Counts the number of distinct known-non-zero accumulations. Indexes the write location.
49
- let mut offset = 0 ;
50
- let mut accum = slice[ offset] . 1 . clone ( ) ;
58
+ // Counts the number of distinct known-non-zero accumulations. Indexes the write location.
59
+ let mut offset = 0 ;
60
+ let mut accum = slice[ offset] . 1 . clone ( ) ;
51
61
52
- for index in 1 .. slice. len ( ) {
53
- if slice[ index] . 0 == slice[ index-1 ] . 0 {
54
- accum. plus_equals ( & slice[ index] . 1 ) ;
55
- }
56
- else {
57
- if !accum. is_zero ( ) {
58
- slice. swap ( offset, index-1 ) ;
59
- slice[ offset] . 1 . clone_from ( & accum) ;
60
- offset += 1 ;
61
- }
62
- accum. clone_from ( & slice[ index] . 1 ) ;
63
- }
62
+ for index in 1 .. slice. len ( ) {
63
+ if slice[ index] . 0 == slice[ index-1 ] . 0 {
64
+ accum. plus_equals ( & slice[ index] . 1 ) ;
64
65
}
65
- if !accum. is_zero ( ) {
66
- slice. swap ( offset, slice. len ( ) -1 ) ;
67
- slice[ offset] . 1 = accum;
68
- offset += 1 ;
66
+ else {
67
+ if !accum. is_zero ( ) {
68
+ slice. swap ( offset, index-1 ) ;
69
+ slice[ offset] . 1 . clone_from ( & accum) ;
70
+ offset += 1 ;
71
+ }
72
+ accum. clone_from ( & slice[ index] . 1 ) ;
69
73
}
70
-
71
- offset
72
74
}
73
- else {
74
- slice. iter ( ) . filter ( |x| !x. 1 . is_zero ( ) ) . count ( )
75
+ if !accum. is_zero ( ) {
76
+ slice. swap ( offset, slice. len ( ) -1 ) ;
77
+ slice[ offset] . 1 = accum;
78
+ offset += 1 ;
75
79
}
80
+
81
+ offset
76
82
}
77
83
78
84
/// Sorts and consolidates `vec`.
79
85
///
80
86
/// This method will sort `vec` and then consolidate runs of more than one entry with
81
87
/// identical first two elements by accumulating the third elements of the triples. Should the final
82
88
/// accumulation be zero, the element is discarded.
89
+ #[ inline]
83
90
pub fn consolidate_updates < D : Ord , T : Ord , R : Semigroup > ( vec : & mut Vec < ( D , T , R ) > ) {
84
91
consolidate_updates_from ( vec, 0 ) ;
85
92
}
@@ -89,48 +96,54 @@ pub fn consolidate_updates<D: Ord, T: Ord, R: Semigroup>(vec: &mut Vec<(D, T, R)
89
96
/// This method will sort `vec[offset..]` and then consolidate runs of more than one entry with
90
97
/// identical first two elements by accumulating the third elements of the triples. Should the final
91
98
/// accumulation be zero, the element is discarded.
99
+ #[ inline]
92
100
pub fn consolidate_updates_from < D : Ord , T : Ord , R : Semigroup > ( vec : & mut Vec < ( D , T , R ) > , offset : usize ) {
93
101
let length = consolidate_updates_slice ( & mut vec[ offset..] ) ;
94
102
vec. truncate ( offset + length) ;
95
103
}
96
104
97
105
/// Sorts and consolidates a slice, returning the valid prefix length.
106
+ #[ inline]
98
107
pub fn consolidate_updates_slice < D : Ord , T : Ord , R : Semigroup > ( slice : & mut [ ( D , T , R ) ] ) -> usize {
99
108
100
109
if slice. len ( ) > 1 {
110
+ consolidate_updates_slice_slow ( slice)
111
+ }
112
+ else {
113
+ slice. iter ( ) . filter ( |x| !x. 2 . is_zero ( ) ) . count ( )
114
+ }
115
+ }
101
116
102
- // We could do an insertion-sort like initial scan which builds up sorted, consolidated runs.
103
- // In a world where there are not many results, we may never even need to call in to merge sort.
104
- slice. sort_unstable_by ( |x, y| ( & x. 0 , & x. 1 ) . cmp ( & ( & y. 0 , & y. 1 ) ) ) ;
117
+ /// Part of `consolidate_updates_slice` that handles slices of length greater than 1.
118
+ fn consolidate_updates_slice_slow < D : Ord , T : Ord , R : Semigroup > ( slice : & mut [ ( D , T , R ) ] ) -> usize {
119
+ // We could do an insertion-sort like initial scan which builds up sorted, consolidated runs.
120
+ // In a world where there are not many results, we may never even need to call in to merge sort.
121
+ slice. sort_unstable_by ( |x, y| ( & x. 0 , & x. 1 ) . cmp ( & ( & y. 0 , & y. 1 ) ) ) ;
105
122
106
- // Counts the number of distinct known-non-zero accumulations. Indexes the write location.
107
- let mut offset = 0 ;
108
- let mut accum = slice[ offset] . 2 . clone ( ) ;
123
+ // Counts the number of distinct known-non-zero accumulations. Indexes the write location.
124
+ let mut offset = 0 ;
125
+ let mut accum = slice[ offset] . 2 . clone ( ) ;
109
126
110
- for index in 1 .. slice. len ( ) {
111
- if ( slice[ index] . 0 == slice[ index-1 ] . 0 ) && ( slice[ index] . 1 == slice[ index-1 ] . 1 ) {
112
- accum. plus_equals ( & slice[ index] . 2 ) ;
113
- }
114
- else {
115
- if !accum. is_zero ( ) {
116
- slice. swap ( offset, index-1 ) ;
117
- slice[ offset] . 2 . clone_from ( & accum) ;
118
- offset += 1 ;
119
- }
120
- accum. clone_from ( & slice[ index] . 2 ) ;
121
- }
127
+ for index in 1 .. slice. len ( ) {
128
+ if ( slice[ index] . 0 == slice[ index-1 ] . 0 ) && ( slice[ index] . 1 == slice[ index-1 ] . 1 ) {
129
+ accum. plus_equals ( & slice[ index] . 2 ) ;
122
130
}
123
- if !accum. is_zero ( ) {
124
- slice. swap ( offset, slice. len ( ) -1 ) ;
125
- slice[ offset] . 2 = accum;
126
- offset += 1 ;
131
+ else {
132
+ if !accum. is_zero ( ) {
133
+ slice. swap ( offset, index-1 ) ;
134
+ slice[ offset] . 2 . clone_from ( & accum) ;
135
+ offset += 1 ;
136
+ }
137
+ accum. clone_from ( & slice[ index] . 2 ) ;
127
138
}
128
-
129
- offset
130
139
}
131
- else {
132
- slice. iter ( ) . filter ( |x| !x. 2 . is_zero ( ) ) . count ( )
140
+ if !accum. is_zero ( ) {
141
+ slice. swap ( offset, slice. len ( ) -1 ) ;
142
+ slice[ offset] . 2 = accum;
143
+ offset += 1 ;
133
144
}
145
+
146
+ offset
134
147
}
135
148
136
149
0 commit comments