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