MolSim
Loading...
Searching...
No Matches
ArrayUtils.h
Go to the documentation of this file.
11#pragma once
12
13#include <algorithm>
14#include <array>
15#include <cmath>
16#include <functional>
17#include <list>
18#include <map>
19#include <numeric>
20#include <set>
21#include <sstream>
22#include <string>
23#include <unordered_map>
24#include <unordered_set>
25#include <vector>
26
31namespace ArrayUtils {
32
33// specialize a type for all of the STL containers.
38namespace is_container_impl {
43template <typename T> struct is_container : std::false_type {};
49template <typename T, std::size_t N> struct is_container<std::array<T, N>> : std::true_type {};
54template <typename... Args> struct is_container<std::vector<Args...>> : std::true_type {};
59template <typename... Args> struct is_container<std::list<Args...>> : std::true_type {};
64template <typename... Args> struct is_container<std::set<Args...>> : std::true_type {};
69template <typename... Args> struct is_container<std::unordered_set<Args...>> : std::true_type {};
70} // namespace is_container_impl
71
76template <typename T> struct is_container {
78};
79
90template <class Container>
91[[nodiscard]] std::string to_string(const Container &container, const std::string &delimiter = ", ",
92 const std::array<std::string, 2> &surround = {"[", "]"}) {
93 auto iter = std::cbegin(container);
94 const auto end = std::cend(container);
95 if (iter == end) {
96 return surround[0] + surround[1];
97 }
98 std::ostringstream strStream;
99 strStream << surround[0] << *iter;
100 for (++iter; iter != end; ++iter) {
101 strStream << delimiter << *iter;
102 }
103 strStream << surround[1];
104 return strStream.str();
105}
106
120template <class Container, class F>
121inline Container elementWisePairOp(const Container &lhs, const Container &rhs, F binaryFunction) {
122 Container ret = lhs;
123 auto retIter = std::begin(ret);
124 auto lhsIter = std::cbegin(lhs);
125 const auto lhsEnd = std::cend(lhs);
126 auto rhsIter = std::cbegin(rhs);
127 const auto rhsEnd = std::cend(rhs);
128
129 for (; lhsIter != lhsEnd && rhsIter != rhsEnd; ++lhsIter, ++rhsIter, ++retIter) {
130 *retIter = binaryFunction(*lhsIter, *rhsIter);
131 }
132
133 return ret;
134}
135
147template <class Scalar, class Container, class F>
148inline Container elementWiseScalarOp(const Scalar &lhs, const Container &rhs, F binaryFunction) {
149 Container ret = rhs;
150 auto retIter = std::begin(ret);
151 auto rhsIter = std::cbegin(rhs);
152 const auto rhsEnd = std::cend(rhs);
153
154 for (; rhsIter != rhsEnd; ++rhsIter, ++retIter) {
155 *retIter = binaryFunction(lhs, *rhsIter);
156 }
157
158 return ret;
159}
160
167template <class Container> auto L2NormSquared(const Container &c) {
168 return std::accumulate(std::cbegin(c), std::cend(c), 0.0, [](auto a, auto b) { return a + b * b; });
169}
170
177template <class Container> auto L2Norm(const Container &c) {
178 return std::sqrt(std::accumulate(std::cbegin(c), std::cend(c), 0.0, [](auto a, auto b) { return a + b * b; }));
179}
180} // namespace ArrayUtils
181
193template <class Container>
194std::enable_if_t<ArrayUtils::is_container<Container>::value, std::ostream &> operator<<(std::ostream &os,
195 const Container &container) {
196 os << ArrayUtils::to_string(container);
197 return os;
198}
199
207template <class Container>
208std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> operator+(const Container &lhs,
209 const Container &rhs) {
210 return ArrayUtils::elementWisePairOp(lhs, rhs, std::plus<>());
211}
212
220template <class Container>
221std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> operator-(const Container &lhs,
222 const Container &rhs) {
223 return ArrayUtils::elementWisePairOp(lhs, rhs, std::minus<>());
224}
225
233template <class Container>
234std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> operator*(const Container &lhs,
235 const Container &rhs) {
236 return ArrayUtils::elementWisePairOp(lhs, rhs, std::multiplies<>());
237}
238
246template <class Scalar, class Container>
247std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> operator*(const Scalar &lhs,
248 const Container &rhs) {
249 return ArrayUtils::elementWiseScalarOp(lhs, rhs, std::multiplies<>());
250}
251
260template <class Container>
261std::enable_if_t<ArrayUtils::is_container<Container>::value, bool> operator==(const Container &lhs,
262 const Container &rhs) {
263 if (lhs.size() != rhs.size()) {
264 return false;
265 }
266
267 auto lhsIter = std::cbegin(lhs);
268 const auto lhsEnd = std::cend(lhs);
269 auto rhsIter = std::cbegin(rhs);
270
271 for (; lhsIter != lhsEnd; ++lhsIter, ++rhsIter) {
272 if (*lhsIter != *rhs) {
273 return false;
274 }
275 }
276 return true;
277}
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator*(const Container &lhs, const Container &rhs)
Element wise multiplication of two containers.
Definition ArrayUtils.h:234
std::enable_if_t< ArrayUtils::is_container< Container >::value, bool > operator==(const Container &lhs, const Container &rhs)
Element wise comparison of two containers.
Definition ArrayUtils.h:261
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator+(const Container &lhs, const Container &rhs)
Element wise addition of two containers.
Definition ArrayUtils.h:208
std::enable_if_t< ArrayUtils::is_container< Container >::value, std::ostream & > operator<<(std::ostream &os, const Container &container)
Stream operator for containers.
Definition ArrayUtils.h:194
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator-(const Container &lhs, const Container &rhs)
Element wise subtraction of two containers.
Definition ArrayUtils.h:221
Collection of utility functions and operators for iterable data containers like std::array,...
Definition ArrayUtils.h:31
auto L2NormSquared(const Container &c)
Calculates the square of the L2 norm for a given container.
Definition ArrayUtils.h:167
std::string to_string(const Container &container, const std::string &delimiter=", ", const std::array< std::string, 2 > &surround={"[", "]"})
Generates a string representation of a container which fulfills the Container requirement (provide cb...
Definition ArrayUtils.h:91
auto L2Norm(const Container &c)
Calculates the L2 norm for a given container.
Definition ArrayUtils.h:177
Container elementWiseScalarOp(const Scalar &lhs, const Container &rhs, F binaryFunction)
Applies a binary function F to with a scalar to every element in a container.
Definition ArrayUtils.h:148
Container elementWisePairOp(const Container &lhs, const Container &rhs, F binaryFunction)
Applies an element wise binary function F to two containers.
Definition ArrayUtils.h:121
Default case: T is not a container.
Definition ArrayUtils.h:43
Type trait to check if a given type is a container.
Definition ArrayUtils.h:76
static constexpr bool const value
Definition ArrayUtils.h:77