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