Aleph-w  1.9
General library for algorithms and data structures
ahDry.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 
28 # ifndef AHDRY_H
29 # define AHDRY_H
30 
31 # include <tuple>
32 # include <functional>
33 # include <sstream>
34 # include <initializer_list>
35 
36 # include <ahFunctional.H>
37 
38 namespace Aleph
39 {
40 
41  template <typename T> class DynList;
42 
43 # define Generic_Traverse(Type) \
44  template <class Operation> \
45  bool traverse(Operation & operation) const noexcept(noexcept(operation)) \
46  { \
47  for (Iterator it(*this); it.has_curr(); it.next_ne()) \
48  if (not operation(it.get_curr_ne())) \
49  return false; \
50  return true; \
51  } \
52  \
53  template <class Operation> \
54  bool traverse(Operation & operation) noexcept(noexcept(operation)) \
55  { \
56  for (Iterator it(*this); it.has_curr(); it.next_ne()) \
57  if (not operation(it.get_curr_ne())) \
58  return false; \
59  return true; \
60  } \
61  \
62  template <class Operation> \
63  bool traverse(Operation && operation = Operation()) const \
64  noexcept(noexcept(operation)) \
65  { \
66  return traverse<Operation>(operation); \
67  } \
68  \
69  template <class Operation> \
70  bool traverse(Operation && operation = Operation()) \
71  noexcept(noexcept(operation)) \
72  { \
73  return traverse<Operation>(operation); \
74  }
75 
76 # define Special_Ctors(Set_Type, Type) \
77  template <template <typename> class List> \
78  Set_Type(const List<Type> & l) : Set_Type() \
79  { \
80  l.for_each([this] (const Type & item) { this->append(item); }); \
81  } \
82  \
83  template <class It> \
84  Set_Type(It b, It e) : Set_Type() \
85  { \
86  for (It it = b; it != e; ++it) \
87  this->append(*it); \
88  } \
89  \
90  Set_Type(std::initializer_list<Type> l) : Set_Type() \
91  { \
92  for (const auto & item : l) \
93  this->append(item); \
94  }
95 
96 
97 # define Locate_Functions(Type) \
98  Type & nth(const size_t n) const \
99  { \
100  Type * ptr = nullptr; \
101  size_t i = 0; \
102  this->traverse([&ptr, &i, &n] (Type & item) \
103  { \
104  if (i++ < n) \
105  return true; \
106  ptr = &item; \
107  return false; \
108  }); \
109  \
110  if (i != n + 1) \
111  throw std::out_of_range("index out of range"); \
112  \
113  return *ptr; \
114  } \
115  \
116  Type & nth_ne(const size_t n) const noexcept \
117  { \
118  Type * ptr = nullptr; \
119  size_t i = 0; \
120  this->traverse([&ptr, &i, &n] (Type & item) \
121  { \
122  if (i++ < n) \
123  return true; \
124  ptr = &item; \
125  return false; \
126  }); \
127  return *ptr; \
128  } \
129  \
130  template <class Operation> \
131  Type * find_ptr(Operation & operation) noexcept(noexcept(operation)) \
132  { \
133  Type * ptr = nullptr; \
134  this->traverse([&ptr,&operation] (Type & item) \
135  { \
136  if (operation(item)) \
137  { \
138  ptr = &item; \
139  return false; \
140  } \
141  return true; \
142  }); \
143  return ptr; \
144  } \
145  \
146  template <class Operation> \
147  Type * find_ptr(Operation & operation) const noexcept(noexcept(operation)) \
148  { \
149  Type * ptr = nullptr; \
150  this->traverse([&ptr, &operation] (Type & item) \
151  { \
152  if (operation(item)) \
153  { \
154  ptr = &item; \
155  return false; \
156  } \
157  return true; \
158  }); \
159  return ptr; \
160  } \
161  \
162  template <class Operation> \
163  Type * find_ptr(Operation && operation = Operation()) const \
164  noexcept(noexcept(operation)) \
165  { \
166  return find_ptr<Operation>(operation); \
167  } \
168  \
169  template <class Operation> \
170  Type * find_ptr(Operation && operation = Operation()) \
171  noexcept(noexcept(operation)) \
172  { \
173  return find_ptr<Operation>(operation); \
174  } \
175  \
176  template <class Operation> \
177  std::tuple<bool, Type> find_item(Operation & operation) \
178  noexcept(noexcept(operation)) \
179  { \
180  auto ptr = find_ptr(operation); \
181  return ptr ? std::make_tuple(true, *ptr) : std::make_tuple(false, Type()); \
182  } \
183  \
184  template <class Operation> \
185  std::tuple<bool, Type> find_item(Operation & operation) const \
186  noexcept(noexcept(operation)) \
187  { \
188  auto ptr = find_ptr(operation); \
189  return ptr ? std::make_tuple(true, *ptr) : std::make_tuple(false, Type()); \
190  } \
191  \
192  template <class Operation> \
193  std::tuple<bool, Type> find_item(Operation && operation = Operation()) \
194  noexcept(noexcept(operation)) \
195  { \
196  return find_item(operation); \
197  } \
198  \
199  template <class Operation> \
200  std::tuple<bool, Type> find_item(Operation && operation = Operation()) const \
201  noexcept(noexcept(operation)) \
202  { \
203  return find_item(operation); \
204  }
205 
206 # define Functional_Methods(Type) \
207  template <class Operation> \
208  auto for_each(Operation & operation) const \
209  noexcept(noexcept(operation))-> decltype(*this) \
210  { \
211  this->traverse([&operation] (const Type & item) \
212  { \
213  operation(item); \
214  return true; \
215  }); \
216  return *this; \
217  } \
218  \
219  template <class Operation> \
220  auto for_each(Operation & operation) noexcept(noexcept(operation)) \
221  -> decltype(*this) \
222  { \
223  this->traverse([&operation] (const Type & item) \
224  { \
225  operation(item); \
226  return true; \
227  }); \
228  return *this; \
229  } \
230  \
231  template <class Operation> \
232  auto for_each(Operation && operation = Operation()) const \
233  noexcept(noexcept(operation)) -> decltype(*this) \
234  { \
235  return this->for_each<Operation>(operation); \
236  } \
237  \
238  template <class Operation> \
239  auto for_each(Operation && operation = Operation()) \
240  noexcept(noexcept(operation)) -> decltype(*this) \
241  { \
242  return this->for_each<Operation>(operation); \
243  } \
244  \
245  template <class Operation> \
246  auto mutable_for_each(Operation & operation) \
247  noexcept(noexcept(operation)) -> decltype(*this) \
248  { \
249  this->traverse([&operation] (Type & item) \
250  { \
251  operation(item); \
252  return true; \
253  }); \
254  return *this; \
255  } \
256  \
257  template <class Operation> \
258  auto mutable_for_each(Operation && operation = Operation()) \
259  noexcept(noexcept(operation)) -> decltype(*this) \
260  { \
261  return this->mutable_for_each<Operation>(operation); \
262  } \
263  \
264  template <class Operation> \
265  bool all(Operation & operation) const \
266  noexcept(noexcept(operation)) \
267  { \
268  return this->template traverse<Operation>(operation); \
269  } \
270  \
271  template <class Operation> \
272  bool all(Operation && operation = Operation()) const \
273  noexcept(noexcept(operation)) \
274  { \
275  return all<Operation>(operation); \
276  } \
277  \
278  template <class Operation> \
279  bool forall(Operation & operation) const \
280  noexcept(noexcept(operation)) \
281  { \
282  return all<Operation>(operation); \
283  } \
284  \
285  template <class Operation> \
286  bool forall(Operation && operation = Operation()) const \
287  noexcept(noexcept(operation)) \
288  { \
289  return all<Operation>(operation); \
290  } \
291  \
292  template <class Operation> \
293  bool exists(Operation & operation) const \
294  noexcept(noexcept(operation)) \
295  { \
296  return not this->traverse([&operation] (const Type & item) \
297  { \
298  return not operation(item); \
299  }); \
300  } \
301  \
302  template <class Operation> \
303  bool exists(Operation && operation = Operation()) const \
304  noexcept(noexcept(operation)) \
305  { \
306  return exists<Operation>(operation); \
307  } \
308  \
309  template <typename __Type = Type, \
310  template <typename> class Container = Aleph::DynList, \
311  class Operation = Dft_Map_Op<Type, __Type>> \
312  Container<__Type> maps(Operation & operation) const \
313  { \
314  Container<__Type> ret_val; \
315  this->for_each([&ret_val, &operation] (const Type & item) \
316  { \
317  ret_val.append(operation(item)); \
318  }); \
319  return ret_val; \
320  } \
321  \
322  template < typename __Type = Type, \
323  template <typename> class Container = Aleph::DynList, \
324  class Operation = Dft_Map_Op<__Type, __Type>> \
325  Container<__Type> maps(Operation && operation = Operation()) const \
326  { \
327  return maps<__Type, Container, Operation>(operation); \
328  } \
329  \
330  template <typename __Type = Type> \
331  __Type foldl(const __Type & init, \
332  std::function<__Type(const __Type&, const Type &)> operation) const \
333  noexcept(noexcept(operation)) \
334  { \
335  auto ret_val = init; \
336  this->for_each([&ret_val, &operation] (const Type & item) \
337  { \
338  ret_val = operation(ret_val, item); \
339  }); \
340  return ret_val; \
341  } \
342  \
343  template <class Operation> \
344  Type fold(const Type & init, Operation & operation) const \
345  noexcept(noexcept(operation)) \
346  { \
347  auto ret_val = init; \
348  this->for_each([&ret_val, &operation] (const Type & item) \
349  { \
350  ret_val = operation(ret_val, item); \
351  }); \
352  return ret_val; \
353  } \
354  \
355  template <class Operation> \
356  Type fold(const Type & init, Operation && operation = Operation()) const \
357  noexcept(noexcept(operation)) \
358  { \
359  return fold<Operation>(init, operation); \
360  } \
361  \
362  template <class Operation> \
363  DynList<Type> filter(Operation & operation) const \
364  { \
365  DynList<Type> ret_val; \
366  this->for_each([&ret_val, &operation] (const Type & item) \
367  { \
368  if (operation(item)) \
369  ret_val.append(item); \
370  }); \
371  return ret_val; \
372  } \
373  \
374  template <class Operation> \
375  DynList<Type> filter(Operation && operation = Operation()) const \
376  { \
377  return filter<Operation>(operation); \
378  } \
379  \
380  template <class Operation> \
381  DynList<std::tuple<Type, size_t>> pfilter(Operation & operation) const \
382  { \
383  DynList<std::tuple<Type, size_t>> ret_val; \
384  size_t i = 0; \
385  this->for_each([&ret_val, &operation, &i] (const Type & item) \
386  { \
387  if (operation(item)) \
388  ret_val.append(std::make_tuple(item, i)); \
389  ++i; \
390  }); \
391  return ret_val; \
392  } \
393  \
394  template <class Operation> \
395  DynList<std::tuple<Type, size_t>> \
396  pfilter(Operation && operation = Operation()) const \
397  { \
398  return pfilter<Operation>(operation); \
399  } \
400  \
401  template <class Operation> \
402  std::pair<DynList<Type>, DynList<Type>> partition(Operation & op) const \
403  { \
404  std::pair<DynList<Type>, DynList<Type>> ret_val; \
405  this->for_each([&ret_val, &op] (const Type & item) \
406  { \
407  if (op(item)) \
408  ret_val.first.append(item); \
409  else \
410  ret_val.second.append(item); \
411  }); \
412  return ret_val; \
413  } \
414  \
415  template <class Operation> \
416  std::pair<DynList<Type>, DynList<Type>> \
417  partition(Operation && op = Operation()) const \
418  { \
419  return partition<Operation>(op); \
420  } \
421  \
422  template <class Operation> \
423  std::tuple<DynList<Type>, DynList<Type>> tpartition(Operation & op) const \
424  { \
425  DynList<Type> r1, r2; \
426  this->for_each([&r1, &r2, &op] (const Type & item) \
427  { \
428  if (op(item)) \
429  r1.append(item); \
430  else \
431  r2.append(item); \
432  }); \
433  return std::make_tuple(r1, r2); \
434  } \
435  \
436  template <class Operation> \
437  std::tuple<DynList<Type>, DynList<Type>> \
438  tpartition(Operation && op = Operation()) const \
439  { \
440  return partition<Operation>(op); \
441  } \
442  \
443  size_t length() const noexcept \
444  { \
445  size_t count = 0; \
446  this->for_each([&count] (const Type &) { ++count; }); \
447  return count; \
448  } \
449  \
450  template <template <typename> class Container = Aleph::DynList> \
451  Container<Type> rev() const \
452  { \
453  Container<Type> ret_val; \
454  for_each([&ret_val] (const Type & item) \
455  { \
456  ret_val.insert(item); \
457  }); \
458  return ret_val; \
459  } \
460  \
461  template <template <typename> class Container = Aleph::DynList> \
462  Container<Type> take(const size_t n) const \
463  { \
464  size_t i = 0; \
465  Container<Type> ret; \
466  this->traverse([&i, &ret, n] (const Type & item) \
467  { \
468  if (i++ >= n) \
469  return false; \
470  ret.append(item); \
471  return true; \
472  }); \
473  return ret; \
474  } \
475  \
476  template <template <typename> class Container = Aleph::DynList> \
477  Container<Type> drop(const size_t n) const \
478  { \
479  size_t i = 0; \
480  Container<Type> ret; \
481  this->traverse([&i, &ret, n] (const Type & item) \
482  { \
483  if (i++ >= n) \
484  ret.append(item); \
485  return true; \
486  }); \
487  return ret; \
488  }
489 
490 # define Generic_Keys(Type) \
491  template <template <typename> class Container = DynList> \
492  Container<Type> keys() const \
493  { \
494  return this->template maps<Type, Container>([] (const Type & key) \
495  { return key; }); \
496  }
497 
498 # define Generic_Items(Type) \
499  template <template <typename> class Container = DynList> \
500  Container<Type> items() const \
501  { \
502  return this->template maps<Type, Container> ([] (const Type & key) \
503  { return key; }); \
504  }
505 
506 
507 # define Equal_To_Method(class_name) \
508  bool equal_to(const class_name & r) const noexcept \
509  { \
510  if (this == &r) \
511  return true; \
512  \
513  if (this->size() != r.size()) \
514  return false; \
515  \
516  return this->all([&r] (const Key & k) \
517  { return r.search(k) != nullptr; }); \
518  } \
519  \
520  bool operator == (const class_name & r) const noexcept \
521  { \
522  return equal_to(r); \
523  } \
524  \
525  bool operator != (const class_name & r) const noexcept \
526  { \
527  return not equal_to(r); \
528  }
529 
530 
531 # define Map_Sequences_Methods() \
532  template <template <typename> class Container = ::DynList> \
533  Container<Key> keys() const \
534  { \
535  Container<Key> ret_val; \
536  this->for_each([&ret_val] (const std::pair<Key, Data> & p) \
537  { \
538  ret_val.append(p.first); \
539  }); \
540  return ret_val; \
541  } \
542  \
543  template <template <typename> class Container = ::DynList> \
544  Container<Data> values() const \
545  { \
546  Container<Data> ret_val; \
547  this->for_each([&ret_val] (const std::pair<Key, Data> & p) \
548  { \
549  ret_val.append(p.second); \
550  }); \
551  return ret_val; \
552  } \
553  \
554  template <template <typename> class Container = ::DynList> \
555  Container<Data*> values_ptr() \
556  { \
557  Container<Data*> ret_val; \
558  this->for_each([&ret_val] (std::pair<Key, Data> & p) \
559  { \
560  ret_val.append(&p.second); \
561  }); \
562  return ret_val; \
563  } \
564  \
565  template <template <typename> class Container = ::DynList> \
566  Container<std::pair<Key, Data>> items() const \
567  { \
568  return this->Base::keys(); \
569  } \
570  \
571  template <template <typename> class Container = ::DynList> \
572  Container<std::pair<Key, Data*>> items_ptr() const \
573  { \
574  Container<std::pair<Key, Data*>> ret_val; \
575  this->for_each([&ret_val] (std::pair<Key, Data> & p) \
576  { \
577  ret_val.append(std::pair<Key,Data*>(p.first, p.second)); \
578  }); \
579  return ret_val; \
580  } \
581  \
582  Data & operator () (const Key & key) \
583  { \
584  return this->find(key); \
585  } \
586  \
587  const Data & operator () (const Key & key) const \
588  { \
589  return this->find(key); \
590  } \
591 
592 # define Generate_Proxy_Operator(Class_Name) \
593  const Data & operator [] (const Key & key) const \
594  { \
595  return find(key); \
596  } \
597  \
598  Data & operator [] (const Key & key) \
599  { \
600  return find(key); \
601  }
602 
603  template <typename Type> inline
604 std::string to_str(const Type & d)
605 {
606  std::ostringstream os;
607  os << d;
608  return os.str();
609 }
610 
611 
612  // This class wrappes the compare class passed to DynMapLinHash which
613  // has form cpm<Key>
614  template <typename Key, typename Data, class Cmp = std::equal_to<Key>>
615  struct Dft_Pair_Cmp
616  {
617  Cmp cmp;
618  Dft_Pair_Cmp(Cmp __cmp = Cmp()) : cmp(__cmp) {}
619  bool operator () (const std::pair<Key, Data> & p1,
620  const std::pair<Key, Data> & p2) const noexcept
621  {
622  return cmp (p1.first, p2.first);
623  }
624  };
625 
626  template <typename Key, typename Data>
627  std::pair<Key, Data> * key_to_pair(Key * ptr)
628  {
629  return (std::pair<Key, Data>*) ptr;
630  }
631 
632  template <typename Key, typename Data>
633  std::pair<Key, Data> * data_to_pair(Data * ptr)
634  {
635  std::pair<Key, Data> * zero = 0;
636  return (std::pair<Key, Data>*) ((long) ptr - (long) &zero->second);
637  }
638 
639 
640 } // end namespace Aleph
641 
642 # endif // AHDRY_H
Definition: ah-comb.H:35
Definition: ahDry.H:41

Leandro Rabindranath León