algorithm.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu)
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <algorithm>
27 #include <map>
28 #include <unordered_map>
29 #include <numeric>
30 #include <vector>
31 
33 
34 namespace armarx
35 {
36  /**
37  * @brief Uses the range of indices to copy values (accessed via src.at())from the given container into the output iterator.
38  *
39  * This function e.g. is useful if you have a map of joint values and need a specific subset 'idx' as vector of floats.
40  * \code
41  * std::vector<int> idx = {0,1,3};
42  *
43  * std::vector<long> srcV={0,10,20,30,40,50};
44  * std::vector<long> fromVec;
45  * copyValuesAt(srcV, idx.begin(), idx.end(), std::back_inserter(fromVec));
46  * //fromVec == {0, 10, 30}
47  *
48  * std::map<int, long> srcM={{0,0},{1,10},{2,20},{3,30},{4,40},{5,50}};
49  * std::vector<long> fromMap;
50  * copyValuesAt(srcM, idx.begin(), idx.end(), std::back_inserter(fromMap));
51  * //fromMap == {0, 10, 30}
52  * \endcode
53  */
54  template<class ContainerT, class IndexIteratorT, class OutputIteratorT, class IndexT = typename std::iterator_traits<IndexIteratorT>::value_type>
55  void copyValuesAt(const ContainerT& src, IndexIteratorT fst, IndexIteratorT lst, OutputIteratorT dest)
56  {
57  std::transform(fst, lst, dest, [&src](const IndexT & i)
58  {
59  return src.at(i);
60  });
61  }
62 
63  /**
64  * @brief Uses the container of indices to copy values (accessed via src.at())from the given container into the output iterator.
65  *
66  * This function e.g. is useful if you have a map of joint values and need a specific subset 'idx' as vector of floats.
67  * \code
68  * std::vector<int> idx = {0,1,3};
69  *
70  * std::vector<long> srcV={0,10,20,30,40,50};
71  * std::vector<long> fromVec;
72  * copyValuesAt(srcV, idx, std::back_inserter(fromVec));
73  * //fromVec == {0, 10, 30}
74  *
75  * std::map<int, long> srcM={{0,0},{1,10},{2,20},{3,30},{4,40},{5,50}};
76  * std::vector<long> fromMap;
77  * copyValuesAt(srcM, idx, std::back_inserter(fromMap));
78  * //fromMap == {0, 10, 30}
79  * \endcode
80  */
81  template<class ContainerT, class IndexContainerT, class OutputIteratorT, class IndexT = typename IndexContainerT::value_type>
82  void copyValuesAt(const ContainerT& src, const IndexContainerT& idx, OutputIteratorT dest)
83  {
84  copyValuesAt(src, idx.begin(), idx.end(), dest);
85  }
86 
87  /**
88  * @brief Uses the range of indices to copy values (accessed via src.at())from the given container into a vector and returns his vector.
89  *
90  * This function e.g. is useful if you have a map of joint values and need a specific subset 'idx' as vector of floats.
91  * \code
92  * std::vector<int> idx = {0,1,3};
93  *
94  * std::vector<long> srcV={0,10,20,30,40,50};
95  * std::vector<long> fromVec = copyValuesAt(srcV, idx.begin(), idx.end());
96  * //fromVec == {0, 10, 30}
97  *
98  * std::map<int, long> srcM={{0,0},{1,10},{2,20},{3,30},{4,40},{5,50}};
99  * std::vector<long> fromMap = copyValuesAt(srcM, idx.begin(), idx.end());
100  * //fromMap == {0, 10, 30}
101  * \endcode
102  */
103  template<class ContainerT, class IndexIteratorT, class IndexT = typename std::iterator_traits<IndexIteratorT>::value_type>
104  std::vector<typename ContainerT::value_type> copyValuesAt(const ContainerT& src, IndexIteratorT fst, IndexIteratorT lst)
105  {
106  std::vector<typename ContainerT::value_type> result;
107  result.reserve(std::distance(fst, lst));
108  copyValuesAt(src, std::move(fst), std::move(lst), std::back_inserter(result));
109  return result;
110  }
111 
112  /**
113  * @brief Uses the container of indices to copy values (accessed via src.at()) from the given container into a vector and returns his vector.
114  *
115  * This function e.g. is useful if you have a map of joint values and need a specific subset 'idx' as vector of floats.
116  * \code
117  * std::vector<int> idx = {0,1,3};
118  *
119  * std::vector<long> srcV={0,10,20,30,40,50};
120  * std::vector<long> fromVec = copyValuesAt(srcV, idx);
121  * //fromVec == {0, 10, 30}
122  *
123  * std::map<int, long> srcM={{0,0},{1,10},{2,20},{3,30},{4,40},{5,50}};
124  * std::vector<long> fromMap = copyValuesAt(srcM, idx);
125  * //fromMap == {0, 10, 30}
126  * \endcode
127  */
128  template<class ContainerT, class IndexContainerT, class IndexT = typename IndexContainerT::value_type>
129  std::vector<typename ContainerT::value_type> copyValuesAt(const ContainerT& src, const IndexContainerT& idx)
130  {
131  return copyValuesAt(src, idx.begin(), idx.end());
132  }
133 
134 
135  /**
136  * @brief This function takes a container (e.g. a vector) of unique elements and returns a map mapping the elements to their corresponding index
137  * @param Container of unique elements (needs index access via at)
138  * @return index map
139  */
140  template<class T, class MapType = std::unordered_map<typename T::value_type, typename T::size_type>>
141  MapType toIndexMap(const T& vec)
142  {
143  MapType result;
144  result.reserve(vec.size());
145  for (typename T::size_type i = 0; i < vec.size(); ++i)
146  {
147  auto emplacement = result.emplace(vec.at(i), i).second;
148  if (!emplacement)
149  {
150  throw std::invalid_argument {"The given container did not contain unique elements!"};
151  }
152  }
153  return result;
154  }
155 
156  template<class MapType, class OutputIteratorType>
157  void getMapKeys(const MapType& map, OutputIteratorType it)
158  {
159  for (const auto& e : map)
160  {
161  *it = e.first;
162  ++it;
163  }
164  }
165 
166  template<class MapType>
167  std::vector<typename MapType::key_type> getMapKeys(const MapType& map)
168  {
169  std::vector<typename MapType::key_type> result;
170  result.reserve(map.size());
171  getMapKeys(map, std::back_inserter(result));
172  return result;
173  }
174 
175  template<class MapType, class OutputIteratorType>
176  void getMapValues(const MapType& map, OutputIteratorType it)
177  {
178  for (const auto& e : map)
179  {
180  *it = e.second;
181  ++it;
182  }
183  }
184 
185  template<class MapType, template<class...> class ContainerT = std::vector>
186  ContainerT<typename MapType::mapped_type> getMapValues(const MapType& map)
187  {
188  ContainerT<typename MapType::mapped_type> result;
189  getMapValues(map, std::inserter(result, result.end()));
190  return result;
191  }
192 
193  template<class T>
194  T sign(T t)
195  {
196  return t < 0 ? -1 : 1;
197  }
198 
199  /**
200  * @brief Increment all given parameter using the pre-increment operator.
201  */
202  inline void incrementAll() {}
203  template<typename It0, typename ...It>
204  void incrementAll(It0& it0, It& ...it)
205  {
206  ++it0;
207  incrementAll(it...);
208  }
209 
210 
211  enum class MergeMapsMode
212  {
216  };
217 
218  /**
219  * Inserts and overwrites the values from oldMap with the values from newMap.
220  * Template parameter T needs to be a map-container value like std::map.
221  */
222  template <typename T>
223  void mergeMaps(T& oldMap, const T& newMap, MergeMapsMode mergeMode = MergeMapsMode::OverrideOldValues)
224  {
225  //we can't annotate fallthrough as ok (we need a newer compiler)
226 #pragma GCC diagnostic push
227 #if __GNUC__ > 4
228 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
229 #endif
230  switch (mergeMode)
231  {
233  for (auto& elem : newMap)
234  {
235  if (oldMap.count(elem.first))
236  {
237  throw std::invalid_argument {"mergeMaps: newMap would override values from oldMap"};
238  }
239  }
240  //all ok -> fall through
242  for (auto& elem : newMap)
243  {
244  oldMap[elem.first] = elem.second;
245  }
246  break;
248  for (auto& elem : newMap)
249  {
250  oldMap.emplace(elem);
251  }
252  break;
253  }
254 #pragma GCC diagnostic pop
255  }
256 
257  template <class MapInT, class TransformT, class MapOutT = MapInT>
258  void transformMapKeys(const MapInT& inMap, MapOutT& outMap, TransformT transform)
259  {
260  for (const auto& elem : inMap)
261  {
262  outMap[transform(elem.first)] = elem.second;
263  }
264  }
265 
266  template <class MapInT, class TransformT, class MapOutT = MapInT>
267  MapOutT transformMapKeys(const MapInT& inMap, TransformT transform)
268  {
269  MapOutT out;
270  transformMapKeys(inMap, out, transform);
271  return out;
272  }
273 
274  template <class KeyT, class ValT>
275  std::vector<KeyT> getIndices(const std::map<KeyT, ValT>& c)
276  {
277  return getMapKeys(c);
278  }
279 
280  template <class KeyT, class ValT>
281  std::vector<KeyT> getIndices(const std::unordered_map<KeyT, ValT>& c)
282  {
283  return getMapKeys(c);
284  }
285 
286  template <class ValT>
287  std::vector<std::size_t> getIndices(const std::vector<ValT>& c)
288  {
289  std::vector<std::size_t> r(c.size()); // don't use uniform initialization here!
290  std::iota(r.begin(), r.end(), 0);
291  return r;
292  }
293 
294  template <class ContainerType, class ElementType>
295  bool Contains(const ContainerType& container, const ElementType& searchElement)
296  {
297  return std::find(container.begin(), container.end(), searchElement) != container.end();
298  }
299 
300  /**
301  * Convenience function (with less typing) to transform a container of type InputT into the same container type of type OutputT.
302  *
303  * Example usage:
304  * <code>
305  * std::vector<int> values = {1,2,3};
306  * auto stringValues = transform(values, +[](const int& v)
307  * {
308  * return std::to_string(v);
309  * };
310  * // stringValues == {"1","2","3"}
311  * </code>
312  * \note Do not forget the + in front of the lambda!
313  */
314  template <class OutputT, class InputT, typename Alloc, template <class, class> class Container>
315  auto transform(const Container<InputT, Alloc>& in, OutputT(*func)(InputT const&))
316  -> Container<OutputT, typename std::allocator_traits<Alloc>::template rebind_alloc<OutputT> >
317  {
318  Container<OutputT, typename std::allocator_traits<Alloc>::template rebind_alloc<OutputT>> result;
319  result.reserve(in.size());
320  std::transform(in.begin(), in.end(), std::back_inserter(result), func);
321  return result;
322  }
323 }
324 namespace std
325 {
326  template<class T, class...Ts>
327  bool isfinite(const std::vector<T, Ts...>& v)
328  {
329  return std::all_of(v.begin(), v.end(), [](const T & t)
330  {
331  return isfinite(t);
332  });
333  }
334 }
armarx::toIndexMap
MapType toIndexMap(const T &vec)
This function takes a container (e.g.
Definition: algorithm.h:141
armarx::getMapValues
void getMapValues(const MapType &map, OutputIteratorType it)
Definition: algorithm.h:176
armarx::Contains
bool Contains(const ContainerType &container, const ElementType &searchElement)
Definition: algorithm.h:295
armarx::getIndices
std::vector< KeyT > getIndices(const std::map< KeyT, ValT > &c)
Definition: algorithm.h:275
armarx::MergeMapsMode::OverrideNoValues
@ OverrideNoValues
armarx::sign
T sign(T t)
Definition: algorithm.h:194
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::MergeMapsMode
MergeMapsMode
Definition: algorithm.h:211
armarx::MergeMapsMode::OverrideOldValues
@ OverrideOldValues
TemplateMetaProgramming.h
std::isfinite
bool isfinite(const std::vector< T, Ts... > &v)
Definition: algorithm.h:327
armarx::incrementAll
void incrementAll()
Increment all given parameter using the pre-increment operator.
Definition: algorithm.h:202
armarx::copyValuesAt
void copyValuesAt(const ContainerT &src, IndexIteratorT fst, IndexIteratorT lst, OutputIteratorT dest)
Uses the range of indices to copy values (accessed via src.at())from the given container into the out...
Definition: algorithm.h:55
armarx::ElementTypes::ElementType
ElementType
Definition: AbstractObjectSerializer.h:32
armarx::transformMapKeys
void transformMapKeys(const MapInT &inMap, MapOutT &outMap, TransformT transform)
Definition: algorithm.h:258
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
std
Definition: Application.h:66
armarx::MergeMapsMode::KeepOldValues
@ KeepOldValues
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:315
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::mergeMaps
void mergeMaps(T &oldMap, const T &newMap, MergeMapsMode mergeMode=MergeMapsMode::OverrideOldValues)
Inserts and overwrites the values from oldMap with the values from newMap.
Definition: algorithm.h:223
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
armarx::getMapKeys
void getMapKeys(const MapType &map, OutputIteratorType it)
Definition: algorithm.h:157
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28