AutoPas  3.0.0
Loading...
Searching...
No Matches
ArrayUtils.h
Go to the documentation of this file.
1
8#pragma once
9
10#include <array>
11#include <iomanip>
12#include <numeric>
13#include <set>
14#include <sstream>
15#include <vector>
16
18
19// specialize a type for containers of type array and vector for use with templated overloaded stream operator.
23namespace is_container_impl {
28template <typename T>
29struct is_container : std::false_type {};
35template <typename T, std::size_t N>
36struct is_container<std::array<T, N>> : std::true_type {};
37
42template <typename... Args>
43struct is_container<std::vector<Args...>> : std::true_type {};
44
49template <typename... Args>
50struct is_container<std::set<Args...>> : std::true_type {};
51
52} // namespace is_container_impl
53
61template <typename T>
63 static constexpr bool const value =
65};
66
80template <class output_t, class input_t, std::size_t SIZE>
81[[nodiscard]] constexpr std::array<output_t, SIZE> static_cast_copy_array(const std::array<input_t, SIZE> &a) {
82 std::array<output_t, SIZE> result{};
83 for (std::size_t d = 0; d < SIZE; ++d) {
84 result[d] = static_cast<output_t>(a[d]);
85 }
86 return result;
87}
88
101template <class Container, class Fun>
102void to_string(std::ostream &os, const Container &container, const std::string &delimiter,
103 const std::array<std::string, 2> &surround, Fun elemToString) {
104 auto it = std::cbegin(container);
105 const auto end = std::cend(container);
106 if (it == end) {
107 os << surround[0] << surround[1];
108 return;
109 }
110 os << surround[0] << elemToString(*it);
111 for (++it; it != end; ++it) {
112 os << delimiter << elemToString(*it);
113 }
114 os << surround[1];
115}
116
125template <class Container>
126void to_string(std::ostream &os, const Container &container, const std::string &delimiter = ", ",
127 const std::array<std::string, 2> &surround = {"[", "]"}) {
128 to_string(os, container, delimiter, surround, [](const auto &x) { return x; });
129}
130
143template <class Container, class Fun>
144[[nodiscard]] std::string to_string(const Container &container, const std::string &delimiter,
145 const std::array<std::string, 2> &surround, Fun elemToString) {
146 std::ostringstream strStream;
147 strStream << std::boolalpha;
148 to_string(strStream, container, delimiter, surround, elemToString);
149
150 return strStream.str();
151}
152
161template <class Container>
162[[nodiscard]] std::string to_string(const Container &container, const std::string &delimiter = ", ",
163 const std::array<std::string, 2> &surround = {"[", "]"}) {
164 return to_string(container, delimiter, surround, [](const auto &elem) { return elem; });
165}
166
179template <class Container>
180std::enable_if_t<autopas::utils::ArrayUtils::is_container<Container>::value, std::ostream &> operator<<(
181 std::ostream &os, const Container &container) {
182 const std::string &delimiter = ", ";
183 const std::array<std::string, 2> &surround = {"[", "]"};
184
185 to_string(os, container, delimiter, surround);
186
187 return os;
188}
189
199template <class OuterContainerT>
200void balanceVectors(OuterContainerT &vecvec) {
202 vecvec, [](auto &innerContainer) -> auto & { return innerContainer; });
203}
204
217template <class OuterContainerT, class F>
218void balanceVectors(OuterContainerT &vecvec, F innerContainerToVec) {
219 using InnerContainerT = typename OuterContainerT::value_type;
220 using ElemT = typename std::remove_reference_t<
221 std::invoke_result_t<decltype(innerContainerToVec), InnerContainerT &>>::value_type;
222 // calculate vecvec statistics
223 const auto vecvecSize = vecvec.size();
224 if (vecvecSize == 0) {
225 // nothing to do
226 return;
227 }
228 const size_t numElem = std::transform_reduce(vecvec.begin(), vecvec.end(), 0, std::plus<>(),
229 [&](auto &vec) { return innerContainerToVec(vec).size(); });
230 const auto targetSize = static_cast<long>(numElem / vecvecSize);
231 const auto remainder = numElem % vecvecSize;
232
233 std::vector<ElemT> tmpStorage;
234 // index of the first subvec that has too few elements
235 size_t firstTooFew = 0;
236 // repeat as long as there is something in the buffer but at least 2 iterations.
237 for (int pass = 0; pass == 0 or not tmpStorage.empty(); ++pass) {
238 // scan all subvecs that are not known to have the desired size
239 for (size_t i = firstTooFew; i < vecvecSize; ++i) {
240 auto &vec = innerContainerToVec(vecvec[i]);
241 const auto thisTargetSize = i < remainder ? targetSize + 1 : targetSize;
242 if (vec.size() > thisTargetSize) {
243 // move what is too much to tmpStorage
244 const auto startOfTooMuch = vec.begin() + thisTargetSize;
245 tmpStorage.insert(tmpStorage.end(), std::make_move_iterator(startOfTooMuch),
246 std::make_move_iterator(vec.end()));
247 vec.erase(startOfTooMuch, vec.end());
248 // if firstTooFew points here bump it, since this vector is now satisfied
249 if (firstTooFew == i) {
250 ++firstTooFew;
251 }
252 } else if (vec.size() < thisTargetSize) {
253 // fill too small vectors from storage
254 vec.reserve(thisTargetSize);
255 const long numMissing = thisTargetSize - vec.size();
256 const auto startOfInsertion =
257 tmpStorage.begin() + (std::max(0l, static_cast<long>(tmpStorage.size()) - numMissing));
258 vec.insert(vec.end(), std::make_move_iterator(startOfInsertion), std::make_move_iterator(tmpStorage.end()));
259 tmpStorage.erase(startOfInsertion, tmpStorage.end());
260
261 } else if (firstTooFew == i) {
262 // if firstTooFew points here bump it, since this vector is already satisfied
263 ++firstTooFew;
264 }
265 // after the first pass all excess elements are collected. So as soon as everything is distributed we are done.
266 if (pass > 0 and tmpStorage.empty()) {
267 break;
268 }
269 }
270 }
271}
272
273} // namespace autopas::utils::ArrayUtils
In this namespace some helper functions for std::array can be found.
Definition: namespaces.h:54
void balanceVectors(OuterContainerT &vecvec)
Given a collection of vectors, redistributes the elements of the vectors so they all have the same (o...
Definition: ArrayUtils.h:200
constexpr std::array< output_t, SIZE > static_cast_copy_array(const std::array< input_t, SIZE > &a)
Creates a new array by performing an element-wise static_cast<>.
Definition: ArrayUtils.h:81
void to_string(std::ostream &os, const Container &container, const std::string &delimiter, const std::array< std::string, 2 > &surround, Fun elemToString)
Generates a string representation of a container which fulfills the Container requirement (provide cb...
Definition: ArrayUtils.h:102
std::enable_if_t< autopas::utils::ArrayUtils::is_container< Container >::value, std::ostream & > operator<<(std::ostream &os, const Container &container)
Stream operator for containers (array and vector types).
Definition: ArrayUtils.h:180
Default case: T is not a container.
Definition: ArrayUtils.h:29
Definition: ArrayUtils.h:62
static constexpr bool const value
bool value true if given type is a container false if not
Definition: ArrayUtils.h:63