OGS
Algorithm.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <optional>
16 #include <string>
17 #include <typeindex>
18 #include <typeinfo>
19 
20 #include "Error.h"
21 
22 namespace BaseLib
23 {
32 template <typename T>
33 std::vector<T> excludeObjectCopy(
34  std::vector<T> const& src_vec,
35  std::vector<std::size_t> const& exclude_positions)
36 {
37  std::vector<T> dest_vec;
38  if (exclude_positions.empty())
39  {
40  dest_vec = src_vec;
41  return dest_vec;
42  }
43 
44  assert(exclude_positions.back() < src_vec.size());
45 
46  std::copy_n(src_vec.cbegin(), exclude_positions[0],
47  std::back_inserter(dest_vec));
48  for (std::size_t i = 1; i < exclude_positions.size(); ++i)
49  {
50  std::copy_n(src_vec.cbegin() + exclude_positions[i - 1] + 1,
51  exclude_positions[i] - (exclude_positions[i - 1] + 1),
52  std::back_inserter(dest_vec));
53  }
54  std::copy(src_vec.cbegin() + exclude_positions.back() + 1, src_vec.cend(),
55  std::back_inserter(dest_vec));
56 
57  return dest_vec;
58 }
59 
60 template <typename T>
61 void excludeObjectCopy(std::vector<T> const& src_vec,
62  std::vector<std::size_t> const& exclude_positions,
63  std::vector<T>& dest_vec)
64 {
65  dest_vec = excludeObjectCopy(src_vec, exclude_positions);
66 }
67 
68 template <typename InputIt, typename Predicate>
69 typename std::iterator_traits<InputIt>::reference findElementOrError(
70  InputIt begin, InputIt end, Predicate predicate,
71  std::string const& error = "")
72 {
73  auto it = std::find_if(begin, end, predicate);
74  if (it == end)
75  {
76  OGS_FATAL("Element not found in the input range; {:s}", error);
77  }
78  return *it;
79 }
80 
87 template <typename Map, typename Key, typename Value>
88 void insertIfTypeIndexKeyUniqueElseError(Map& map, Key const& key,
89  Value&& value,
90  std::string const& error_message)
91 {
92  auto const inserted = map.emplace(key, std::forward<Value>(value));
93  if (!inserted.second)
94  { // insertion failed, i.e., key already exists
95  OGS_FATAL("{:s} Key `{:s}' already exists.", error_message,
96  std::to_string(key.hash_code()));
97  }
98 }
99 
105 template <typename Map, typename Key, typename Value>
106 void insertIfKeyUniqueElseError(Map& map, Key const& key, Value&& value,
107  std::string const& error_message)
108 {
109  auto const inserted = map.emplace(key, std::forward<Value>(value));
110  if (!inserted.second)
111  { // insertion failed, i.e., key already exists
112  OGS_FATAL("{:s} Key `{:s}' already exists.", error_message, key);
113  }
114 }
115 
120 template <typename Map, typename Key, typename Value>
121 void insertIfKeyValueUniqueElseError(Map& map, Key const& key, Value&& value,
122  std::string const& error_message)
123 {
124  auto value_compare = [&value](typename Map::value_type const& elem)
125  { return value == elem.second; };
126 
127  if (std::find_if(map.cbegin(), map.cend(), value_compare) != map.cend())
128  {
129  OGS_FATAL("{:s} Value `{:s}' already exists.", error_message,
130  std::to_string(value));
131  }
132 
133  auto const inserted = map.emplace(key, std::forward<Value>(value));
134  if (!inserted.second)
135  { // insertion failed, i.e., key already exists
136  OGS_FATAL("{:s} Key `{:s}' already exists.", error_message,
137  std::to_string(key));
138  }
139 }
140 
146 template <typename Map, typename Key>
147 typename Map::mapped_type& getOrError(Map& map, Key const& key,
148  std::string const& error_message)
149 {
150  auto it = map.find(key);
151  if (it == map.end())
152  {
153  if constexpr (std::is_convertible<Key, std::string>::value)
154  {
155  OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message, key);
156  }
157  else
158  {
159  OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message,
160  std::to_string(key));
161  }
162  }
163 
164  return it->second;
165 }
167 template <typename Map, typename Key>
168 typename Map::mapped_type const& getOrError(Map const& map, Key const& key,
169  std::string const& error_message)
170 {
171  auto it = map.find(key);
172  if (it == map.end())
173  {
174  if constexpr (std::is_convertible<Key, std::string>::value)
175  {
176  OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message, key);
177  }
178  else
179  {
180  OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message,
181  std::to_string(key));
182  }
183  }
184 
185  return it->second;
186 }
187 
191 template <typename Container, typename Predicate>
192 typename Container::value_type const& getIfOrError(
193  Container const& container,
194  Predicate&& predicate,
195  std::string const& error_message)
196 {
197  auto it = std::find_if(begin(container), end(container), predicate);
198  if (it == end(container))
199  {
200  OGS_FATAL("Could not find element matching the predicate: {:s}",
201  error_message);
202  }
203  return *it;
204 }
205 
208 template <typename T>
209 void makeVectorUnique(std::vector<T>& v)
210 {
211  std::sort(v.begin(), v.end());
212  auto it = std::unique(v.begin(), v.end());
213  v.erase(it, v.end());
214 }
215 
218 template <typename T, class Compare>
219 void makeVectorUnique(std::vector<T>& v, Compare comp)
220 {
221  std::sort(v.begin(), v.end(), comp);
222  auto it = std::unique(v.begin(), v.end());
223  v.erase(it, v.end());
224 }
225 
231 template <typename ValueType, typename IndexType>
232 void reorderVector(std::vector<ValueType>& v,
233  std::vector<IndexType> const& order)
234 {
235  std::vector<ValueType> temp_v(v.size());
236  temp_v.swap(v);
237 
238  for (std::size_t i = 0; i < order.size(); i++)
239  {
240  std::swap(v[i], temp_v[order[i]]);
241  }
242 }
243 
244 template <typename Container>
245 void uniquePushBack(Container& container,
246  typename Container::value_type const& element)
247 {
248  if (std::find(container.begin(), container.end(), element) ==
249  container.end())
250  {
251  container.push_back(element);
252  }
253 }
254 
255 template <typename Container>
256 bool contains(Container const& container,
257  typename Container::value_type const& element)
258 {
259  return std::find(container.begin(), container.end(), element) !=
260  container.end();
261 }
262 
263 template <typename Container, typename Predicate>
264 bool containsIf(Container const& container, Predicate&& predicate)
265 {
266  return std::find_if(container.begin(), container.end(), predicate) !=
267  container.end();
268 }
269 
270 template <typename Container>
271 std::optional<typename Container::value_type> findFirstNotEqualElement(
272  Container const& container, typename Container::value_type const& element)
273 {
274  auto const it =
275  std::find_if_not(container.begin(), container.end(),
276  [&element](typename Container::value_type const& e)
277  { return e == element; });
278  return it == container.end() ? std::nullopt : std::make_optional(*it);
279 }
280 
286 template <typename Container>
287 std::size_t findIndex(Container const& container,
288  typename Container::value_type const& element)
289 {
290  auto const it = std::find(container.begin(), container.end(), element);
291  if (it == container.end())
292  {
293  return std::numeric_limits<std::size_t>::max();
294  }
295  return std::distance(container.begin(), it);
296 }
297 
299 template <typename T1, typename T2>
300 void cleanupVectorElements(std::vector<T1*> const& items,
301  std::vector<T2*> const& dependent_items)
302 {
303  for (auto dependent_item : dependent_items)
304  {
305  delete dependent_item;
306  }
307  for (auto item : items)
308  {
309  delete item;
310  }
311 }
312 
313 } // namespace BaseLib
#define OGS_FATAL(...)
Definition: Error.h:26
std::optional< typename Container::value_type > findFirstNotEqualElement(Container const &container, typename Container::value_type const &element)
Definition: Algorithm.h:271
Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
Definition: Algorithm.h:147
std::size_t findIndex(Container const &container, typename Container::value_type const &element)
Definition: Algorithm.h:287
bool contains(Container const &container, typename Container::value_type const &element)
Definition: Algorithm.h:256
void insertIfKeyUniqueElseError(Map &map, Key const &key, Value &&value, std::string const &error_message)
Definition: Algorithm.h:106
bool containsIf(Container const &container, Predicate &&predicate)
Definition: Algorithm.h:264
void insertIfTypeIndexKeyUniqueElseError(Map &map, Key const &key, Value &&value, std::string const &error_message)
Definition: Algorithm.h:88
void uniquePushBack(Container &container, typename Container::value_type const &element)
Definition: Algorithm.h:245
void reorderVector(std::vector< ValueType > &v, std::vector< IndexType > const &order)
Definition: Algorithm.h:232
void insertIfKeyValueUniqueElseError(Map &map, Key const &key, Value &&value, std::string const &error_message)
Definition: Algorithm.h:121
std::vector< T > excludeObjectCopy(std::vector< T > const &src_vec, std::vector< std::size_t > const &exclude_positions)
Definition: Algorithm.h:33
void makeVectorUnique(std::vector< T > &v)
Definition: Algorithm.h:209
void cleanupVectorElements(std::vector< T1 * > const &items, std::vector< T2 * > const &dependent_items)
Definition: Algorithm.h:300
Container::value_type const & getIfOrError(Container const &container, Predicate &&predicate, std::string const &error_message)
Definition: Algorithm.h:192
std::iterator_traits< InputIt >::reference findElementOrError(InputIt begin, InputIt end, Predicate predicate, std::string const &error="")
Definition: Algorithm.h:69
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37