Elm  2
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
util.h
1 /*
2  * utilities for data module
3  *
4  * This file is part of OTAWA
5  * Copyright (c) 2016, IRIT UPS.
6  *
7  * OTAWA is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * OTAWA is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with OTAWA; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 #ifndef ELM_DATA_UTIL_H_
22 #define ELM_DATA_UTIL_H_
23 
24 #include <elm/PreIterator.h>
25 #include <elm/data/Range.h>
26 #include <elm/meta.h>
27 #include <elm/type_info.h>
28 #include <elm/types.h>
29 
30 namespace elm {
31 
32 // simple functions
33 template <class T>
34 struct Add {
35  typedef T x_t;
36  typedef T y_t;
37  inline T operator()(const T& a, const T& b) const { return a + b; }
38  static T null;
39 };
40 template <class T> struct scalar_zero
41  { static inline T zero(void) { return 0; } };
42 template <class T> struct class_zero
43  { static inline T zero(void) { return T::zero; } };
44 template <class T> T Add<T>::null = _if<type_info<T>::is_scalar, scalar_zero<T>, class_zero<T> >::zero();
45 
46 template <class T>
47 struct Mul {
48  typedef T x_t;
49  typedef T y_t;
50  inline T operator()(const T& a, const T& b) const { return a * b; }
51  static T null;
52 };
53 template <class T> struct scalar_one
54  { static inline T one(void) { return 1; } };
55 template <class T> struct class_one
56  { static inline T one(void) { return T::zero; } };
57 template <class T> T Mul<T>::null = _if<type_info<T>::is_scalar, scalar_one<T>, class_one<T> >::one();
58 
59 template <class T> struct true_pred
60  { inline bool operator()(const T& v) { return true; } };
61 
62 
63 // count operations
64 template <class C, class P>
65 inline int count(const C& c, const P& p)
66  { int r = 0; for(const auto& i: c) if(p(i)) r++; return r; }
67 
68 
69 // forall operations
70 template <class C, class P>
71 inline bool forall(const C& c, const P& p)
72  { for(const auto& i: c) if(!p(i)) return false; return true; }
73 
74 
75 // exists operations
76 template <class C, class P>
77 inline bool exists(const C& c, const P& p)
78  { for(const auto& i: c) if(p(i)) return true; return false; }
79 
80 
81 // find operation
82 template <class C, class P>
83 inline typename C::Iter find(const C& c, const P& p)
84  { typename C::Iter i = c.begin(); for(; i != c.end(); i++) if(p(*i)) break; return i; }
85 
86 
87 // map operation
88 template <class C, class F, class D>
89 inline void map(const C& c, const F& f, D& d)
90  { for(const auto& i: c) d.add(f(i)); }
91 
92 
93 // iter operation
94 template <class C, class F>
95 inline void iter(const C& c, const F& f)
96  { for(const auto& i: c) f(i); }
97 
98 
99 // fold operation
100 template <class C, class F, class T>
101 inline T fold(const C& c, const F& f, T t)
102  { for(const auto& i: c) t = f(i, t); return t; }
103 
104 
105 // equality test
106 template <class C1, class C2>
107 inline bool equals(const C1& c1, const C2& c2) {
108  auto i2 = c2.begin();
109  for(auto i1: c1) {
110  if(i2 == c2.end() || i1 != *i2)
111  return false;
112  ++i1;
113  ++i2;
114  }
115  return i2 == c2.end();
116 }
117 
118 
119 // mismatch operation
120 template <class C1, class C2>
122  auto i1 = c1.begin();
123  auto i2 = c2.begin();
124  while(i1 != c1.end() && i2 != c2.end() && *i1 == *i2) {
125  ++i1;
126  ++i2;
127  }
128  return pair(i1, i2);
129 }
130 
131 template <class C1, class C2, class P>
132 Pair<typename C1::Iter, typename C2::Iter> mismatch(const C1& c1, const C2& c2, P p) {
133  auto i1 = c1.begin();
134  auto i2 = c2.begin();
135  while(i1 != c1.end() && i2 != c2.end() && p(*i1, *i2)) {
136  ++i1;
137  ++i2;
138  }
139  return pair(i1, i2);
140 }
141 
142 
143 template <class C>
144 inline void deleteAll(const C& c) { for(auto i: c) delete i; }
145 
146 
147 // useful function
148 template <class C>
149 inline typename C::t sum(const C& c)
150  { return fold(c, [](const typename C::t& i, const typename C::t& s) { return i + s; }, typename C::t(0)); }
151 template <class C>
152 inline typename C::t product(const C& c)
153  { return fold(c, [](const typename C::t& i, const typename C::t& p) { return i * p; }, typename C::t(1)); }
154 
155 
156 // construction operations
157 template <class C>
158 inline void fill(C& c, int n, const typename C::t v = type_info<typename C::t>::null)
159  { for(int i = 0; i < n; i++) c.add(v); }
160 
161 
162 // NumIter class
163 template <class T>
164 class NumIter {
165 public:
166  typedef T t;
167 
168  inline NumIter(T i, T j, T s = 1): _i(i), _j(j), _s(s) { }
169  inline bool ended() const { return _i <= _j; }
170  inline T item() const { return _i; }
171  inline void next() { _i += _s; }
172  inline bool equals(const NumIter<T>& i) const { return _i == i._i; }
173 
174  inline operator bool() const { return !ended(); }
175  inline operator T() const { return item(); }
176  inline T operator*() const { return item(); }
177  inline NumIter& operator++() { next(); return *this; }
178  inline NumIter operator++(int) { NumIter o = *this; next(); return *o; }
179  inline bool operator==(const NumIter& i) const { return equals(i); }
180  inline bool operator!=(const NumIter& i) const { return !equals(i); }
181 
182 private:
183  T _i, _j, _s;
184 };
185 template <class T>
186 class NumRange {
187 public:
188  typedef T t;
189  inline NumRange(T i, T j, T s = 1): _i(i), _j(j), _s(s) { }
190  inline NumIter<T> begin() const { return NumIter<T>(_i, _j, _s); }
191  inline NumIter<T> end() const { return NumIter<T>(_j + 1, _j, _s); }
192 private:
193  int _i, _j, _s;
194 };
195 template <class T> NumRange<T> nrange(T i, T j, T s = 1) { return NumRange<T>(i, j, s); }
196 
197 
198 // select classes
199 template <class I, class P>
200 class SelectIter: public PreIterator<SelectIter<I, P>, typename I::t> {
201 public:
202  inline SelectIter(const I &i, const P& p): _i(i), _p(p) { step(); }
203  inline bool atEnd() const { return _i.atEnd(); }
204  inline const typename I::return_t& item() const { return _i.item(); }
205  inline void next() { _i++; step(); }
206  inline bool equals(const SelectIter<I, P>& i) const { return _i.equals(i._i); }
207 private:
208  inline void step() { while(_i() && !_p(*_i)) _i++; }
209  I _i;
210  P _p;
211 };
212 template <class I, class P>
213 inline SelectIter<I, P> select_iter(const I& i, const P& p) { return SelectIter<I, P>(i, p); }
214 
215 template <class C, class P>
216 inline Range<SelectIter<typename C::Iter, P> > select(const C& c, const P& p)
217  { return range(select_iter(c.begin(), p), select_iter(c.end(), p)); }
218 
219 template <class I>
220 class Iterable {
221 public:
222  typedef typename I::t t;
223  Iterable(const I& begin, const I& end): b(begin), e(end) { }
224  inline const I& begin() const { return b; }
225  inline const I& end() const { return e; }
226 private:
227  I b, e;
228 };
229 
230 template <class I>
231 Iterable<I> subiter(const I& b, const I& e) { return Iterable<I>(b, e); }
232 
233 } // elm
234 
235 #endif /* ELM_DATA_UTIL_H_ */
elm::class_zero::zero
static T zero(void)
Definition: util.h:43
elm::Range
Definition: Range.h:29
elm::_if
Definition: meta.h:43
elm::io::p
Printable< T, M > p(const T &data, const M &man)
Definition: Output.h:302
elm::select
Range< SelectIter< typename C::Iter, P > > select(const C &c, const P &p)
Definition: util.h:216
elm::iter
void iter(const C &c, const F &f)
Definition: util.h:95
elm::Add::y_t
T y_t
Definition: util.h:36
elm::subiter
Iterable< I > subiter(const I &b, const I &e)
Definition: util.h:231
elm::SelectIter::equals
bool equals(const SelectIter< I, P > &i) const
Definition: util.h:206
elm::SelectIter::atEnd
bool atEnd() const
Definition: util.h:203
elm::NumIter::operator++
NumIter & operator++()
Definition: util.h:177
elm::fold
T fold(const C &c, const F &f, T t)
Definition: util.h:101
elm::pair
Pair< T1, T2 > pair(const T1 &v1, const T2 &v2)
Definition: Pair.h:63
elm::equals
bool equals(const C1 &c1, const C2 &c2)
Definition: util.h:107
elm::product
C::t product(const C &c)
Definition: util.h:152
elm::Add::x_t
T x_t
Definition: util.h:35
elm::NumIter
Definition: util.h:164
elm::Add
Definition: util.h:34
elm::Pair
Definition: Pair.h:33
elm::class_one
Definition: util.h:55
elm::class_one::one
static T one(void)
Definition: util.h:56
elm::deleteAll
void deleteAll(const C &c)
Definition: util.h:144
elm::Mul::operator()
T operator()(const T &a, const T &b) const
Definition: util.h:50
elm::type_info
Definition: type_info.h:56
elm::NumRange::begin
NumIter< T > begin() const
Definition: util.h:190
elm::Iterable::begin
const I & begin() const
Definition: util.h:224
elm::Add::operator()
T operator()(const T &a, const T &b) const
Definition: util.h:37
elm::Iterable
Definition: util.h:220
bool
elm::class_zero
Definition: util.h:42
elm::Mul
Definition: util.h:47
elm::map
void map(const C &c, const F &f, D &d)
Definition: util.h:89
elm::forall
bool forall(const C &c, const P &p)
Definition: util.h:71
elm::NumRange
Definition: util.h:186
elm::NumIter::equals
bool equals(const NumIter< T > &i) const
Definition: util.h:172
elm::NumIter::NumIter
NumIter(T i, T j, T s=1)
Definition: util.h:168
elm::find
C::Iter find(const C &c, const P &p)
Definition: util.h:83
elm::NumIter::operator++
NumIter operator++(int)
Definition: util.h:178
elm::range
Range< I > range(const I &begin, const I &end)
Definition: Range.h:67
elm::Iterable::Iterable
Iterable(const I &begin, const I &end)
Definition: util.h:223
elm::Mul::y_t
T y_t
Definition: util.h:49
elm::Mul::x_t
T x_t
Definition: util.h:48
elm
Definition: adapter.h:26
elm::scalar_one::one
static T one(void)
Definition: util.h:54
elm::SelectIter::next
void next()
Definition: util.h:205
elm::NumIter::operator==
bool operator==(const NumIter &i) const
Definition: util.h:179
elm::SelectIter
Definition: util.h:200
elm::Iterable::t
I::t t
Definition: util.h:222
elm::NumRange::end
NumIter< T > end() const
Definition: util.h:191
elm::NumIter::item
T item() const
Definition: util.h:170
elm::NumIter::t
T t
Definition: util.h:166
elm::scalar_one
Definition: util.h:53
elm::Iterable::end
const I & end() const
Definition: util.h:225
elm::nrange
NumRange< T > nrange(T i, T j, T s=1)
Definition: util.h:195
elm::mismatch
Pair< typename C1::Iter, typename C2::Iter > mismatch(const C1 &c1, const C2 &c2)
Definition: util.h:121
elm::count
int count(const C &c, const P &p)
Definition: util.h:65
elm::scalar_zero::zero
static T zero(void)
Definition: util.h:41
elm::SelectIter::item
const I::return_t & item() const
Definition: util.h:204
elm::NumIter::next
void next()
Definition: util.h:171
elm::exists
bool exists(const C &c, const P &p)
Definition: util.h:77
elm::NumIter::operator!=
bool operator!=(const NumIter &i) const
Definition: util.h:180
elm::sum
C::t sum(const C &c)
Definition: util.h:149
elm::NumIter::ended
bool ended() const
Definition: util.h:169
elm::select_iter
SelectIter< I, P > select_iter(const I &i, const P &p)
Definition: util.h:213
elm::SelectIter::SelectIter
SelectIter(const I &i, const P &p)
Definition: util.h:202
elm::NumRange::t
T t
Definition: util.h:188
elm::PreIterator
Definition: iter.h:28
elm::true_pred
Definition: util.h:59
elm::fill
void fill(C &c, int n, const typename C::t v=type_info< typename C::t >::null)
Definition: util.h:158
elm::scalar_zero
Definition: util.h:40
elm::true_pred::operator()
bool operator()(const T &v)
Definition: util.h:60
elm::NumIter::operator*
T operator*() const
Definition: util.h:176
elm::NumRange::NumRange
NumRange(T i, T j, T s=1)
Definition: util.h:189