19 #include <unordered_map> 
   20 #include <unordered_set> 
   38 namespace is_container_impl {
 
   50 template <
typename T, std::
size_t N>
 
   56 template <
typename... Args>
 
   62 template <
typename... Args>
 
   68 template <
typename... Args>
 
   74 template <
typename... Args>
 
   75 struct is_container<std::unordered_set<Args...>> : std::true_type {};
 
   96 template <
class Container>
 
   97 [[nodiscard]] std::string 
to_string(
const Container& container, 
const std::string& delimiter = 
", ",
 
   98                                     const std::array<std::string, 2>& surround = {
"[", 
"]"}) {
 
   99     auto iter = std::cbegin(container);
 
  100     const auto end = std::cend(container);
 
  102         return surround[0] + surround[1];
 
  104     std::ostringstream strStream;
 
  105     strStream << surround[0] << *iter;
 
  106     for (++iter; iter != end; ++iter) {
 
  107         strStream << delimiter << *iter;
 
  109     strStream << surround[1];
 
  110     return strStream.str();
 
  126 template <
class Container, 
class F>
 
  127 inline Container 
elementWisePairOp(
const Container& lhs, 
const Container& rhs, F binaryFunction) {
 
  129     auto retIter = std::begin(ret);
 
  130     auto lhsIter = std::cbegin(lhs);
 
  131     const auto lhsEnd = std::cend(lhs);
 
  132     auto rhsIter = std::cbegin(rhs);
 
  133     const auto rhsEnd = std::cend(rhs);
 
  135     for (; lhsIter != lhsEnd and rhsIter != rhsEnd; ++lhsIter, ++rhsIter, ++retIter) {
 
  136         *retIter = binaryFunction(*lhsIter, *rhsIter);
 
  153 template <
class Scalar, 
class Container, 
class F>
 
  156     auto retIter = std::begin(ret);
 
  157     auto rhsIter = std::cbegin(rhs);
 
  158     const auto rhsEnd = std::cend(rhs);
 
  160     for (; rhsIter != rhsEnd; ++rhsIter, ++retIter) {
 
  161         *retIter = binaryFunction(lhs, *rhsIter);
 
  173 template <
class Container>
 
  175     return std::sqrt(std::accumulate(std::cbegin(c), std::cend(c), 0.0, [](
auto a, 
auto b) { 
return a + b * b; }));
 
  183 inline auto L2Norm<std::array<double, 3>>(
const std::array<double, 3>& c) {
 
  184     return std::sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
 
  193 template <
class Container>
 
  195     return std::accumulate(std::cbegin(c), std::cend(c), 0.0, [](
auto a, 
auto b) { 
return a + b * b; });
 
  203 inline auto L2NormSquared<std::array<double, 3>>(
const std::array<double, 3>& c) {
 
  204     return c[0] * c[0] + c[1] * c[1] + c[2] * c[2];
 
  219 template <
class Container>
 
  220 std::enable_if_t<ArrayUtils::is_container<Container>::value, std::ostream&> 
operator<<(std::ostream& os, 
const Container& container) {
 
  232 template <
class Container>
 
  233 std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> 
operator+(
const Container& lhs, 
const Container& rhs) {
 
  244 template <
class Container>
 
  245 std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> 
operator-(
const Container& lhs, 
const Container& rhs) {
 
  256 template <
class Container>
 
  257 std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> 
operator*(
const Container& lhs, 
const Container& rhs) {
 
  268 template <
class Scalar, 
class Container>
 
  269 std::enable_if_t<ArrayUtils::is_container<Container>::value, Container> 
operator*(
const Scalar& lhs, 
const Container& rhs) {
 
  281 template <
class Container>
 
  282 std::enable_if_t<ArrayUtils::is_container<Container>::value, 
bool> 
operator==(
const Container& lhs, 
const Container& rhs) {
 
  283     if (lhs.size() != rhs.size()) {
 
  287     auto lhsIter = std::cbegin(lhs);
 
  288     const auto lhsEnd = std::cend(lhs);
 
  289     auto rhsIter = std::cbegin(rhs);
 
  291     for (; lhsIter != lhsEnd; ++lhsIter, ++rhsIter) {
 
  292         if (*lhsIter != *rhs) {
 
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator-(const Container &lhs, const Container &rhs)
 
std::enable_if_t< ArrayUtils::is_container< Container >::value, std::ostream & > operator<<(std::ostream &os, const Container &container)
 
std::enable_if_t< ArrayUtils::is_container< Container >::value, bool > operator==(const Container &lhs, const Container &rhs)
 
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator*(const Container &lhs, const Container &rhs)
 
std::enable_if_t< ArrayUtils::is_container< Container >::value, Container > operator+(const Container &lhs, const Container &rhs)
 
Collection of utility functions and operators for iterable data containers.
 
auto L2NormSquared(const Container &c)
 
std::string to_string(const Container &container, const std::string &delimiter=", ", const std::array< std::string, 2 > &surround={"[", "]"})
 
auto L2Norm(const Container &c)
 
Container elementWiseScalarOp(const Scalar &lhs, const Container &rhs, F binaryFunction)
 
Container elementWisePairOp(const Container &lhs, const Container &rhs, F binaryFunction)
 
static constexpr bool const value