GiNaC  1.8.0
container.h
Go to the documentation of this file.
1 
5 /*
6  * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #ifndef GINAC_CONTAINER_H
24 #define GINAC_CONTAINER_H
25 
26 #include "ex.h"
27 #include "print.h"
28 #include "archive.h"
29 #include "assertion.h"
30 #include "compiler.h"
31 
32 #include <algorithm>
33 #include <iterator>
34 #include <list>
35 #include <memory>
36 #include <stdexcept>
37 #include <vector>
38 
39 namespace GiNaC {
40 
42 template <template <class T, class = std::allocator<T>> class C>
44 protected:
45  typedef C<ex> STLT;
46 
48  container_storage(size_t n, const ex & e) : seq(n, e) {}
49  container_storage(std::initializer_list<ex> il) : seq(il) {}
50 
51  template <class In>
52  container_storage(In b, In e) : seq(b, e) {}
53 
54  void reserve(size_t) {}
55  static void reserve(STLT &, size_t) {}
56 
58 
59  // disallow destruction of container through a container_storage*
60 protected:
62 };
63 
64 template <>
65 inline void container_storage<std::vector>::reserve(size_t n) { seq.reserve(n); }
66 
67 template <>
68 inline void container_storage<std::vector>::reserve(std::vector<ex> & v, size_t n) { v.reserve(n); }
69 
70 
72 template <template <class T, class = std::allocator<T>> class C>
73 class container : public basic, public container_storage<C> {
75 protected:
76  typedef typename container_storage<C>::STLT STLT;
77 
78 public:
79  typedef typename STLT::const_iterator const_iterator;
80  typedef typename STLT::const_reverse_iterator const_reverse_iterator;
81 
82 protected:
83  // helpers
84  static unsigned get_default_flags() { return 0; }
85  static char get_open_delim() { return '('; }
86  static char get_close_delim() { return ')'; }
87 
88  // constructors
89 public:
90  container(STLT const & s)
91  {
93  this->seq = s;
94  }
95 
96  explicit container(STLT && v)
97  {
99  this->seq.swap(v);
100  }
101 
102  container(exvector::const_iterator b, exvector::const_iterator e)
103  : container_storage<C>(b, e)
104  {
106  }
107 
108  container(std::initializer_list<ex> il)
109  : container_storage<C>(il)
110  {
112  }
113 
114  // functions overriding virtual functions from base classes
115 public:
116  bool info(unsigned inf) const override { return inherited::info(inf); }
117  unsigned precedence() const override { return 10; }
118  size_t nops() const override { return this->seq.size(); }
119  ex op(size_t i) const override;
120  ex & let_op(size_t i) override;
121  ex subs(const exmap & m, unsigned options = 0) const override;
122 
123  void read_archive(const archive_node &n, lst &sym_lst) override
124  {
125  inherited::read_archive(n, sym_lst);
127 
128  auto range = n.find_property_range("seq", "seq");
129  this->reserve(this->seq, range.end - range.begin);
130  for (archive_node::archive_node_cit i=range.begin; i<range.end; ++i) {
131  ex e;
132  n.find_ex_by_loc(i, e, sym_lst);
133  this->seq.emplace_back(e);
134  }
135  }
136 
138  void archive(archive_node &n) const override
139  {
140  inherited::archive(n);
141  for (auto & i : this->seq) {
142  n.add_ex("seq", i);
143  }
144  }
145 
146 protected:
147  ex conjugate() const override
148  {
149  STLT *newcont = nullptr;
150  for (const_iterator i=this->seq.begin(); i!=this->seq.end(); ++i) {
151  if (newcont) {
152  newcont->push_back(i->conjugate());
153  continue;
154  }
155  ex x = i->conjugate();
156  if (are_ex_trivially_equal(x, *i)) {
157  continue;
158  }
159  newcont = new STLT;
160  this->reserve(*newcont, this->seq.size());
161  for (const_iterator j=this->seq.begin(); j!=i; ++j) {
162  newcont->push_back(*j);
163  }
164  newcont->push_back(x);
165  }
166  if (newcont) {
167  ex result = thiscontainer(*newcont);
168  delete newcont;
169  return result;
170  }
171  return *this;
172  }
173 
174  ex real_part() const override
175  {
176  STLT cont;
177  this->reserve(cont, nops());
178  const_iterator b = begin();
179  const_iterator e = end();
180  for(const_iterator i=b; i!=e; ++i)
181  cont.push_back(i->real_part());
182  return thiscontainer(cont);
183  }
184 
185  ex imag_part() const override
186  {
187  STLT cont;
188  this->reserve(cont, nops());
189  const_iterator b = begin();
190  const_iterator e = end();
191  for(const_iterator i=b; i!=e; ++i)
192  cont.push_back(i->imag_part());
193  return thiscontainer(cont);
194  }
195 
196  bool is_equal_same_type(const basic & other) const override;
197 
198  // new virtual functions which can be overridden by derived classes
199 protected:
202  virtual ex thiscontainer(const STLT & v) const { return container(v); }
203 
206  virtual ex thiscontainer(STLT && v) const { return container(std::move(v)); }
207 
208  virtual void printseq(const print_context & c, char openbracket, char delim,
209  char closebracket, unsigned this_precedence,
210  unsigned upper_precedence = 0) const;
211 
212  // non-virtual functions in this class
213 private:
214  void sort_(std::random_access_iterator_tag)
215  {
216  std::sort(this->seq.begin(), this->seq.end(), ex_is_less());
217  }
218 
219  void sort_(std::input_iterator_tag)
220  {
221  this->seq.sort(ex_is_less());
222  }
223 
224  void unique_()
225  {
226  typename STLT::iterator p = std::unique(this->seq.begin(), this->seq.end(), ex_is_equal());
227  this->seq.erase(p, this->seq.end());
228  }
229 
230 public:
231  container & prepend(const ex & b);
232  container & append(const ex & b);
235  container & remove_all();
236  container & sort();
237  container & unique();
238 
239  const_iterator begin() const {return this->seq.begin();}
240  const_iterator end() const {return this->seq.end();}
241  const_reverse_iterator rbegin() const {return this->seq.rbegin();}
242  const_reverse_iterator rend() const {return this->seq.rend();}
243 
244 protected:
245  void do_print(const print_context & c, unsigned level) const;
246  void do_print_tree(const print_tree & c, unsigned level) const;
247  void do_print_python(const print_python & c, unsigned level) const;
248  void do_print_python_repr(const print_python_repr & c, unsigned level) const;
249  STLT subschildren(const exmap & m, unsigned options = 0) const;
250 };
251 
253 template <template <class T, class = std::allocator<T>> class C>
255 {
256  setflag(get_default_flags());
257 }
258 
259 template <template <class T, class = std::allocator<T>> class C>
260 void container<C>::do_print(const print_context & c, unsigned level) const
261 {
262  // always print brackets around seq, ignore upper_precedence
263  printseq(c, get_open_delim(), ',', get_close_delim(), precedence(), precedence()+1);
264 }
265 
266 template <template <class T, class = std::allocator<T>> class C>
267 void container<C>::do_print_tree(const print_tree & c, unsigned level) const
268 {
269  c.s << std::string(level, ' ') << class_name() << " @" << this
270  << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
271  << ", nops=" << nops()
272  << std::endl;
273  const_iterator i = this->seq.begin(), end = this->seq.end();
274  while (i != end) {
275  i->print(c, level + c.delta_indent);
276  ++i;
277  }
278  c.s << std::string(level + c.delta_indent,' ') << "=====" << std::endl;
279 }
280 
281 template <template <class T, class = std::allocator<T>> class C>
282 void container<C>::do_print_python(const print_python & c, unsigned level) const
283 {
284  printseq(c, '[', ',', ']', precedence(), precedence()+1);
285 }
286 
287 template <template <class T, class = std::allocator<T>> class C>
288 void container<C>::do_print_python_repr(const print_python_repr & c, unsigned level) const
289 {
290  c.s << class_name();
291  printseq(c, '(', ',', ')', precedence(), precedence()+1);
292 }
293 
294 template <template <class T, class = std::allocator<T>> class C>
295 ex container<C>::op(size_t i) const
296 {
297  GINAC_ASSERT(i < nops());
298 
299  const_iterator it = this->seq.begin();
300  advance(it, i);
301  return *it;
302 }
303 
304 template <template <class T, class = std::allocator<T>> class C>
306 {
307  GINAC_ASSERT(i < nops());
308 
309  ensure_if_modifiable();
310  typename STLT::iterator it = this->seq.begin();
311  advance(it, i);
312  return *it;
313 }
314 
315 template <template <class T, class = std::allocator<T>> class C>
316 ex container<C>::subs(const exmap & m, unsigned options) const
317 {
318  // After having subs'ed all children, this method subs'es one final
319  // level, but only if the intermediate result is a container! This is
320  // because if the intermediate result has eval'ed to a non-container a
321  // last level substitution would be wrong, as this example involving a
322  // function f and its inverse f^-1 shows:
323  // f(x).subs(x==f^-1(x))
324  // -> f(f^-1(x)) [subschildren]
325  // -> x [eval] /* must not subs(x==f^-1(x))! */
326  STLT subsed = subschildren(m, options);
327  if (!subsed.empty()) {
328  ex result(thiscontainer(subsed));
329  if (is_a<container<C>>(result))
330  return ex_to<basic>(result).subs_one_level(m, options);
331  else
332  return result;
333  } else {
334  if (is_a<container<C>>(*this))
335  return subs_one_level(m, options);
336  else
337  return *this;
338  }
339 }
340 
342 template <template <class T, class = std::allocator<T>> class C>
343 int container<C>::compare_same_type(const basic & other) const
344 {
345  GINAC_ASSERT(is_a<container>(other));
346  const container & o = static_cast<const container &>(other);
347 
348  const_iterator it1 = this->seq.begin(), it1end = this->seq.end(),
349  it2 = o.seq.begin(), it2end = o.seq.end();
350 
351  while (it1 != it1end && it2 != it2end) {
352  int cmpval = it1->compare(*it2);
353  if (cmpval)
354  return cmpval;
355  ++it1; ++it2;
356  }
357 
358  return (it1 == it1end) ? (it2 == it2end ? 0 : -1) : 1;
359 }
360 
361 template <template <class T, class = std::allocator<T>> class C>
362 bool container<C>::is_equal_same_type(const basic & other) const
363 {
364  GINAC_ASSERT(is_a<container>(other));
365  const container & o = static_cast<const container &>(other);
366 
367  if (this->seq.size() != o.seq.size())
368  return false;
369 
370  const_iterator it1 = this->seq.begin(), it1end = this->seq.end(), it2 = o.seq.begin();
371  while (it1 != it1end) {
372  if (!it1->is_equal(*it2))
373  return false;
374  ++it1; ++it2;
375  }
376 
377  return true;
378 }
379 
381 template <template <class T, class = std::allocator<T>> class C>
383 {
384  ensure_if_modifiable();
385  this->seq.push_front(b);
386  return *this;
387 }
388 
390 template <template <class T, class = std::allocator<T>> class C>
392 {
393  ensure_if_modifiable();
394  this->seq.push_back(b);
395  return *this;
396 }
397 
399 template <template <class T, class = std::allocator<T>> class C>
401 {
402  ensure_if_modifiable();
403  this->seq.pop_front();
404  return *this;
405 }
406 
408 template <template <class T, class = std::allocator<T>> class C>
410 {
411  ensure_if_modifiable();
412  this->seq.pop_back();
413  return *this;
414 }
415 
417 template <template <class T, class = std::allocator<T>> class C>
419 {
420  ensure_if_modifiable();
421  this->seq.clear();
422  return *this;
423 }
424 
426 template <template <class T, class = std::allocator<T>> class C>
428 {
429  ensure_if_modifiable();
430  sort_(typename std::iterator_traits<typename STLT::iterator>::iterator_category());
431  return *this;
432 }
433 
435 template<> inline void container<std::list>::unique_()
436 {
437  this->seq.unique(ex_is_equal());
438 }
439 
441 template <template <class T, class = std::allocator<T>> class C>
443 {
444  ensure_if_modifiable();
445  unique_();
446  return *this;
447 }
448 
450 template <template <class T, class = std::allocator<T>> class C>
451 void container<C>::printseq(const print_context & c, char openbracket, char delim,
452  char closebracket, unsigned this_precedence,
453  unsigned upper_precedence) const
454 {
455  if (this_precedence <= upper_precedence)
456  c.s << openbracket;
457 
458  if (!this->seq.empty()) {
459  const_iterator it = this->seq.begin(), itend = this->seq.end();
460  --itend;
461  while (it != itend) {
462  it->print(c, this_precedence);
463  c.s << delim;
464  ++it;
465  }
466  it->print(c, this_precedence);
467  }
468 
469  if (this_precedence <= upper_precedence)
470  c.s << closebracket;
471 }
472 
473 template <template <class T, class = std::allocator<T>> class C>
475 {
476  // returns an empty container if nothing had to be substituted
477  // returns a STLT with substituted elements otherwise
478 
479  const_iterator cit = this->seq.begin(), end = this->seq.end();
480  while (cit != end) {
481  const ex & subsed_ex = cit->subs(m, options);
482  if (!are_ex_trivially_equal(*cit, subsed_ex)) {
483 
484  // copy first part of seq which hasn't changed
485  STLT s(this->seq.begin(), cit);
486  this->reserve(s, this->seq.size());
487 
488  // insert changed element
489  s.push_back(subsed_ex);
490  ++cit;
491 
492  // copy rest
493  while (cit != end) {
494  s.push_back(cit->subs(m, options));
495  ++cit;
496  }
497 
498  return s;
499  }
500 
501  ++cit;
502  }
503 
504  return STLT(); // nothing has changed
505 }
506 
507 } // namespace GiNaC
508 
509 #endif // ndef GINAC_CONTAINER_H
GiNaC::is_a
bool is_a(const basic &obj)
Check if obj is a T, including base classes.
Definition: basic.h:313
GiNaC::container::append
container & append(const ex &b)
Add element at back.
Definition: container.h:391
GiNaC::print_python_repr
Context for python-parsable output.
Definition: print.h:139
GiNaC::const_iterator
Definition: ex.h:370
GiNaC::container_storage::container_storage
container_storage(std::initializer_list< ex > il)
Definition: container.h:49
GiNaC::ex_is_equal
Definition: ex.h:694
GiNaC::container::remove_last
container & remove_last()
Remove last element.
Definition: container.h:409
assertion.h
Assertion macro definition.
GiNaC::container::STLT
container_storage< C >::STLT STLT
Definition: container.h:76
GiNaC::container::get_default_flags
static unsigned get_default_flags()
Specialization of container::get_default_flags() for lst.
Definition: container.h:84
GiNaC::container::const_reverse_iterator
STLT::const_reverse_iterator const_reverse_iterator
Definition: container.h:80
GiNaC::container::get_open_delim
static char get_open_delim()
Specialization of container::get_open_delim() for lst.
Definition: container.h:85
GiNaC::ex::subs
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:826
GiNaC::print_context
Base class for print_contexts.
Definition: print.h:103
GiNaC::container::precedence
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Definition: container.h:117
GiNaC::container::rend
const_reverse_iterator rend() const
Definition: container.h:242
GiNaC::container::do_print_python_repr
void do_print_python_repr(const print_python_repr &c, unsigned level) const
Definition: container.h:288
GiNaC::archive_node::add_ex
void add_ex(const std::string &name, const ex &value)
Add property of type "ex" to node.
Definition: archive.cpp:410
GiNaC::container_storage::seq
STLT seq
Definition: container.h:57
GiNaC::archive_node
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Definition: archive.h:49
GiNaC::container_storage::reserve
void reserve(size_t)
Definition: container.h:54
options
unsigned options
Definition: factor.cpp:2480
m
mvec m
Definition: factor.cpp:771
GiNaC::container::begin
const_iterator begin() const
Definition: container.h:239
GiNaC::container::get_close_delim
static char get_close_delim()
Specialization of container::get_close_delim() for lst.
Definition: container.h:86
GiNaC
Definition: add.cpp:38
GiNaC::container::is_equal_same_type
bool is_equal_same_type(const basic &other) const override
Returns true if two objects of same type are equal.
Definition: container.h:362
GiNaC::container_storage::~container_storage
~container_storage()
Definition: container.h:61
GiNaC::container::prepend
container & prepend(const ex &b)
Add element at front.
Definition: container.h:382
GiNaC::container_storage::reserve
static void reserve(STLT &, size_t)
Definition: container.h:55
GiNaC::are_ex_trivially_equal
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
Definition: ex.h:684
GiNaC::container::end
const_iterator end() const
Definition: container.h:240
GiNaC::container::unique
container & unique()
Remove adjacent duplicate elements.
Definition: container.h:442
x
ex x
Definition: factor.cpp:1641
GINAC_DECLARE_REGISTERED_CLASS
#define GINAC_DECLARE_REGISTERED_CLASS(classname, supername)
Macro for inclusion in the declaration of each registered class.
Definition: registrar.h:153
GiNaC::container::const_iterator
STLT::const_iterator const_iterator
Definition: container.h:79
GiNaC::container::unique_
void unique_()
Definition: container.h:224
GiNaC::container::read_archive
void read_archive(const archive_node &n, lst &sym_lst) override
Load (deserialize) the object from an archive node.
Definition: container.h:123
GiNaC::ex
Lightweight wrapper for GiNaC's symbolic objects.
Definition: ex.h:72
GiNaC::basic::compare_same_type
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition: basic.cpp:719
GiNaC::print_python
Context for python pretty-print output.
Definition: print.h:131
GiNaC::container::archive
void archive(archive_node &n) const override
Archive the object.
Definition: container.h:138
GiNaC::container::rbegin
const_reverse_iterator rbegin() const
Definition: container.h:241
GiNaC::container::subschildren
STLT subschildren(const exmap &m, unsigned options=0) const
Definition: container.h:474
GiNaC::container::sort
container & sort()
Sort elements.
Definition: container.h:427
ex.h
Interface to GiNaC's light-weight expression handles.
GiNaC::container::op
ex op(size_t i) const override
Return operand/member at position i.
Definition: container.h:295
GiNaC::container::container
container(std::initializer_list< ex > il)
Definition: container.h:108
print.h
Definition of helper classes for expression output.
GiNaC::container::remove_first
container & remove_first()
Remove first element.
Definition: container.h:400
compiler.h
Definition of optimizing macros.
GiNaC::container::remove_all
container & remove_all()
Remove all elements.
Definition: container.h:418
GiNaC::container::subs
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
Definition: container.h:316
GiNaC::archive_node::archive_node_cit
std::vector< property >::const_iterator archive_node_cit
Definition: archive.h:84
GiNaC::container::real_part
ex real_part() const override
Definition: container.h:174
GiNaC::print_tree
Context for tree-like output for debugging.
Definition: print.h:147
GiNaC::container_storage
Helper template for encapsulating the reserve() mechanics of STL containers.
Definition: container.h:43
GiNaC::container_storage::container_storage
container_storage()
Definition: container.h:47
GiNaC::container::container
container(STLT const &s)
Definition: container.h:90
GiNaC::container::let_op
ex & let_op(size_t i) override
Return modifiable operand/member at position i.
Definition: container.h:305
GiNaC::container::container
container(STLT &&v)
Definition: container.h:96
GiNaC::basic::setflag
const basic & setflag(unsigned f) const
Set some status_flags.
Definition: basic.h:288
GiNaC::container::do_print_tree
void do_print_tree(const print_tree &c, unsigned level) const
Definition: container.h:267
GiNaC::container
Wrapper template for making GiNaC classes out of STL containers.
Definition: container.h:73
GiNaC::container::imag_part
ex imag_part() const override
Definition: container.h:185
c
size_t c
Definition: factor.cpp:770
GiNaC::exmap
std::map< ex, ex, ex_is_less > exmap
Definition: basic.h:50
GiNaC::container::printseq
virtual void printseq(const print_context &c, char openbracket, char delim, char closebracket, unsigned this_precedence, unsigned upper_precedence=0) const
Print sequence of contained elements.
Definition: container.h:451
archive.h
Archiving of GiNaC expressions.
GiNaC::container::container
container(exvector::const_iterator b, exvector::const_iterator e)
Definition: container.h:102
n
size_t n
Definition: factor.cpp:1463
GiNaC::container_storage::container_storage
container_storage(size_t n, const ex &e)
Definition: container.h:48
GiNaC::container::conjugate
ex conjugate() const override
Definition: container.h:147
GiNaC::basic
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition: basic.h:105
GiNaC::container::do_print_python
void do_print_python(const print_python &c, unsigned level) const
Definition: container.h:282
GiNaC::container_storage::container_storage
container_storage(In b, In e)
Definition: container.h:52
GiNaC::nops
size_t nops(const ex &thisex)
Definition: ex.h:712
GiNaC::container::thiscontainer
virtual ex thiscontainer(STLT &&v) const
Similar to duplicate(), but with a preset sequence (which gets pilfered).
Definition: container.h:206
GiNaC::container::nops
size_t nops() const override
Number of operands/members.
Definition: container.h:118
GiNaC::container::do_print
void do_print(const print_context &c, unsigned level) const
Definition: container.h:260
GiNaC::container::sort_
void sort_(std::input_iterator_tag)
Definition: container.h:219
GiNaC::container::thiscontainer
virtual ex thiscontainer(const STLT &v) const
Similar to duplicate(), but with a preset sequence.
Definition: container.h:202
GiNaC::container::sort_
void sort_(std::random_access_iterator_tag)
Definition: container.h:214
GINAC_ASSERT
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition: assertion.h:33
GiNaC::ex_is_less
Definition: ex.h:690
GiNaC::container::info
bool info(unsigned inf) const override
Information about the object.
Definition: container.h:116
GiNaC::container_storage::STLT
C< ex > STLT
Definition: container.h:45

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.