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 <sstream>
14#include <vector>
15
17
32template <class output_t, class input_t, std::size_t SIZE>
33[[nodiscard]] constexpr std::array<output_t, SIZE> static_cast_copy_array(const std::array<input_t, SIZE> &a) {
34 std::array<output_t, SIZE> result{};
35 for (std::size_t d = 0; d < SIZE; ++d) {
36 result[d] = static_cast<output_t>(a[d]);
37 }
38 return result;
39}
40
53template <class Container, class Fun>
54void to_string(std::ostream &os, const Container &container, const std::string &delimiter,
55 const std::array<std::string, 2> &surround, Fun elemToString) {
56 auto it = std::cbegin(container);
57 const auto end = std::cend(container);
58 if (it == end) {
59 os << surround[0] << surround[1];
60 return;
61 }
62 os << surround[0] << elemToString(*it);
63 for (++it; it != end; ++it) {
64 os << delimiter << elemToString(*it);
65 }
66 os << surround[1];
67}
68
77template <class Container>
78void to_string(std::ostream &os, const Container &container, const std::string &delimiter = ", ",
79 const std::array<std::string, 2> &surround = {"[", "]"}) {
80 to_string(os, container, delimiter, surround, [](const auto &x) { return x; });
81}
82
95template <class Container, class Fun>
96[[nodiscard]] std::string to_string(const Container &container, const std::string &delimiter,
97 const std::array<std::string, 2> &surround, Fun elemToString) {
98 std::ostringstream strStream;
99 strStream << std::boolalpha;
100 to_string(strStream, container, delimiter, surround, elemToString);
101
102 return strStream.str();
103}
104
113template <class Container>
114[[nodiscard]] std::string to_string(const Container &container, const std::string &delimiter = ", ",
115 const std::array<std::string, 2> &surround = {"[", "]"}) {
116 return to_string(container, delimiter, surround, [](const auto &elem) { return elem; });
117}
118
131template <ContainerType Container>
132std::ostream &operator<<(std::ostream &os, const Container &container) {
133 const std::string &delimiter = ", ";
134 const std::array<std::string, 2> &surround = {"[", "]"};
135
136 to_string(os, container, delimiter, surround);
137
138 return os;
139}
140
150template <class OuterContainerT>
151void balanceVectors(OuterContainerT &vecvec) {
153 vecvec, [](auto &innerContainer) -> auto & { return innerContainer; });
154}
155
168template <class OuterContainerT, class F>
169void balanceVectors(OuterContainerT &vecvec, F innerContainerToVec) {
170 using InnerContainerT = typename OuterContainerT::value_type;
171 using ElemT = typename std::remove_reference_t<
172 std::invoke_result_t<decltype(innerContainerToVec), InnerContainerT &>>::value_type;
173 // calculate vecvec statistics
174 const auto vecvecSize = vecvec.size();
175 if (vecvecSize == 0) {
176 // nothing to do
177 return;
178 }
179 const size_t numElem = std::transform_reduce(vecvec.begin(), vecvec.end(), 0, std::plus<>(),
180 [&](auto &vec) { return innerContainerToVec(vec).size(); });
181 const auto targetSize = static_cast<long>(numElem / vecvecSize);
182 const auto remainder = numElem % vecvecSize;
183
184 std::vector<ElemT> tmpStorage;
185 // index of the first subvec that has too few elements
186 size_t firstTooFew = 0;
187 // repeat as long as there is something in the buffer but at least 2 iterations.
188 for (int pass = 0; pass == 0 or not tmpStorage.empty(); ++pass) {
189 // scan all subvecs that are not known to have the desired size
190 for (size_t i = firstTooFew; i < vecvecSize; ++i) {
191 auto &vec = innerContainerToVec(vecvec[i]);
192 const auto thisTargetSize = i < remainder ? targetSize + 1 : targetSize;
193 if (vec.size() > thisTargetSize) {
194 // move what is too much to tmpStorage
195 const auto startOfTooMuch = vec.begin() + thisTargetSize;
196 tmpStorage.insert(tmpStorage.end(), std::make_move_iterator(startOfTooMuch),
197 std::make_move_iterator(vec.end()));
198 vec.erase(startOfTooMuch, vec.end());
199 // if firstTooFew points here bump it, since this vector is now satisfied
200 if (firstTooFew == i) {
201 ++firstTooFew;
202 }
203 } else if (vec.size() < thisTargetSize) {
204 // fill too small vectors from storage
205 vec.reserve(thisTargetSize);
206 const long numMissing = thisTargetSize - vec.size();
207 const auto startOfInsertion =
208 tmpStorage.begin() + (std::max(0l, static_cast<long>(tmpStorage.size()) - numMissing));
209 vec.insert(vec.end(), std::make_move_iterator(startOfInsertion), std::make_move_iterator(tmpStorage.end()));
210 tmpStorage.erase(startOfInsertion, tmpStorage.end());
211
212 } else if (firstTooFew == i) {
213 // if firstTooFew points here bump it, since this vector is already satisfied
214 ++firstTooFew;
215 }
216 // after the first pass all excess elements are collected. So as soon as everything is distributed we are done.
217 if (pass > 0 and tmpStorage.empty()) {
218 break;
219 }
220 }
221 }
222}
223} // 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:151
std::ostream & operator<<(std::ostream &os, const Container &container)
Stream operator for containers (array and vector types).
Definition: ArrayUtils.h:132
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:33
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:54