GiNaC 1.8.7
idx.cpp
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#include "idx.h"
24#include "symbol.h"
25#include "lst.h"
26#include "relational.h"
27#include "operators.h"
28#include "archive.h"
29#include "utils.h"
30#include "hash_seed.h"
31
32#include <iostream>
33#include <sstream>
34#include <stdexcept>
35
36namespace GiNaC {
37
40 print_func<print_latex>(&idx::do_print_latex).
41 print_func<print_csrc>(&idx::do_print_csrc).
42 print_func<print_tree>(&idx::do_print_tree))
43
45 print_func<print_context>(&varidx::do_print).
46 print_func<print_latex>(&varidx::do_print_latex).
47 print_func<print_tree>(&varidx::do_print_tree))
48
50 print_func<print_context>(&spinidx::do_print).
51 print_func<print_latex>(&spinidx::do_print_latex).
52 print_func<print_tree>(&spinidx::do_print_tree))
53
55// default constructor
57
58idx::idx() {}
59
60varidx::varidx() : covariant(false)
61{
62}
63
64spinidx::spinidx() : dotted(false)
65{
66}
67
69// other constructors
71
72idx::idx(const ex & v, const ex & d) : value(v), dim(d)
73{
74 if (is_dim_numeric())
76 throw(std::invalid_argument("dimension of space must be a positive integer"));
77}
78
79varidx::varidx(const ex & v, const ex & d, bool cov) : inherited(v, d), covariant(cov)
80{
81}
82
83spinidx::spinidx(const ex & v, const ex & d, bool cov, bool dot) : inherited(v, d, cov), dotted(dot)
84{
85}
86
88// archiving
90
91void idx::read_archive(const archive_node& n, lst& sym_lst)
92{
93 inherited::read_archive(n, sym_lst);
94 n.find_ex("value", value, sym_lst);
95 n.find_ex("dim", dim, sym_lst);
96}
98
99void varidx::read_archive(const archive_node& n, lst& sym_lst)
100{
101 inherited::read_archive(n, sym_lst);
102 n.find_bool("covariant", covariant);
103}
105
107{
108 inherited::read_archive(n, sym_lst);
109 n.find_bool("dotted", dotted);
110}
112
114{
115 inherited::archive(n);
116 n.add_ex("value", value);
117 n.add_ex("dim", dim);
118}
119
121{
122 inherited::archive(n);
123 n.add_bool("covariant", covariant);
124}
125
127{
128 inherited::archive(n);
129 n.add_bool("dotted", dotted);
130}
131
133// functions overriding virtual functions from base classes
135
136void idx::print_index(const print_context & c, unsigned level) const
137{
138 bool need_parens = !(is_exactly_a<numeric>(value) || is_a<symbol>(value));
139 if (need_parens)
140 c.s << "(";
141 value.print(c);
142 if (need_parens)
143 c.s << ")";
145 c.s << "[";
146 dim.print(c);
147 c.s << "]";
148 }
149}
150
151void idx::do_print(const print_context & c, unsigned level) const
152{
153 c.s << ".";
154 print_index(c, level);
155}
156
157void idx::do_print_latex(const print_latex & c, unsigned level) const
158{
159 c.s << "{";
160 print_index(c, level);
161 c.s << "}";
162}
163
164void idx::do_print_csrc(const print_csrc & c, unsigned level) const
165{
166 c.s << "[";
168 c.s << ex_to<numeric>(value).to_int();
169 else
170 value.print(c);
171 c.s << "]";
172}
173
174void idx::do_print_tree(const print_tree & c, unsigned level) const
175{
176 c.s << std::string(level, ' ') << class_name() << " @" << this
177 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
178 << std::endl;
179 value.print(c, level + c.delta_indent);
180 dim.print(c, level + c.delta_indent);
181}
182
183void varidx::do_print(const print_context & c, unsigned level) const
184{
185 if (covariant)
186 c.s << ".";
187 else
188 c.s << "~";
189 print_index(c, level);
190}
191
192void varidx::do_print_tree(const print_tree & c, unsigned level) const
193{
194 c.s << std::string(level, ' ') << class_name() << " @" << this
195 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
196 << (covariant ? ", covariant" : ", contravariant")
197 << std::endl;
198 value.print(c, level + c.delta_indent);
199 dim.print(c, level + c.delta_indent);
200}
201
202void spinidx::do_print(const print_context & c, unsigned level) const
203{
204 if (covariant)
205 c.s << ".";
206 else
207 c.s << "~";
208 if (dotted)
209 c.s << "*";
210 print_index(c, level);
211}
212
213void spinidx::do_print_latex(const print_latex & c, unsigned level) const
214{
215 if (dotted)
216 c.s << "\\dot{";
217 else
218 c.s << "{";
219 print_index(c, level);
220 c.s << "}";
221}
222
223void spinidx::do_print_tree(const print_tree & c, unsigned level) const
224{
225 c.s << std::string(level, ' ') << class_name() << " @" << this
226 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
227 << (covariant ? ", covariant" : ", contravariant")
228 << (dotted ? ", dotted" : ", undotted")
229 << std::endl;
230 value.print(c, level + c.delta_indent);
231 dim.print(c, level + c.delta_indent);
232}
233
234bool idx::info(unsigned inf) const
235{
236 switch(inf) {
237 case info_flags::idx:
239 return true;
240 }
241 return inherited::info(inf);
242}
243
244size_t idx::nops() const
245{
246 // don't count the dimension as that is not really a sub-expression
247 return 1;
248}
249
250ex idx::op(size_t i) const
251{
252 GINAC_ASSERT(i == 0);
253 return value;
254}
255
257{
258 const ex &mapped_value = f(value);
259 if (are_ex_trivially_equal(value, mapped_value))
260 return *this;
261 else {
262 idx *copy = duplicate();
264 copy->value = mapped_value;
265 return *copy;
266 }
267}
268
271int idx::compare_same_type(const basic & other) const
272{
273 GINAC_ASSERT(is_a<idx>(other));
274 const idx &o = static_cast<const idx &>(other);
275
276 int cmpval = value.compare(o.value);
277 if (cmpval)
278 return cmpval;
279 return dim.compare(o.dim);
280}
281
282bool idx::match_same_type(const basic & other) const
283{
284 GINAC_ASSERT(is_a<idx>(other));
285 const idx &o = static_cast<const idx &>(other);
286
287 return dim.is_equal(o.dim);
288}
289
290int varidx::compare_same_type(const basic & other) const
291{
292 GINAC_ASSERT(is_a<varidx>(other));
293 const varidx &o = static_cast<const varidx &>(other);
294
295 int cmpval = inherited::compare_same_type(other);
296 if (cmpval)
297 return cmpval;
298
299 // Check variance last so dummy indices will end up next to each other
300 if (covariant != o.covariant)
301 return covariant ? -1 : 1;
302
303 return 0;
304}
305
306bool varidx::match_same_type(const basic & other) const
307{
308 GINAC_ASSERT(is_a<varidx>(other));
309 const varidx &o = static_cast<const varidx &>(other);
310
311 if (covariant != o.covariant)
312 return false;
313
314 return inherited::match_same_type(other);
315}
316
317int spinidx::compare_same_type(const basic & other) const
318{
319 GINAC_ASSERT(is_a<spinidx>(other));
320 const spinidx &o = static_cast<const spinidx &>(other);
321
322 // Check dottedness first so dummy indices will end up next to each other
323 if (dotted != o.dotted)
324 return dotted ? -1 : 1;
325
326 int cmpval = inherited::compare_same_type(other);
327 if (cmpval)
328 return cmpval;
329
330 return 0;
331}
332
333bool spinidx::match_same_type(const basic & other) const
334{
335 GINAC_ASSERT(is_a<spinidx>(other));
336 const spinidx &o = static_cast<const spinidx &>(other);
337
338 if (dotted != o.dotted)
339 return false;
340 return inherited::match_same_type(other);
341}
342
343unsigned idx::calchash() const
344{
345 // NOTE: The code in simplify_indexed() assumes that canonically
346 // ordered sequences of indices have the two members of dummy index
347 // pairs lying next to each other. The hash values for indices must
348 // be devised accordingly. The easiest (only?) way to guarantee the
349 // desired ordering is to make indices with the same value have equal
350 // hash keys. That is, the hash values must not depend on the index
351 // dimensions or other attributes (variance etc.).
352 // The compare_same_type() methods will take care of the rest.
353 unsigned v = make_hash_seed(typeid(*this));
354 v = rotate_left(v);
355 v ^= value.gethash();
356
357 // Store calculated hash value only if object is already evaluated
360 hashvalue = v;
361 }
362
363 return v;
364}
365
369{
370 return *this;
371}
372
373ex idx::subs(const exmap & m, unsigned options) const
374{
375 // First look for index substitutions
376 auto it = m.find(*this);
377 if (it != m.end()) {
378
379 // Substitution index->index
380 if (is_a<idx>(it->second) || (options & subs_options::really_subs_idx))
381 return it->second;
382
383 // Otherwise substitute value
384 idx *i_copy = duplicate();
385 i_copy->value = it->second;
387 return *i_copy;
388 }
389
390 // None, substitute objects in value (not in dimension)
391 const ex &subsed_value = value.subs(m, options);
392 if (are_ex_trivially_equal(value, subsed_value))
393 return *this;
394
395 idx *i_copy = duplicate();
396 i_copy->value = subsed_value;
398 return *i_copy;
399}
400
404ex idx::derivative(const symbol & s) const
405{
406 return _ex0;
407}
408
410// new virtual functions
412
413bool idx::is_dummy_pair_same_type(const basic & other) const
414{
415 const idx &o = static_cast<const idx &>(other);
416
417 // Only pure symbols form dummy pairs, "2n+1" doesn't
418 if (!is_a<symbol>(value))
419 return false;
420
421 // Value must be equal, of course
422 if (!value.is_equal(o.value))
423 return false;
424
425 // Dimensions need not be equal but must be comparable (so we can
426 // determine the minimum dimension of contractions)
427 if (dim.is_equal(o.dim))
428 return true;
429
430 return is_exactly_a<numeric>(dim) || is_exactly_a<numeric>(o.dim);
431}
432
433bool varidx::is_dummy_pair_same_type(const basic & other) const
434{
435 const varidx &o = static_cast<const varidx &>(other);
436
437 // Variance must be opposite
438 if (covariant == o.covariant)
439 return false;
440
441 return inherited::is_dummy_pair_same_type(other);
442}
443
445{
446 const spinidx &o = static_cast<const spinidx &>(other);
447
448 // Dottedness must be the same
449 if (dotted != o.dotted)
450 return false;
451
452 return inherited::is_dummy_pair_same_type(other);
453}
454
455
457// non-virtual functions
459
460ex idx::replace_dim(const ex & new_dim) const
461{
462 idx *i_copy = duplicate();
463 i_copy->dim = new_dim;
465 return *i_copy;
466}
467
468ex idx::minimal_dim(const idx & other) const
469{
470 return GiNaC::minimal_dim(dim, other.dim);
471}
472
474{
475 varidx *i_copy = duplicate();
476 i_copy->covariant = !i_copy->covariant;
478 return *i_copy;
479}
480
482{
483 spinidx *i_copy = duplicate();
484 i_copy->dotted = !i_copy->dotted;
486 return *i_copy;
487}
488
490{
491 spinidx *i_copy = duplicate();
492 i_copy->covariant = !i_copy->covariant;
493 i_copy->dotted = !i_copy->dotted;
495 return *i_copy;
496}
497
499// global functions
501
502bool is_dummy_pair(const idx & i1, const idx & i2)
503{
504 // The indices must be of exactly the same type
505 if (typeid(i1) != typeid(i2))
506 return false;
507
508 // Same type, let the indices decide whether they are paired
509 return i1.is_dummy_pair_same_type(i2);
510}
511
512bool is_dummy_pair(const ex & e1, const ex & e2)
513{
514 // The expressions must be indices
515 if (!is_a<idx>(e1) || !is_a<idx>(e2))
516 return false;
517
518 return is_dummy_pair(ex_to<idx>(e1), ex_to<idx>(e2));
519}
520
521void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator itend, exvector & out_free, exvector & out_dummy)
522{
523 out_free.clear();
524 out_dummy.clear();
525
526 // No indices? Then do nothing
527 if (it == itend)
528 return;
529
530 // Only one index? Then it is a free one if it's not numeric
531 if (itend - it == 1) {
532 if (ex_to<idx>(*it).is_symbolic())
533 out_free.push_back(*it);
534 return;
535 }
536
537 // Sort index vector. This will cause dummy indices come to lie next
538 // to each other (because the sort order is defined to guarantee this).
539 exvector v(it, itend);
540 shaker_sort(v.begin(), v.end(), ex_is_less(), ex_swap());
541
542 // Find dummy pairs and free indices
543 it = v.begin(); itend = v.end();
544 auto last = it++;
545 while (it != itend) {
546 if (is_dummy_pair(*it, *last)) {
547 out_dummy.push_back(*last);
548 it++;
549 if (it == itend)
550 return;
551 } else {
552 if (!it->is_equal(*last) && ex_to<idx>(*last).is_symbolic())
553 out_free.push_back(*last);
554 }
555 last = it++;
556 }
557 if (ex_to<idx>(*last).is_symbolic())
558 out_free.push_back(*last);
559}
560
561ex minimal_dim(const ex & dim1, const ex & dim2)
562{
563 if (dim1.is_equal(dim2) || dim1 < dim2 || (is_exactly_a<numeric>(dim1) && !is_a<numeric>(dim2)))
564 return dim1;
565 else if (dim1 > dim2 || (!is_a<numeric>(dim1) && is_exactly_a<numeric>(dim2)))
566 return dim2;
567 else {
568 std::ostringstream s;
569 s << "minimal_dim(): index dimensions " << dim1 << " and " << dim2 << " cannot be ordered";
570 throw (std::runtime_error(s.str()));
571 }
572}
573
574} // namespace GiNaC
Archiving of GiNaC expressions.
#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
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition: basic.h:105
const basic & clearflag(unsigned f) const
Clear some status_flags.
Definition: basic.h:291
const basic & setflag(unsigned f) const
Set some status_flags.
Definition: basic.h:288
unsigned hashvalue
hash value
Definition: basic.h:303
unsigned flags
of type status_flags
Definition: basic.h:302
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition: basic.cpp:719
virtual basic * duplicate() const
Create a clone of this object on the heap.
Definition: basic.h:131
Wrapper template for making GiNaC classes out of STL containers.
Definition: container.h:73
Lightweight wrapper for GiNaC's symbolic objects.
Definition: ex.h:72
unsigned gethash() const
Definition: ex.h:233
bool is_equal(const ex &other) const
Definition: ex.h:345
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:841
bool info(unsigned inf) const
Definition: ex.h:132
int compare(const ex &other) const
Definition: ex.h:322
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Definition: ex.cpp:56
This class holds one index of an indexed object.
Definition: idx.h:36
ex map(map_function &f) const override
Construct new expression by applying the specified function to all sub-expressions (one level only,...
Definition: idx.cpp:256
void print_index(const print_context &c, unsigned level) const
Definition: idx.cpp:136
ex derivative(const symbol &s) const override
Implementation of ex::diff() for an index always returns 0.
Definition: idx.cpp:404
ex dim
Dimension of space (can be symbolic or numeric)
Definition: idx.h:104
idx(const ex &v, const ex &dim)
Construct index with given value and dimension.
Definition: idx.cpp:72
void do_print_csrc(const print_csrc &c, unsigned level) const
Definition: idx.cpp:164
bool is_dim_numeric() const
Check whether the dimension is numeric.
Definition: idx.h:83
unsigned calchash() const override
Compute the hash value of an object and if it makes sense to store it in the objects status_flags,...
Definition: idx.cpp:343
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
Definition: idx.cpp:373
ex replace_dim(const ex &new_dim) const
Make a new index with the same value but a different dimension.
Definition: idx.cpp:460
ex op(size_t i) const override
Return operand/member at position i.
Definition: idx.cpp:250
ex value
Expression that constitutes the index (numeric or symbolic name)
Definition: idx.h:103
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
Definition: idx.cpp:282
virtual bool is_dummy_pair_same_type(const basic &other) const
Check whether the index forms a dummy index pair with another index of the same type.
Definition: idx.cpp:413
bool info(unsigned inf) const override
Information about the object.
Definition: idx.cpp:234
void do_print_latex(const print_latex &c, unsigned level) const
Definition: idx.cpp:157
size_t nops() const override
Number of operands/members.
Definition: idx.cpp:244
void do_print_tree(const print_tree &c, unsigned level) const
Definition: idx.cpp:174
void read_archive(const archive_node &n, lst &syms) override
Load (deserialize) the object from an archive node.
Definition: idx.cpp:91
ex minimal_dim(const idx &other) const
Return the minimum of the dimensions of this and another index.
Definition: idx.cpp:468
void do_print(const print_context &c, unsigned level) const
Definition: idx.cpp:151
void archive(archive_node &n) const override
Save (serialize) the object into archive node.
Definition: idx.cpp:113
ex evalf() const override
By default, basic::evalf would evaluate the index value but we don't want a.1 to become a.
Definition: idx.cpp:368
Base class for print_contexts.
Definition: print.h:103
Base context for C source output.
Definition: print.h:158
Context for latex-parsable output.
Definition: print.h:123
@ print_index_dimensions
print the dimensions of indices
Definition: print.h:57
Context for tree-like output for debugging.
Definition: print.h:147
This class holds a spinor index that can be dotted or undotted and that also has a variance.
Definition: idx.h:160
void read_archive(const archive_node &n, lst &syms) override
Load (deserialize) the object from an archive node.
Definition: idx.cpp:106
void do_print_latex(const print_latex &c, unsigned level) const
Definition: idx.cpp:213
void do_print(const print_context &c, unsigned level) const
Definition: idx.cpp:202
void archive(archive_node &n) const override
Save (serialize) the object into archive node.
Definition: idx.cpp:126
spinidx(const ex &v, const ex &dim=2, bool covariant=false, bool dotted=false)
Construct index with given value, dimension, variance and dot.
Definition: idx.cpp:64
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
Definition: idx.cpp:333
ex toggle_dot() const
Make a new index with the same value and variance but the opposite dottedness.
Definition: idx.cpp:481
bool is_dummy_pair_same_type(const basic &other) const override
Check whether the index forms a dummy index pair with another index of the same type.
Definition: idx.cpp:444
void do_print_tree(const print_tree &c, unsigned level) const
Definition: idx.cpp:223
bool dotted
Definition: idx.h:206
ex toggle_variance_dot() const
Make a new index with the same value but opposite variance and dottedness.
Definition: idx.cpp:489
@ evaluated
.eval() has already done its job
Definition: flags.h:203
@ hash_calculated
.calchash() has already done its job
Definition: flags.h:205
Basic CAS symbol.
Definition: symbol.h:39
This class holds an index with a variance (co- or contravariant).
Definition: idx.h:112
void read_archive(const archive_node &n, lst &syms) override
Load (deserialize) the object from an archive node.
Definition: idx.cpp:99
bool is_dummy_pair_same_type(const basic &other) const override
Check whether the index forms a dummy index pair with another index of the same type.
Definition: idx.cpp:433
varidx(const ex &v, const ex &dim, bool covariant=false)
Construct index with given value, dimension and variance.
Definition: idx.cpp:60
void do_print(const print_context &c, unsigned level) const
Definition: idx.cpp:183
void archive(archive_node &n) const override
Save (serialize) the object into archive node.
Definition: idx.cpp:120
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
Definition: idx.cpp:306
bool covariant
x.mu, default is contravariant: x~mu
Definition: idx.h:149
void do_print_tree(const print_tree &c, unsigned level) const
Definition: idx.cpp:192
ex toggle_variance() const
Make a new index with the same value but the opposite variance.
Definition: idx.cpp:473
static const bool value
Definition: factor.cpp:199
unsigned options
Definition: factor.cpp:2475
size_t n
Definition: factor.cpp:1432
size_t c
Definition: factor.cpp:757
mvec m
Definition: factor.cpp:758
size_t last
Definition: factor.cpp:1434
Type-specific hash seed.
Interface to GiNaC's indices.
Definition of GiNaC's lst.
Definition: add.cpp:38
ex minimal_dim(const ex &dim1, const ex &dim2)
Return the minimum of two index dimensions.
Definition: idx.cpp:561
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_dummy_pair(const idx &i1, const idx &i2)
Check whether two indices form a dummy pair.
Definition: idx.cpp:502
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
Definition: idx.cpp:45
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq, print_func< print_context >(&add::do_print). print_func< print_latex >(&add::do_print_latex). print_func< print_csrc >(&add::do_print_csrc). print_func< print_tree >(&add::do_print_tree). print_func< print_python_repr >(&add::do_print_python_repr)) add
Definition: add.cpp:40
static unsigned make_hash_seed(const std::type_info &tinfo)
We need a hash function which gives different values for objects of different types.
Definition: hash_seed.h:36
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
Definition: utils.h:48
void shaker_sort(It first, It last, Cmp comp, Swap swapit)
Definition: utils.h:193
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT_T(lst, basic, print_func< print_context >(&lst::do_print). print_func< print_tree >(&lst::do_print_tree)) template<> bool lst GINAC_BIND_UNARCHIVER(lst)
Specialization of container::info() for lst.
Definition: lst.cpp:42
const ex _ex0
Definition: utils.cpp:369
void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator itend, exvector &out_free, exvector &out_dummy)
Given a vector of indices, split them into two vectors, one containing the free indices,...
Definition: idx.cpp:521
std::vector< ex > exvector
Definition: basic.h:48
Interface to GiNaC's overloaded operators.
Interface to relations between expressions.
Function object for map().
Definition: basic.h:85
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...

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