Algorithm.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Algorithm_H
21 #define MIRTK_Algorithm_H
22 
23 #include "mirtk/Array.h"
24 #include "mirtk/UnorderedSet.h"
25 #include "mirtk/Pair.h"
26 
27 #include <algorithm>
28 #include <functional>
29 #include <iterator>
30 
31 
32 namespace mirtk {
33 
34 
35 using std::min_element;
36 using std::max_element;
37 using std::minmax_element;
38 using std::find;
39 using std::binary_search;
40 using std::sort;
41 using std::stable_sort;
42 using std::partial_sort;
43 using std::nth_element;
44 using std::reverse;
45 using std::shuffle;
46 using std::set_intersection;
47 
48 using std::copy;
49 using std::back_inserter;
50 using std::front_inserter;
51 using std::inserter;
52 
53 using std::transform;
54 using std::bind1st;
55 using std::bind2nd;
56 using std::plus;
57 using std::minus;
58 using std::multiplies;
59 using std::divides;
60 using std::modulus;
61 using std::negate;
62 
63 
64 /// Get minimum array element
65 template <class T>
66 T MinElement(const Array<T> &values)
67 {
68  if (values.empty()) return T(0);
69  return *min_element(values.begin(), values.end());
70 }
71 
72 /// Get maximum array element
73 template <class T>
74 T MaxElement(const Array<T> &values)
75 {
76  if (values.empty()) return T(0);
77  return *max_element(values.begin(), values.end());
78 }
79 
80 /// Get minimum and maximum array element
81 template <class T>
82 Pair<T, T> MinMaxElement(const Array<T> &values)
83 {
84  if (values.empty()) return MakePair(T(0), T(0));
85  auto minmax = minmax_element(values.begin(), values.end());
86  return MakePair(*minmax.first, *minmax.second);
87 }
88 
89 /// Apply unary operation for each array element in-place
90 template <class T, class UnaryOperation>
91 void Transform(Array<T> &values, UnaryOperation op)
92 {
93  transform(values.begin(), values.end(), values.begin(), op);
94 }
95 
96 /// Compare functor used to sort array indices increasing element attribute
97 template <class AttributeType>
99 {
100  const Array<AttributeType> &_Values;
101 
102 public:
103 
104  CompareIndicesOfArrayByIncreasingValue(const Array<AttributeType> &values)
105  :
106  _Values(values)
107  {}
108 
109  template <class IndexType>
110  bool operator ()(IndexType i, IndexType j) const
111  {
112  return _Values[i] < _Values[j];
113  }
114 };
115 
116 /// Compare functor used to sort array indices by decreasing element attribute
117 template <class AttributeType>
119 {
120  const Array<AttributeType> &_Values;
121 
122 public:
123 
124  CompareIndicesOfArrayByDecreasingValue(const Array<AttributeType> &values)
125  :
126  _Values(values)
127  {}
128 
129  template <class IndexType>
130  bool operator ()(IndexType i, IndexType j) const
131  {
132  return _Values[i] > _Values[j];
133  }
134 };
135 
136 /// Sort values in array
137 template <class T>
138 void Sort(Array<T> &values)
139 {
140  sort(values.begin(), values.end());
141 }
142 
143 /// Sort values in array using custom comparator
144 template <class T, class Compare>
145 void Sort(Array<T> &values, Compare comp)
146 {
147  sort(values.begin(), values.end(), comp);
148 }
149 
150 /// Sort values in array while preserving order of equal entries
151 template <class T>
152 void StableSort(Array<T> &values)
153 {
154  stable_sort(values.begin(), values.end());
155 }
156 
157 /// Sort values in array while preserving order of equal entries
158 template <class T, class Compare>
159 void StableSort(Array<T> &values, Compare comp)
160 {
161  stable_sort(values.begin(), values.end(), comp);
162 }
163 
164 /// Sort first n values in array
165 template <class T>
166 void PartialSort(Array<T> &values, int n)
167 {
168  partial_sort(values.begin(), values.begin() + n + 1, values.end());
169 }
170 
171 /// Sort values in array using custom comparator
172 template <class T, class Compare>
173 void PartialSort(Array<T> &values, int n, Compare comp)
174 {
175  partial_sort(values.begin(), values.begin() + n + 1, values.end(), comp);
176 }
177 
178 /// Sort values of array such that values before the n-th element are
179 /// smaller than this element and elements after are greater or equal
180 template <class T>
181 T &NthElement(Array<T> &values, int n)
182 {
183  nth_element(values.begin(), values.begin() + n, values.end());
184  return values[n];
185 }
186 
187 /// Sort values of array such that values before the n-th element are
188 /// smaller than this element and elements after are greater or equal
189 /// according to a custom comparator functor
190 template <class T, class Compare>
191 T &NthElement(Array<T> &values, int n, Compare comp)
192 {
193  nth_element(values.begin(), values.begin() + n, values.end(), comp);
194  return values[n];
195 }
196 
197 /// Get median value
198 template <class T>
199 T MedianValue(const Array<T> &values)
200 {
201  Array<T> copy(values);
202  return NthElement(copy, static_cast<int>(values.size())/2);
203 }
204 
205 /// Get permutation of array indices corresponding to sorted order of values
206 template <class T>
207 Array<int> IncreasingOrder(const Array<T> &values)
208 {
209  Array<int> indices(values.size());
210  for (size_t i = 0; i < values.size(); ++i) {
211  indices[i] = static_cast<int>(i);
212  }
214  return indices;
215 }
216 
217 /// Get permutation of array indices corresponding to sorted order of values
218 template <class T>
219 Array<int> DecreasingOrder(const Array<T> &values)
220 {
221  Array<int> indices(values.size());
222  for (size_t i = 0; i < values.size(); ++i) {
223  indices[i] = static_cast<int>(i);
224  }
226  return indices;
227 }
228 
229 /// Get permutation of array values given a permutation of array indices
230 ///
231 /// \sa IncreasingOrder, DecreasingOrder
232 template <class T>
233 Array<T> Permutation(const Array<int> &order, const Array<T> &values)
234 {
235  Array<T> permuted_values;
236  permuted_values.reserve(values.size());
237  for (auto i : order) permuted_values.push_back(values[i]);
238  return permuted_values;
239 }
240 
241 /// Find value in unsorted Array
242 template <class T>
243 typename Array<T>::iterator
244 Find(Array<T> &values, const T &value)
245 {
246  return find(values.begin(), values.end(), value);
247 }
248 
249 /// Find value in unsorted Array
250 template <class T>
251 typename Array<T>::const_iterator
252 Find(const Array<T> &values, const T &value)
253 {
254  return find(values.begin(), values.end(), value);
255 }
256 
257 /// Find value in unsorted Array
258 template <class T>
259 int FindIndex(const Array<T> &values, const T &value)
260 {
261  auto it = find(values.begin(), values.end(), value);
262  if (it == values.end()) return -1;
263  return static_cast<int>(std::distance(values.begin(), it));
264 }
265 
266 /// Find value in sorted Array using binary search
267 template <class T>
268 typename Array<T>::iterator
269 BinarySearch(Array<T> &values, const T &value)
270 {
271  return binary_search(values.begin(), values.end(), value);
272 }
273 
274 /// Find value in sorted Array using binary search
275 template <class T>
276 typename Array<T>::const_iterator
277 BinarySearch(const Array<T> &values, const T &value)
278 {
279  return binary_search(values.begin(), values.end(), value);
280 }
281 
282 /// Find value in sorted Array using binary search with custom comparator
283 template <class T, class Compare>
284 typename Array<T>::iterator
285 BinarySearch(Array<T> &values, const T &value, Compare comp)
286 {
287  return binary_search(values.begin(), values.end(), value, comp);
288 }
289 
290 /// Find value in sorted Array using binary search with custom comparator
291 template <class T, class Compare>
292 typename Array<T>::const_iterator
293 BinarySearch(const Array<T> &values, const T &value, Compare comp)
294 {
295  return binary_search(values.begin(), values.end(), value, comp);
296 }
297 
298 /// Intersection of two unordered sets
299 ///
300 /// \note set_intersection cannot be used for unsorted containers!
301 template <class T>
302 UnorderedSet<T> Intersection(const UnorderedSet<T> &a, const UnorderedSet<T> &b)
303 {
304  if (b.size() < a.size()) {
305  return Intersection(b, a);
306  } else {
307  UnorderedSet<T> c;
308  for (auto v : a) {
309  if (b.find(v) != b.end()) c.insert(v);
310  }
311  return c;
312  }
313 }
314 
315 /// Intersection of two unordered sets
316 ///
317 /// \note set_union cannot be used for unsorted containers!
318 template <class T>
319 UnorderedSet<T> Union(const UnorderedSet<T> &a, const UnorderedSet<T> &b)
320 {
321  if (b.size() > a.size()) {
322  return Union(b, a);
323  } else {
324  UnorderedSet<T> c = a;
325  for (auto v : b) c.insert(v);
326  return c;
327  }
328 }
329 
330 
331 } // namespace mirtk
332 
333 #endif // MIRTK_Algorithm_H
Array< int > IncreasingOrder(const Array< T > &values)
Get permutation of array indices corresponding to sorted order of values.
Definition: Algorithm.h:207
Array< T >::iterator Find(Array< T > &values, const T &value)
Find value in unsorted Array.
Definition: Algorithm.h:244
void Sort(Array< T > &values)
Sort values in array.
Definition: Algorithm.h:138
UnorderedSet< T > Intersection(const UnorderedSet< T > &a, const UnorderedSet< T > &b)
Definition: Algorithm.h:302
Compare functor used to sort array indices by decreasing element attribute.
Definition: Algorithm.h:118
void StableSort(Array< T > &values)
Sort values in array while preserving order of equal entries.
Definition: Algorithm.h:152
Array< T > Permutation(const Array< int > &order, const Array< T > &values)
Definition: Algorithm.h:233
T MaxElement(const Array< T > &values)
Get maximum array element.
Definition: Algorithm.h:74
Array< int > DecreasingOrder(const Array< T > &values)
Get permutation of array indices corresponding to sorted order of values.
Definition: Algorithm.h:219
Definition: IOConfig.h:41
Compare functor used to sort array indices increasing element attribute.
Definition: Algorithm.h:98
void PartialSort(Array< T > &values, int n)
Sort first n values in array.
Definition: Algorithm.h:166
T MedianValue(const Array< T > &values)
Get median value.
Definition: Algorithm.h:199
Array< T >::iterator BinarySearch(Array< T > &values, const T &value)
Find value in sorted Array using binary search.
Definition: Algorithm.h:269
UnorderedSet< T > Union(const UnorderedSet< T > &a, const UnorderedSet< T > &b)
Definition: Algorithm.h:319
int FindIndex(const Array< T > &values, const T &value)
Find value in unsorted Array.
Definition: Algorithm.h:259
T MinElement(const Array< T > &values)
Get minimum array element.
Definition: Algorithm.h:66
Pair< T, T > MinMaxElement(const Array< T > &values)
Get minimum and maximum array element.
Definition: Algorithm.h:82
T & NthElement(Array< T > &values, int n)
Definition: Algorithm.h:181
void Transform(Array< T > &values, UnaryOperation op)
Apply unary operation for each array element in-place.
Definition: Algorithm.h:91