Ocean
Subset.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_SUBSET_H
9 #define META_OCEAN_BASE_SUBSET_H
10 
11 #include "ocean/base/Base.h"
12 
13 namespace Ocean
14 {
15 
16 /**
17  * This class implements subset functions.
18  * @ingroup base
19  */
20 class Subset
21 {
22  private:
23 
24  /**
25  * This helper class implements a subset functions.
26  * @tparam TIndex Data type of the index elements
27  */
28  template <typename TIndex>
30  {
31  public:
32 
33  /**
34  * Extracts a subset of a given set of objects by usage of an index vector holding the indices of all objects to be used.
35  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
36  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
37  * @param objects Entire set of objects from that a subset will be extracted
38  * @param indices Indices defining the subset to be extracted
39  * @return Resulting subset of the given objects
40  * @tparam T Data type of the objects
41  */
42  template <typename T>
43  static inline std::vector<T> subset(const std::vector<T>& objects, const std::vector<TIndex>& indices);
44 
45  /**
46  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
47  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
48  * @param objects Entire set of objects from that a subset will be extracted
49  * @param indices Indices defining the subset to be extracted
50  * @return Resulting subset of the given objects
51  * @tparam T Data type of the objects
52  */
53  template <typename T>
54  static inline std::vector<T> subset(const std::vector<T>& objects, const std::set<TIndex>& indices);
55 
56  /**
57  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
58  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
59  * @param objects Entire set of objects from that a subset will be extracted
60  * @param indices Indices defining the inverted subset to be extracted
61  * @return Resulting subset of the given objects
62  * @tparam T Data type of the objects
63  */
64  template <typename T>
65  static inline std::vector<T> invertedSubset(const std::vector<T>& objects, const std::unordered_set<TIndex>& indices);
66 
67  /**
68  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
69  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
70  * @param objects Entire set of objects from that a subset will be extracted
71  * @param indices Indices defining the inverted subset to be extracted
72  * @return Resulting subset of the given objects
73  * @tparam T Data type of the objects
74  */
75  template <typename T>
76  static inline std::vector<T> invertedSubset(const std::vector<T>& objects, const std::set<TIndex>& indices);
77 
78  /**
79  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
80  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
81  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
82  * @param objects Entire set of objects from that a subset will be extracted
83  * @param numberObjects Number of given objects
84  * @param indices Indices defining the subset to be extracted
85  * @param numberIndices Number of given indices
86  * @return Resulting subset of the given objects
87  * @tparam T Data type of the objects
88  */
89  template <typename T>
90  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const TIndex* indices, const size_t numberIndices);
91 
92  /**
93  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
94  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
95  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
96  * @param objects Entire set of objects from that a subset will be extracted
97  * @param numberObjects Number of given objects
98  * @param indices Indices defining the subset to be extracted
99  * @return Resulting subset of the given objects
100  * @tparam T Data type of the objects
101  */
102  template <typename T>
103  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const std::vector<TIndex>& indices);
104 
105  /**
106  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
107  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
108  * @param objects Entire set of objects from that a subset will be extracted
109  * @param numberObjects Number of given objects
110  * @param indices Indices defining the subset to be extracted
111  * @return Resulting subset of the given objects
112  * @tparam T Data type of the objects
113  */
114  template <typename T>
115  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices);
116 
117  /**
118  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
119  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
120  * @param objects Entire set of objects from that a subset will be extracted
121  * @param numberObjects Number of given objects
122  * @param indices Indices defining the inverted subset to be extracted
123  * @return Resulting subset of the given objects
124  * @tparam T Data type of the objects
125  */
126  template <typename T>
127  static inline std::vector<T> invertedSubset(const T* objects, const size_t numberObjects, const std::unordered_set<TIndex>& indices);
128 
129  /**
130  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
131  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
132  * @param objects Entire set of objects from that a subset will be extracted
133  * @param numberObjects Number of given objects
134  * @param indices Indices defining the inverted subset to be extracted
135  * @return Resulting subset of the given objects
136  * @tparam T Data type of the objects
137  */
138  template <typename T>
139  static inline std::vector<T> invertedSubset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices);
140 
141  /**
142  * Converts object indices to an uint8_t vector holding statements for each object.
143  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
144  * @param numberObjects Number of objects that can be addressed by the indices
145  * @return Resulting (boolean != 0u) statements
146  * @tparam TContainer The container to be used, e.g., std::vector, std::set, std::unordred_set
147  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
148  */
149  template <typename TContainer, uint8_t tValue>
150  static inline std::vector<uint8_t> indices2statements(const TContainer& indices, const size_t numberObjects);
151 
152  /**
153  * Converts object indices to an uint8_t vector holding statements for each object.
154  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
155  * @param numberIndices Number of provided indices
156  * @param numberObjects Number of objects that can be addressed by the indices
157  * @return Resulting boolean statements
158  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
159  */
160  template <uint8_t tValue>
161  static inline std::vector<uint8_t> indices2statements(const TIndex* indices, const size_t numberIndices, const size_t numberObjects);
162 
163  /**
164  * Converts an uint8_t vector holding statements for each object into object indices.
165  * @param statements Boolean statement for each object
166  * @return Resulting object indices
167  * @tparam tValue Value for objects that will be defined in the indices
168  */
169  template <uint8_t tValue>
170  static inline std::vector<TIndex> statements2indices(const std::vector<uint8_t>& statements);
171 
172  /**
173  * Converts an uint8_t vector holding statements for each object into object indices.
174  * @param statements Boolean statement for each object
175  * @param numberStatements Number of statements
176  * @return Resulting object indices
177  * @tparam tValue Value for objects that will be defined in the indices
178  */
179  template <uint8_t tValue>
180  static inline std::vector<TIndex> statements2indices(const uint8_t* statements, const size_t numberStatements);
181  };
182 
183  public:
184 
185  /**
186  * Extracts a subset of a given set of objects by usage of an index vector holding the indices of all objects to be used.
187  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
188  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
189  * @param objects Entire set of objects from that a subset will be extracted
190  * @param indices Indices defining the subset to be extracted
191  * @return Resulting subset of the given objects
192  * @tparam TIndex Data type of the index elements
193  * @tparam T Data type of the objects
194  */
195  template <typename TIndex, typename T>
196  static inline std::vector<T> subset(const std::vector<T>& objects, const std::vector<TIndex>& indices);
197 
198  /**
199  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
200  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
201  * @param objects Entire set of objects from that a subset will be extracted
202  * @param indices Indices defining the subset to be extracted
203  * @return Resulting subset of the given objects
204  * @tparam TIndex Data type of the index elements
205  * @tparam T Data type of the objects
206  */
207  template <typename TIndex, typename T>
208  static inline std::vector<T> subset(const std::vector<T>& objects, const std::set<TIndex>& indices);
209 
210  /**
211  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
212  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
213  * @param objects Entire set of objects from that a subset will be extracted
214  * @param indices Indices defining the inverted subset to be extracted
215  * @return Resulting subset of the given objects
216  * @tparam TIndex Data type of the index elements
217  * @tparam T Data type of the objects
218  */
219  template <typename TIndex, typename T>
220  static inline std::vector<T> invertedSubset(const std::vector<T>& objects, const std::unordered_set<TIndex>& indices);
221 
222  /**
223  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
224  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
225  * @param objects Entire set of objects from that a subset will be extracted
226  * @param indices Indices defining the inverted subset to be extracted
227  * @return Resulting subset of the given objects
228  * @tparam TIndex Data type of the index elements
229  * @tparam T Data type of the objects
230  */
231  template <typename TIndex, typename T>
232  static inline std::vector<T> invertedSubset(const std::vector<T>& objects, const std::set<TIndex>& indices);
233 
234  /**
235  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
236  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
237  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
238  * @param objects Entire set of objects from that a subset will be extracted
239  * @param numberObjects Number of given objects
240  * @param indices Indices defining the subset to be extracted
241  * @param numberIndices Number of given indices
242  * @return Resulting subset of the given objects
243  * @tparam TIndex Data type of the index elements
244  * @tparam T Data type of the objects
245  */
246  template <typename TIndex, typename T>
247  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const TIndex* indices, const size_t numberIndices);
248 
249  /**
250  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
251  * If the index data type is an uint8_t, than the (boolean != 0u) statement is used to use the corresponding object or not.<br>
252  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
253  * @param objects Entire set of objects from that a subset will be extracted
254  * @param numberObjects Number of given objects
255  * @param indices Indices defining the subset to be extracted
256  * @return Resulting subset of the given objects
257  * @tparam TIndex Data type of the index elements
258  * @tparam T Data type of the objects
259  */
260  template <typename TIndex, typename T>
261  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const std::vector<TIndex>& indices);
262 
263  /**
264  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be used.
265  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
266  * @param objects Entire set of objects from that a subset will be extracted
267  * @param numberObjects Number of given objects
268  * @param indices Indices defining the subset to be extracted
269  * @return Resulting subset of the given objects
270  * @tparam TIndex Data type of the index elements
271  * @tparam T Data type of the objects
272  */
273  template <typename TIndex, typename T>
274  static inline std::vector<T> subset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices);
275 
276  /**
277  * Extracts the indices that are not given within a set indices.
278  * @param indices The set of given indices, the resulting indices will not contain any of these indices, can contain indices with range [0, maximalIndex]
279  * @param numberElements The number of possible elements defining the entire range of possible indices: [0, numberElements)
280  * @tparam TIndex Data type of the index elements
281  */
282  template <typename TIndex>
283  static std::vector<TIndex> invertedIndices(const std::vector<TIndex>& indices, const size_t numberElements);
284 
285  /**
286  * Extracts the indices that are not given within a set indices.
287  * @param indices The set of given indices, the resulting indices will not contain any of these indices, can contain indices with range [0, maximalIndex]
288  * @param numberElements The number of possible elements defining the entire range of possible indices: [0, numberElements)
289  * @tparam TIndex Data type of the index elements
290  */
291  template <typename TIndex>
292  static std::unordered_set<TIndex> invertedIndices(const std::unordered_set<TIndex>& indices, const size_t numberElements);
293 
294  /**
295  * Extracts the indices that are not given within a set indices.
296  * @param indices The set of given indices, the resulting indices will not contain any of these indices, can contain indices with range [0, maximalIndex]
297  * @param numberElements The number of possible elements defining the entire range of possible indices: [0, numberElements)
298  * @tparam TIndex Data type of the index elements
299  */
300  template <typename TIndex>
301  static std::set<TIndex> invertedIndices(const std::set<TIndex>& indices, const size_t numberElements);
302 
303  /**
304  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
305  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
306  * @param objects Entire set of objects from that a subset will be extracted
307  * @param numberObjects Number of given objects
308  * @param indices Indices defining the inverted subset to be extracted
309  * @return Resulting subset of the given objects
310  * @tparam TIndex Data type of the index elements
311  * @tparam T Data type of the objects
312  */
313  template <typename TIndex, typename T>
314  static inline std::vector<T> invertedSubset(const T* objects, const size_t numberObjects, const std::unordered_set<TIndex>& indices);
315 
316  /**
317  * Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not used.
318  * Beware: No range check is done! Thus, each index must not exceed the number of given objects.<br>
319  * @param objects Entire set of objects from that a subset will be extracted
320  * @param numberObjects Number of given objects
321  * @param indices Indices defining the inverted subset to be extracted
322  * @return Resulting subset of the given objects
323  * @tparam TIndex Data type of the index elements
324  * @tparam T Data type of the objects
325  */
326  template <typename TIndex, typename T>
327  static inline std::vector<T> invertedSubset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices);
328 
329  /**
330  * Converts object indices to an uint8_t vector holding statements for each object.
331  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
332  * @param numberObjects Number of objects that can be addressed by the indices
333  * @return Resulting boolean statements
334  * @tparam TIndex Data type of the index elements
335  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
336  */
337  template <typename TIndex, uint8_t tValue>
338  static inline std::vector<uint8_t> indices2statements(const std::vector<TIndex>& indices, const size_t numberObjects);
339 
340  /**
341  * Converts object indices to an uint8_t vector holding statements for each object.
342  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
343  * @param numberObjects Number of objects that can be addressed by the indices
344  * @return Resulting boolean statements
345  * @tparam TIndex Data type of the index elements
346  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
347  */
348  template <typename TIndex, uint8_t tValue>
349  static inline std::vector<uint8_t> indices2statements(const std::set<TIndex>& indices, const size_t numberObjects);
350 
351  /**
352  * Converts object indices to an uint8_t vector holding statements for each object.
353  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
354  * @param numberObjects Number of objects that can be addressed by the indices
355  * @return Resulting boolean statements
356  * @tparam TIndex Data type of the index elements
357  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
358  */
359  template <typename TIndex, uint8_t tValue>
360  static inline std::vector<uint8_t> indices2statements(const std::unordered_set<TIndex>& indices, const size_t numberObjects);
361 
362  /**
363  * Converts object indices to an uint8_t vector holding statements for each object.
364  * @param indices Indices defining the subset of the objects, with range [0, numberObjects)
365  * @param numberIndices Number of provided indices
366  * @param numberObjects Number of objects that can be addressed by the indices
367  * @return Resulting boolean statements
368  * @tparam TIndex Data type of the index elements
369  * @tparam tValue Value for objects that are defined in the indices, the inverse value is applied otherwise
370  */
371  template <typename TIndex, uint8_t tValue>
372  static inline std::vector<uint8_t> indices2statements(const TIndex* indices, const size_t numberIndices, const size_t numberObjects);
373 
374  /**
375  * Converts an uint8_t vector holding statements for each object into object indices.
376  * @param statements Boolean statement for each object
377  * @return Resulting object indices
378  * @tparam TIndex Data type of the index elements
379  * @tparam tValue Value for objects that will be defined in the indices
380  */
381  template <typename TIndex, uint8_t tValue>
382  static inline std::vector<TIndex> statements2indices(const std::vector<uint8_t>& statements);
383 
384  /**
385  * Converts an uint8_t vector holding statements for each object into object indices.
386  * @param statements Boolean statement for each object
387  * @param numberStatements Number of statements
388  * @return Resulting object indices
389  * @tparam TIndex Data type of the index elements
390  * @tparam tValue Value for objects that will be defined in the indices
391  */
392  template <typename TIndex, uint8_t tValue>
393  static inline std::vector<TIndex> statements2indices(const uint8_t* statements, const size_t numberStatements);
394 
395  /**
396  * Determines corresponding element pairs from two sets of element maps.
397  * Two elements correspond with each other if they have the same key.
398  * @param elementMapA The first map of elements
399  * @param elementMapB The second map of elements
400  * @param elementsA The resulting elements from the first map which have a corresponding element in the second map
401  * @param elementsB The resulting elements from the second map which have a corresponding element in the first map
402  * @tparam TKey The data type of each key
403  * @tparam TElement The data type of each element
404  */
405  template <typename TKey, typename TElement>
406  static void correspondingElements(const std::map<TKey, TElement>& elementMapA, const std::map<TKey, TElement>& elementMapB, std::vector<TElement>& elementsA, std::vector<TElement>& elementsB);
407 
408  /**
409  * Determines whether two (ordered) sets have at least one intersecting element.
410  * Both input sets must be in ascending order.
411  * @param firstA The iterator to the first element in the first set
412  * @param endA The iterator to the (exclusive) element after the last element in the first set
413  * @param firstB The iterator to the first element in the second set
414  * @param endB The iterator to the (exclusive) element after the last element in the second set
415  * @return True, if so
416  */
417  template <typename TIterator>
418  static bool hasIntersectingElement(const TIterator& firstA, const TIterator& endA, const TIterator& firstB, const TIterator& endB);
419 
420  /**
421  * Determines whether two (ordered) sets have at least one intersecting element.
422  * @param setA The first set to check, can be empty
423  * @param setB The second set to check, can be empty
424  * @return True, if so
425  */
426  template <typename T>
427  static inline bool hasIntersectingElement(const std::set<T>& setA, const std::set<T>& setB);
428 
429  /**
430  * Determines whether two ordered vectors have at least one intersecting element.
431  * @param sortedA The first vector to check, can be empty
432  * @param sortedB The second vector to check, can be empty
433  * @return True, if so
434  */
435  template <typename T>
436  static inline bool hasIntersectingElement(const std::vector<T>& sortedA, const std::vector<T>& sortedB);
437 };
438 
439 template <typename TIndex>
440 template <typename T>
441 inline std::vector<T> Subset::InternalSubset<TIndex>::subset(const std::vector<T>& objects, const std::vector<TIndex>& indices)
442 {
443  std::vector<T> result;
444  result.reserve(indices.size());
445 
446  for (const TIndex& index : indices)
447  {
448  ocean_assert(size_t(index) < objects.size());
449  result.push_back(objects[size_t(index)]);
450  }
451 
452  return result;
453 }
454 
455 template <>
456 template <typename T>
457 inline std::vector<T> Subset::InternalSubset<uint8_t>::subset(const std::vector<T>& objects, const std::vector<uint8_t>& indices)
458 {
459  std::vector<T> result;
460  result.reserve(indices.size());
461 
462  typename std::vector<T>::const_iterator iObject = objects.begin();
463 
464  for (const uint8_t index : indices)
465  {
466  if (index != 0u)
467  {
468  result.push_back(*iObject);
469  }
470 
471  ++iObject;
472  }
473 
474  return result;
475 }
476 
477 template <typename TIndex>
478 template <typename T>
479 inline std::vector<T> Subset::InternalSubset<TIndex>::subset(const std::vector<T>& objects, const std::set<TIndex>& indices)
480 {
481  std::vector<T> result;
482  result.reserve(indices.size());
483 
484  for (typename std::set<TIndex>::const_iterator i = indices.begin(); i != indices.end(); ++i)
485  {
486  ocean_assert(*i < objects.size());
487  result.push_back(objects[size_t(*i)]);
488  }
489 
490  return result;
491 }
492 
493 template <typename TIndex>
494 template <typename T>
495 inline std::vector<T> Subset::InternalSubset<TIndex>::invertedSubset(const std::vector<T>& objects, const std::unordered_set<TIndex>& indices)
496 {
497  ocean_assert(objects.size() >= indices.size());
498  ocean_assert((unsigned long long)(objects.size()) < (unsigned long long)(std::numeric_limits<TIndex>::max()));
499 
500  if (objects.size() == indices.size())
501  {
502 #ifdef OCEAN_DEBUG
503  for (const TIndex& index : indices)
504  {
505  ocean_assert(index < objects.size());
506  }
507 #endif
508 
509  return std::vector<T>();
510  }
511 
512  std::vector<T> result;
513  result.reserve(objects.size() - indices.size());
514 
515  for (size_t n = 0u; n < objects.size(); ++n)
516  {
517  if (indices.find(TIndex(n)) == indices.cend())
518  {
519  result.push_back(objects[n]);
520  }
521  }
522 
523  return result;
524 }
525 
526 template <typename TIndex>
527 template <typename T>
528 inline std::vector<T> Subset::InternalSubset<TIndex>::invertedSubset(const std::vector<T>& objects, const std::set<TIndex>& indices)
529 {
530  ocean_assert(objects.size() >= indices.size());
531  ocean_assert((unsigned long long)(objects.size()) < (unsigned long long)(std::numeric_limits<TIndex>::max()));
532 
533  if (objects.size() == indices.size())
534  {
535 #ifdef OCEAN_DEBUG
536  for (const TIndex& index : indices)
537  {
538  ocean_assert(index < objects.size());
539  }
540 #endif
541 
542  return std::vector<T>();
543  }
544 
545  std::vector<T> result;
546  result.reserve(objects.size() - indices.size());
547 
548  for (size_t n = 0u; n < objects.size(); ++n)
549  {
550  if (indices.find(TIndex(n)) == indices.cend())
551  {
552  result.push_back(objects[n]);
553  }
554  }
555 
556  return result;
557 }
558 
559 template <typename TIndex>
560 template <typename T>
561 inline std::vector<T> Subset::InternalSubset<TIndex>::subset(const T* objects, const size_t numberObjects, const TIndex* indices, const size_t numberIndices)
562 {
563  std::vector<T> result;
564  result.reserve(numberIndices);
565 
566  for (size_t n = 0; n < numberIndices; ++n)
567  {
568  ocean_assert_and_suppress_unused(indices[n] < numberObjects, numberObjects);
569 
570  result.push_back(objects[indices[n]]);
571  }
572 
573  return result;
574 }
575 
576 template <>
577 template <typename T>
578 inline std::vector<T> Subset::InternalSubset<uint8_t>::subset(const T* objects, const size_t numberObjects, const uint8_t* indices, const size_t numberIndices)
579 {
580  ocean_assert_and_suppress_unused(numberIndices <= numberObjects, numberObjects);
581 
582  std::vector<T> result;
583  result.reserve(numberIndices);
584 
585  for (size_t n = 0; n < numberIndices; ++n)
586  {
587  if (indices[n] != 0u)
588  {
589  result.push_back(objects[n]);
590  }
591  }
592 
593  return result;
594 }
595 
596 template <typename TIndex>
597 template <typename T>
598 inline std::vector<T> Subset::InternalSubset<TIndex>::subset(const T* objects, const size_t numberObjects, const std::vector<TIndex>& indices)
599 {
600  return subset(objects, numberObjects, indices.data(), indices.size());
601 }
602 
603 template <typename TIndex>
604 template <typename T>
605 inline std::vector<T> Subset::InternalSubset<TIndex>::subset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices)
606 {
607  std::vector<T> result;
608  result.reserve(indices.size());
609 
610  for (const TIndex& index : indices)
611  {
612  ocean_assert_and_suppress_unused(index < numberObjects, numberObjects);
613 
614  result.push_back(objects[index]);
615  }
616 
617  return result;
618 }
619 
620 template <typename TIndex>
621 template <typename T>
622 inline std::vector<T> Subset::InternalSubset<TIndex>::invertedSubset(const T* objects, const size_t numberObjects, const std::unordered_set<TIndex>& indices)
623 {
624  ocean_assert(numberObjects >= indices.size());
625  ocean_assert((unsigned long long)(numberObjects) < (unsigned long long)(std::numeric_limits<TIndex>::max()));
626 
627  if (numberObjects == indices.size())
628  {
629 #ifdef OCEAN_DEBUG
630  for (const TIndex& index : indices)
631  {
632  ocean_assert(indices < numberObjects);
633  }
634 #endif
635 
636  return std::vector<T>();
637  }
638 
639  std::vector<T> result;
640  result.reserve(numberObjects - indices.size());
641 
642  for (size_t n = 0; n < numberObjects; ++n)
643  {
644  if (indices.find(TIndex(n)) == indices.cend())
645  {
646  result.push_back(objects[n]);
647  }
648  }
649 
650  return result;
651 }
652 
653 template <typename TIndex>
654 template <typename T>
655 inline std::vector<T> Subset::InternalSubset<TIndex>::invertedSubset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices)
656 {
657  ocean_assert(numberObjects >= indices.size());
658  ocean_assert((unsigned long long)(numberObjects) < (unsigned long long)(std::numeric_limits<TIndex>::max()));
659 
660  if (numberObjects == indices.size())
661  {
662 #ifdef OCEAN_DEBUG
663  for (const TIndex& index : indices)
664  {
665  ocean_assert(index < numberObjects);
666  }
667 #endif
668 
669  return std::vector<T>();
670  }
671 
672  std::vector<T> result;
673  result.reserve(numberObjects - indices.size());
674 
675  for (size_t n = 0; n < numberObjects; ++n)
676  {
677  if (indices.find(TIndex(n)) == indices.cend())
678  {
679  result.push_back(objects[n]);
680  }
681  }
682 
683  return result;
684 }
685 
686 template <typename TIndex>
687 template <typename TContainer, uint8_t tValue>
688 inline std::vector<uint8_t> Subset::InternalSubset<TIndex>::indices2statements(const TContainer& indices, const size_t numberObjects)
689 {
690  std::vector<uint8_t> result(numberObjects, !tValue);
691 
692  for (const TIndex& index : indices)
693  {
694  ocean_assert(index < result.size());
695  result[index] = tValue;
696  }
697 
698  return result;
699 }
700 
701 template <typename TIndex>
702 template <uint8_t tValue>
703 inline std::vector<uint8_t> Subset::InternalSubset<TIndex>::indices2statements(const TIndex* indices, const size_t numberIndices, const size_t numberObjects)
704 {
705  std::vector<uint8_t> result(numberObjects, !tValue);
706 
707  for (size_t n = 0; n < numberIndices; ++n)
708  {
709  ocean_assert(indices[n] < result.size());
710  result[indices[n]] = tValue;
711  }
712 
713  return result;
714 }
715 
716 template <typename TIndex>
717 template <uint8_t tValue>
718 inline std::vector<TIndex> Subset::InternalSubset<TIndex>::statements2indices(const std::vector<uint8_t>& statements)
719 {
720  std::vector<TIndex> result;
721 
722  for (size_t n = 0; n < statements.size(); ++n)
723  {
724  if (statements[n] == tValue)
725  {
726  result.push_back(TIndex(n));
727  }
728  }
729 
730  return result;
731 }
732 
733 template <typename TIndex>
734 template <uint8_t tValue>
735 inline std::vector<TIndex> Subset::InternalSubset<TIndex>::statements2indices(const uint8_t* statements, const size_t numberStatements)
736 {
737  std::vector<TIndex> result;
738 
739  for (size_t n = 0; n < numberStatements; ++n)
740  {
741  if (statements[n] == tValue)
742  {
743  result.push_back(TIndex(n));
744  }
745  }
746 
747  return result;
748 }
749 
750 template <typename TIndex, typename T>
751 inline std::vector<T> Subset::subset(const std::vector<T>& objects, const std::vector<TIndex>& indices)
752 {
753  return InternalSubset<TIndex>::template subset<T>(objects, indices);
754 }
755 
756 template <typename TIndex, typename T>
757 inline std::vector<T> Subset::subset(const std::vector<T>& objects, const std::set<TIndex>& indices)
758 {
759  return InternalSubset<TIndex>::template subset<T>(objects, indices);
760 }
761 
762 template <typename TIndex>
763 std::vector<TIndex> Subset::invertedIndices(const std::vector<TIndex>& indices, const size_t numberElements)
764 {
765  ocean_assert(indices.size() <= TIndex(numberElements));
766 
767  if (indices.size() == numberElements)
768  {
769 #ifdef OCEAN_DEBUG
770  const std::unordered_set<TIndex> indexSet(indices.begin(), indices.end());
771  ocean_assert(indexSet.size() == indices.size());
772 
773  for (size_t n = 0; n < numberElements; ++n)
774  {
775  ocean_assert(indexSet.find(TIndex(n)) != indexSet.cend());
776  }
777 #endif
778 
779  return std::vector<TIndex>();
780  }
781 
782  const std::unordered_set<TIndex> indexSet(indices.begin(), indices.end());
783  ocean_assert(indexSet.size() == indices.size());
784 
785  std::vector<TIndex> result;
786  result.reserve(numberElements - indices.size());
787 
788  for (TIndex i = TIndex(0); i < TIndex(numberElements); ++i)
789  {
790  if (indexSet.find(i) == indexSet.cend())
791  {
792  result.push_back(i);
793  }
794  }
795 
796  return result;
797 }
798 
799 template <typename TIndex>
800 std::unordered_set<TIndex> Subset::invertedIndices(const std::unordered_set<TIndex>& indices, const size_t numberElements)
801 {
802  ocean_assert(indices.size() <= TIndex(numberElements));
803 
804  if (indices.size() == numberElements)
805  {
806 #ifdef OCEAN_DEBUG
807  for (size_t n = 0; n < numberElements; ++n)
808  {
809  ocean_assert(indices.find(TIndex(n)) != indices.end());
810  }
811 #endif
812 
813  return std::unordered_set<TIndex>();
814  }
815 
816  std::unordered_set<TIndex> result;
817  result.reserve(numberElements - indices.size());
818 
819  for (TIndex i = TIndex(0); i < TIndex(numberElements); ++i)
820  {
821  if (indices.find(i) == indices.cend())
822  {
823  result.emplace(i);
824  }
825  }
826 
827  return result;
828 }
829 
830 template <typename TIndex>
831 std::set<TIndex> Subset::invertedIndices(const std::set<TIndex>& indices, const size_t numberElements)
832 {
833  ocean_assert(indices.size() <= TIndex(numberElements));
834 
835  if (indices.size() == numberElements)
836  {
837 #ifdef OCEAN_DEBUG
838  for (size_t n = 0; n < numberElements; ++n)
839  {
840  ocean_assert(indices.find(TIndex(n)) != indices.end());
841  }
842 #endif
843 
844  return std::set<TIndex>();
845  }
846 
847  std::set<TIndex> result;
848 
849  for (TIndex i = TIndex(0); i < TIndex(numberElements); ++i)
850  {
851  if (indices.find(i) == indices.cend())
852  {
853  result.insert(i);
854  }
855  }
856 
857  return result;
858 }
859 
860 template <typename TIndex, typename T>
861 inline std::vector<T> Subset::invertedSubset(const std::vector<T>& objects, const std::unordered_set<TIndex>& indices)
862 {
863  return InternalSubset<TIndex>::template invertedSubset<T>(objects, indices);
864 }
865 
866 template <typename TIndex, typename T>
867 inline std::vector<T> Subset::invertedSubset(const std::vector<T>& objects, const std::set<TIndex>& indices)
868 {
869  return InternalSubset<TIndex>::template invertedSubset<T>(objects, indices);
870 }
871 
872 template <typename TIndex, typename T>
873 inline std::vector<T> Subset::subset(const T* objects, const size_t numberObjects, const TIndex* indices, const size_t numberIndices)
874 {
875  return InternalSubset<TIndex>::template subset<T>(objects, numberObjects, indices, numberIndices);
876 }
877 
878 template <typename TIndex, typename T>
879 inline std::vector<T> Subset::subset(const T* objects, const size_t numberObjects, const std::vector<TIndex>& indices)
880 {
881  return InternalSubset<TIndex>::template subset<T>(objects, numberObjects, indices);
882 }
883 
884 template <typename TIndex, typename T>
885 inline std::vector<T> Subset::subset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices)
886 {
887  return InternalSubset<TIndex>::template subset<T>(objects, numberObjects, indices);
888 }
889 
890 template <typename TIndex, typename T>
891 inline std::vector<T> Subset::invertedSubset(const T* objects, const size_t numberObjects, const std::unordered_set<TIndex>& indices)
892 {
893  return InternalSubset<TIndex>::template invertedSubset<T>(objects, numberObjects, indices);
894 }
895 
896 template <typename TIndex, typename T>
897 inline std::vector<T> Subset::invertedSubset(const T* objects, const size_t numberObjects, const std::set<TIndex>& indices)
898 {
899  return InternalSubset<TIndex>::template invertedSubset<T>(objects, numberObjects, indices);
900 }
901 
902 template <typename TIndex, uint8_t tValue>
903 inline std::vector<uint8_t> Subset::indices2statements(const std::vector<TIndex>& indices, const size_t numberObjects)
904 {
905  return InternalSubset<TIndex>::template indices2statements<std::vector<TIndex>, tValue>(indices, numberObjects);
906 }
907 
908 template <typename TIndex, uint8_t tValue>
909 inline std::vector<uint8_t> Subset::indices2statements(const std::unordered_set<TIndex>& indices, const size_t numberObjects)
910 {
911  return InternalSubset<TIndex>::template indices2statements<std::unordered_set<TIndex>, tValue>(indices, numberObjects);
912 }
913 
914 template <typename TIndex, uint8_t tValue>
915 inline std::vector<uint8_t> Subset::indices2statements(const std::set<TIndex>& indices, const size_t numberObjects)
916 {
917  return InternalSubset<TIndex>::template indices2statements<std::set<TIndex>, tValue>(indices, numberObjects);
918 }
919 
920 template <typename TIndex, uint8_t tValue>
921 inline std::vector<uint8_t> Subset::indices2statements(const TIndex* indices, const size_t numberIndices, const size_t numberObjects)
922 {
923  return InternalSubset<TIndex>::template indices2statements<tValue>(indices, numberIndices, numberObjects);
924 }
925 
926 template <typename TIndex, uint8_t tValue>
927 inline std::vector<TIndex> Subset::statements2indices(const std::vector<uint8_t>& statements)
928 {
929  return InternalSubset<TIndex>::template statements2indices<tValue>(statements);
930 }
931 
932 template <typename TIndex, uint8_t tValue>
933 inline std::vector<TIndex> Subset::statements2indices(const uint8_t* statements, const size_t numberStatements)
934 {
935  return InternalSubset<TIndex>::template statements2indices<tValue>(statements, numberStatements);
936 }
937 
938 template <typename TKey, typename TElement>
939 void Subset::correspondingElements(const std::map<TKey, TElement>& elementMapA, const std::map<TKey, TElement>& elementMapB, std::vector<TElement>& elementsA, std::vector<TElement>& elementsB)
940 {
941  elementsA.clear();
942  elementsB.clear();
943 
944  // we expect that the map entries are sorted based on their keys
945  ocean_assert(elementMapA.size() < 2 || elementMapA.cbegin()->first < elementMapA.crbegin()->first);
946  ocean_assert(elementMapB.size() < 2 || elementMapB.cbegin()->first < elementMapB.crbegin()->first);
947 
948  typename std::map<TKey, TElement>::const_iterator iA = elementMapA.cbegin();
949  typename std::map<TKey, TElement>::const_iterator iB = elementMapB.cbegin();
950 
951  while (iA != elementMapA.cend() && iB != elementMapB.cend())
952  {
953  // let's find elements with identical keys
954 
955  if (iA->first > iB->first)
956  {
957  ++iB;
958  }
959  else if (iA->first < iB->first)
960  {
961  ++iA;
962  }
963  else
964  {
965  ocean_assert(iA->first == iB->first);
966 
967  elementsA.emplace_back(iA->second);
968  elementsB.emplace_back(iB->second);
969 
970  ++iA;
971  ++iB;
972  }
973  }
974 }
975 
976 template <typename TIterator>
977 bool Subset::hasIntersectingElement(const TIterator& firstA, const TIterator& endA, const TIterator& firstB, const TIterator& endB)
978 {
979  if (firstA == endA || firstB == endB)
980  {
981  return false;
982  }
983 
984 #ifdef OCEAN_DEBUG
985  TIterator debugLeftA = firstA;
986  TIterator debugRightA = firstA;
987  ++debugRightA;
988 
989  TIterator debugLeftB = firstB;
990  TIterator debugRightB = firstB;
991  ++debugRightB;
992 
993  while (debugRightA != endA && debugRightB != endB)
994  {
995  ocean_assert(*debugLeftA++ <= *debugRightA++);
996  ocean_assert(*debugLeftB++ <= *debugRightB++);
997  }
998 #endif
999 
1000  TIterator lastA = endA;
1001  TIterator lastB = endB;
1002 
1003  if (*(--lastA) < *firstB || *(--lastB) < *firstA)
1004  {
1005  return false;
1006  }
1007 
1008  TIterator iA = firstA;
1009  TIterator iB = firstB;
1010 
1011  while (iA != endA && iB != endB)
1012  {
1013  if (*iA == *iB)
1014  {
1015  return true;
1016  }
1017 
1018  if (*iA < *iB)
1019  {
1020  ++iA;
1021  }
1022  else
1023  {
1024  ocean_assert(*iA > *iB);
1025  ++iB;
1026  }
1027  }
1028 
1029  return false;
1030 }
1031 
1032 template <typename T>
1033 bool Subset::hasIntersectingElement(const std::set<T>& setA, const std::set<T>& setB)
1034 {
1035  return hasIntersectingElement(setA.cbegin(), setA.cend(), setB.cbegin(), setB.cend());
1036 }
1037 
1038 template <typename T>
1039 bool Subset::hasIntersectingElement(const std::vector<T>& sortedA, const std::vector<T>& sortedB)
1040 {
1041  return hasIntersectingElement(sortedA.cbegin(), sortedA.cend(), sortedB.cbegin(), sortedB.cend());
1042 }
1043 
1044 }
1045 
1046 #endif // META_OCEAN_BASE_SUBSET_H
This helper class implements a subset functions.
Definition: Subset.h:30
static std::vector< T > invertedSubset(const std::vector< T > &objects, const std::unordered_set< TIndex > &indices)
Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not use...
Definition: Subset.h:495
static std::vector< uint8_t > indices2statements(const TContainer &indices, const size_t numberObjects)
Converts object indices to an uint8_t vector holding statements for each object.
Definition: Subset.h:688
static std::vector< TIndex > statements2indices(const std::vector< uint8_t > &statements)
Converts an uint8_t vector holding statements for each object into object indices.
Definition: Subset.h:718
static std::vector< T > subset(const std::vector< T > &objects, const std::vector< TIndex > &indices)
Extracts a subset of a given set of objects by usage of an index vector holding the indices of all ob...
Definition: Subset.h:441
This class implements subset functions.
Definition: Subset.h:21
static std::vector< uint8_t > indices2statements(const std::vector< TIndex > &indices, const size_t numberObjects)
Converts object indices to an uint8_t vector holding statements for each object.
Definition: Subset.h:903
static bool hasIntersectingElement(const TIterator &firstA, const TIterator &endA, const TIterator &firstB, const TIterator &endB)
Determines whether two (ordered) sets have at least one intersecting element.
Definition: Subset.h:977
static std::vector< T > subset(const std::vector< T > &objects, const std::vector< TIndex > &indices)
Extracts a subset of a given set of objects by usage of an index vector holding the indices of all ob...
Definition: Subset.h:751
static std::vector< TIndex > invertedIndices(const std::vector< TIndex > &indices, const size_t numberElements)
Extracts the indices that are not given within a set indices.
Definition: Subset.h:763
static void correspondingElements(const std::map< TKey, TElement > &elementMapA, const std::map< TKey, TElement > &elementMapB, std::vector< TElement > &elementsA, std::vector< TElement > &elementsB)
Determines corresponding element pairs from two sets of element maps.
Definition: Subset.h:939
static std::vector< TIndex > statements2indices(const std::vector< uint8_t > &statements)
Converts an uint8_t vector holding statements for each object into object indices.
Definition: Subset.h:927
static std::vector< T > invertedSubset(const std::vector< T > &objects, const std::unordered_set< TIndex > &indices)
Extracts a subset of a given set of objects by usage of a set of indices of all objects to be not use...
Definition: Subset.h:861
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15