GiNaC 1.8.7
container.h
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2023 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
39namespace GiNaC {
40
42template <template <class T, class = std::allocator<T>> class C>
44protected:
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*
60protected:
62};
63
64template <>
65inline void container_storage<std::vector>::reserve(size_t n) { seq.reserve(n); }
66
67template <>
68inline void container_storage<std::vector>::reserve(std::vector<ex> & v, size_t n) { v.reserve(n); }
69
70
72template <template <class T, class = std::allocator<T>> class C>
73class container : public basic, public container_storage<C> {
75protected:
77
78public:
79 typedef typename STLT::const_iterator const_iterator;
80 typedef typename STLT::const_reverse_iterator const_reverse_iterator;
81
82protected:
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
89public:
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
115public:
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
146protected:
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
199protected:
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
213private:
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
230public:
231 container & prepend(const ex & b);
232 container & append(const ex & b);
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
244protected:
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
253template <template <class T, class = std::allocator<T>> class C>
255{
256 setflag(get_default_flags());
257}
258
259template <template <class T, class = std::allocator<T>> class C>
260void 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
266template <template <class T, class = std::allocator<T>> class C>
267void 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
281template <template <class T, class = std::allocator<T>> class C>
282void container<C>::do_print_python(const print_python & c, unsigned level) const
283{
284 printseq(c, '[', ',', ']', precedence(), precedence()+1);
285}
286
287template <template <class T, class = std::allocator<T>> class C>
288void 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
294template <template <class T, class = std::allocator<T>> class C>
295ex 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
304template <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
315template <template <class T, class = std::allocator<T>> class C>
316ex 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
342template <template <class T, class = std::allocator<T>> class C>
343int 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
361template <template <class T, class = std::allocator<T>> class C>
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
381template <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
390template <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
399template <template <class T, class = std::allocator<T>> class C>
401{
402 ensure_if_modifiable();
403 this->seq.pop_front();
404 return *this;
405}
406
408template <template <class T, class = std::allocator<T>> class C>
410{
411 ensure_if_modifiable();
412 this->seq.pop_back();
413 return *this;
414}
415
417template <template <class T, class = std::allocator<T>> class C>
419{
420 ensure_if_modifiable();
421 this->seq.clear();
422 return *this;
423}
424
426template <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
435template<> inline void container<std::list>::unique_()
436{
437 this->seq.unique(ex_is_equal());
438}
439
441template <template <class T, class = std::allocator<T>> class C>
443{
444 ensure_if_modifiable();
445 unique_();
446 return *this;
447}
448
450template <template <class T, class = std::allocator<T>> class C>
451void 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
473template <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
Archiving of GiNaC expressions.
Assertion macro definition.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition: assertion.h:33
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Definition: archive.h:49
std::vector< property >::const_iterator archive_node_cit
Definition: archive.h:84
void add_ex(const std::string &name, const ex &value)
Add property of type "ex" to node.
Definition: archive.cpp:410
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition: basic.h:105
const basic & setflag(unsigned f) const
Set some status_flags.
Definition: basic.h:288
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition: basic.cpp:719
Helper template for encapsulating the reserve() mechanics of STL containers.
Definition: container.h:43
container_storage(In b, In e)
Definition: container.h:52
static void reserve(STLT &, size_t)
Definition: container.h:55
void reserve(size_t)
Definition: container.h:54
container_storage(std::initializer_list< ex > il)
Definition: container.h:49
container_storage(size_t n, const ex &e)
Definition: container.h:48
Wrapper template for making GiNaC classes out of STL containers.
Definition: container.h:73
const_reverse_iterator rend() const
Definition: container.h:242
container(exvector::const_iterator b, exvector::const_iterator e)
Definition: container.h:102
static unsigned get_default_flags()
Specialization of container::get_default_flags() for lst.
Definition: container.h:84
STLT subschildren(const exmap &m, unsigned options=0) const
Definition: container.h:474
container(std::initializer_list< ex > il)
Definition: container.h:108
ex real_part() const override
Definition: container.h:174
const_reverse_iterator rbegin() const
Definition: container.h:241
bool is_equal_same_type(const basic &other) const override
Returns true if two objects of same type are equal.
Definition: container.h:362
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
const_iterator end() const
Definition: container.h:240
container & prepend(const ex &b)
Add element at front.
Definition: container.h:382
STLT::const_iterator const_iterator
Definition: container.h:79
ex conjugate() const override
Definition: container.h:147
void read_archive(const archive_node &n, lst &sym_lst) override
Load (deserialize) the object from an archive node.
Definition: container.h:123
const_iterator begin() const
Definition: container.h:239
void archive(archive_node &n) const override
Archive the object.
Definition: container.h:138
container(STLT const &s)
Definition: container.h:90
bool info(unsigned inf) const override
Information about the object.
Definition: container.h:116
size_t nops() const override
Number of operands/members.
Definition: container.h:118
void do_print_python_repr(const print_python_repr &c, unsigned level) const
Definition: container.h:288
container & remove_last()
Remove last element.
Definition: container.h:409
virtual ex thiscontainer(STLT &&v) const
Similar to duplicate(), but with a preset sequence (which gets pilfered).
Definition: container.h:206
STLT::const_reverse_iterator const_reverse_iterator
Definition: container.h:80
void sort_(std::random_access_iterator_tag)
Definition: container.h:214
container_storage< C >::STLT STLT
Definition: container.h:76
ex op(size_t i) const override
Return operand/member at position i.
Definition: container.h:295
container & sort()
Sort elements.
Definition: container.h:427
void sort_(std::input_iterator_tag)
Definition: container.h:219
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Definition: container.h:117
container & unique()
Remove adjacent duplicate elements.
Definition: container.h:442
void do_print(const print_context &c, unsigned level) const
Definition: container.h:260
container & remove_all()
Remove all elements.
Definition: container.h:418
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
Definition: container.h:316
ex & let_op(size_t i) override
Return modifiable operand/member at position i.
Definition: container.h:305
static char get_close_delim()
Specialization of container::get_close_delim() for lst.
Definition: container.h:86
container & remove_first()
Remove first element.
Definition: container.h:400
virtual ex thiscontainer(const STLT &v) const
Similar to duplicate(), but with a preset sequence.
Definition: container.h:202
void do_print_tree(const print_tree &c, unsigned level) const
Definition: container.h:267
static char get_open_delim()
Specialization of container::get_open_delim() for lst.
Definition: container.h:85
container & append(const ex &b)
Add element at back.
Definition: container.h:391
container(STLT &&v)
Definition: container.h:96
void do_print_python(const print_python &c, unsigned level) const
Definition: container.h:282
ex imag_part() const override
Definition: container.h:185
Lightweight wrapper for GiNaC's symbolic objects.
Definition: ex.h:72
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:841
Base class for print_contexts.
Definition: print.h:103
Context for python-parsable output.
Definition: print.h:139
Context for python pretty-print output.
Definition: print.h:131
Context for tree-like output for debugging.
Definition: print.h:147
Definition of optimizing macros.
Interface to GiNaC's light-weight expression handles.
unsigned options
Definition: factor.cpp:2475
size_t n
Definition: factor.cpp:1432
size_t c
Definition: factor.cpp:757
ex x
Definition: factor.cpp:1610
mvec m
Definition: factor.cpp:758
ex cont
Definition: factor.cpp:2191
Definition: add.cpp:38
std::map< ex, ex, ex_is_less > exmap
Definition: basic.h:50
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:699
bool is_a(const basic &obj)
Check if obj is a T, including base classes.
Definition: basic.h:313
size_t nops(const ex &thisex)
Definition: ex.h:727
Definition of helper classes for expression output.
#define GINAC_DECLARE_REGISTERED_CLASS(classname, supername)
Macro for inclusion in the declaration of each registered class.
Definition: registrar.h:153

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