xerus
a general purpose tensor library
containerSupport.h
Go to the documentation of this file.
1 // Xerus - A General Purpose Tensor Library
2 // Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf.
3 //
4 // Xerus is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as published
6 // by the Free Software Foundation, either version 3 of the License,
7 // or (at your option) any later version.
8 //
9 // Xerus is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
13 //
14 // You should have received a copy of the GNU Affero General Public License
15 // along with Xerus. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // For further information on Xerus visit https://libXerus.org
18 // or contact us at contact@libXerus.org.
19 
25 #pragma once
26 
27 #include <vector>
28 #include <set>
29 #include <map>
30 #include <tuple>
31 #include <algorithm>
32 #include <numeric>
33 #include <iostream>
34 
35 #include "standard.h"
36 #include "sfinae.h"
37 #include "check.h"
38 
39 namespace xerus { namespace misc {
40 
41  #if __GNUC__ > 4 || defined(__clang__)
42 
43  XERUS_GENERATE_HAS_FUNCTION(count)
44  XERUS_GENERATE_HAS_FUNCTION(find)
45 
46 
47 
48  template<template<class, class...> class container_t, class item_t, class... rest_t,
49  typename std::enable_if<sfinae::has_count<container_t<item_t, rest_t...>, item_t>::value, int>::type = 0>
50  inline size_t count(const container_t<item_t, rest_t...> &_container, const item_t &_item) noexcept(noexcept(_container.count(_item))) {
51  return _container.count(_item);
52  }
53 
54 
56  template<template<class, class...> class container_t, class item_t, class... rest_t,
57  typename std::enable_if<!sfinae::has_count<container_t<item_t, rest_t...>, item_t>::value, int>::type = 0>
58  inline size_t count(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
59  size_t count = 0;
60  for(const item_t& otherItem : _container) {
61  if(otherItem == _item) { count++; }
62  }
63  return count;
64  }
65 
66 
68  template<template<class, class...> class container_t, class item_t, class... rest_t,
69  typename std::enable_if<sfinae::has_find<container_t<item_t, rest_t...>, item_t>::value, int>::type = 0>
70  inline bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
71  return _container.find(_item) != _container.end();
72  }
73 
74 
76  template<template<class, class...> class container_t, class item_t, class... rest_t,
77  typename std::enable_if<!sfinae::has_find<container_t<item_t, rest_t...>, item_t>::value, int>::type = 0>
78  inline bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
79  return std::find(_container.begin(), _container.end(), _item) != _container.end();
80  }
81 
82  #else
83 
85 
86 
87  template<template<class, class...> class container_t, class item_t, class... rest_t,
88  typename std::enable_if<!has_member_count<container_t<item_t, rest_t...>>::value, int>::type = 0>
89  inline size_t count(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
90  size_t count = 0;
91  for(const item_t& otherItem : _container) {
92  if(otherItem == _item) { count++; }
93  }
94  return count;
95  }
96 
97 
99  template<template<class, class...> class container_t, class item_t, class... rest_t,
100  typename std::enable_if<has_member_count<container_t<item_t, rest_t...>>::value, int>::type = 0>
101  inline size_t count(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
102  return _container.count(_item);
103  }
104 
106  template<template<class, class...> class container_t, class item_t, class... rest_t,
107  typename std::enable_if<!has_member_count<container_t<item_t, rest_t...>>::value, int>::type = 0>
108  inline bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
109  return std::find(_container.begin(), _container.end(), _item) != _container.end();
110  }
111 
112 
114  template<template<class, class...> class container_t, class item_t, class... rest_t,
115  typename std::enable_if<has_member_count<container_t<item_t, rest_t...>>::value, int>::type = 0>
116  inline bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
117  return _container.find(_item) != _container.end();
118  }
119 
120  #endif
121 
123  template<template<class, class...> class containerA_t, template<class, class...> class containerB_t, class item_t, class... restA_t, class... restB_t>
124  inline bool contains(const containerA_t<item_t, restA_t...> &_largeContainer, const containerB_t<item_t, restB_t...> &_smallContainer) {
125  for(const item_t &item : _smallContainer) {
126  if(!contains(_largeContainer, item)) { return false; }
127  }
128  return true;
129  }
130 
131 
133  template<template<class, class...> class container_t, class item_t, class... rest_t>
134  inline bool disjunct(const container_t<item_t, rest_t...>& _containerA, const container_t<item_t, rest_t...>& _containerB) {
135  for(const item_t& item : _containerA) {
136  if(contains(_containerB, item)) { return false; }
137  }
138  return true;
139  }
140 
141 
143  template<template<class, class...> class container_t, class item_t, class... rest_t>
144  inline item_t max(const container_t<item_t, rest_t...>& _container) {
145  XERUS_REQUIRE(!_container.empty(), "max() must not be invoked with empty container.");
146  return *std::max_element(_container.begin(), _container.end());
147  }
148 
149 
151  template<template<class, class...> class container_t, class item_t, class... rest_t>
152  inline item_t min(const container_t<item_t, rest_t...>& _container) {
153  XERUS_REQUIRE(!_container.empty(), "min() must not be invoked with empty container.");
154  return *std::min_element(_container.begin(), _container.end());
155  }
156 
157 
159  template<template<class, class...> class container_t, class item_t, class... rest_t>
160  inline item_t sum(const container_t<item_t, rest_t...>& _container) {
161  return std::accumulate(_container.begin(), _container.end(), item_t(0));
162  }
163 
165  template<template<class, class...> class container_t, class item_t, class... rest_t>
166  inline item_t average(const container_t<item_t, rest_t...>& _container) {
167  return sum(_container)/_container.size();
168  }
169 
170 
172  template<template<class, class...> class container_t, class item_t, class... rest_t>
173  inline item_t product(const container_t<item_t, rest_t...>& _container) {
174  return std::accumulate(_container.begin(), _container.end(), item_t(1), std::multiplies<item_t>());
175  }
176 
177 
179  template<template<class, class...> class container_t, class item_t, class... rest_t>
180  inline double fp_product(const container_t<item_t, rest_t...>& _container) {
181  return std::accumulate(_container.begin(), _container.end(), double(1.0), std::multiplies<double>());
182  }
183 
184 
186  template<class item_t, class... rest_t>
187  inline item_t product(const std::vector<item_t, rest_t...>& _container, const size_t _first, const size_t _last) {
188  XERUS_REQUIRE(_first <= _last && _last <= _container.size(), "Invalid range " << _first << "-" << _last << " given (Container size " << _container.size() << ")");
189  return std::accumulate(_container.begin()+_first, _container.begin()+_last, item_t(1), std::multiplies<item_t>());
190  }
191 
192 
194  template<class rule_t, template<class, class...> class container_t, class item_t, class... rest_t>
195  inline void erase(container_t<item_t, rest_t...>& _container, const rule_t& _rule) {
196  _container.erase(std::remove_if(_container.begin(), _container.end(), _rule), _container.end());
197  }
198 } } // namespaces xerus::misc
199 
200 
201 
Header file for CHECK and REQUIRE macros.
The main namespace of xerus.
Definition: basic.h:37
Header file for macros that encapsulate SFINAE functionality.
#define XERUS_REQUIRE(condition, message)
Checks whether condition is true. logs an error otherwise via XERUS_LOG(error, message).
Definition: check.h:65
XERUS_GENERATE_HAS_MEMBER(count) template< template< class
: Counts how often an element is contained in an arbitary container
Header file for global shorthand notations of elementary integer types and attribute lists...