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 find(const ex &pattern, exset &found) const
Find all occurrences of a pattern.
Definition ex.cpp:107
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
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 ls GINAC_BIND_UNARCHIVER)(lst)
Specialization of container::info() for lst.
Definition lst.cpp:42
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
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
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.
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
Definition registrar.h:185
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.