70 symmetry::symmetry(
unsigned i) : type(none)
89 inherited::read_archive(
n, sym_lst);
91 if (!(
n.find_unsigned(
"type", t)))
92 throw (std::runtime_error(
"unknown symmetry type in archive"));
98 if (
n.find_ex(
"child", e, sym_lst, i))
99 add(ex_to<symmetry>(e));
108 if (
n.find_unsigned(
"index", u, i))
121 inherited::archive(
n);
123 n.add_unsigned(
"type",
type);
127 n.add_unsigned(
"index", i);
131 n.add_ex(
"child", i);
145 const symmetry &othersymm = ex_to<symmetry>(other);
154 size_t this_size =
indices.size();
155 size_t that_size = othersymm.
indices.size();
156 if (this_size > that_size)
158 if (this_size < that_size)
161 for (
auto i=
indices.begin(),j=othersymm.
indices.begin(); i!=end; ++i,++j) {
173 for (
size_t i=0; i<
children.size(); ++i) {
174 int cmpval = ex_to<symmetry>(
children[i])
215 case none:
c.s <<
'!';
break;
218 case cyclic:
c.s <<
'@';
break;
219 default:
c.s <<
'?';
break;
223 for (
size_t i=0; i<num; i++) {
234 c.s << std::string(level,
' ') << class_name() <<
" @" <<
this 235 << std::hex <<
", hash=0x" <<
hashvalue <<
", flags=0x" <<
flags << std::dec
239 case none:
c.s <<
"none";
break;
242 case cyclic:
c.s <<
"cycl";
break;
243 default:
c.s <<
"<unknown>";
break;
246 c.s <<
", indices=(";
257 i.print(
c, level +
c.delta_indent);
295 throw (std::logic_error(
"symmetry:add(): children must have same number of indices"));
299 std::set<unsigned> un;
300 set_union(
indices.begin(),
indices.end(),
c.indices.begin(),
c.indices.end(), inserter(un, un.begin()));
301 if (un.size() !=
indices.size() +
c.indices.size())
302 throw (std::logic_error(
"symmetry::add(): the same index appears in more than one child"));
315 throw (std::range_error(
"symmetry::verify(): index values are out of range"));
317 for (
unsigned i=0; i<
n; i++)
328 static ex s = dynallocate<symmetry>(0);
329 return ex_to<symmetry>(s);
334 static ex s = dynallocate<symmetry>(1);
335 return ex_to<symmetry>(s);
340 static ex s = dynallocate<symmetry>(2);
341 return ex_to<symmetry>(s);
346 static ex s = dynallocate<symmetry>(3);
347 return ex_to<symmetry>(s);
352 static ex s = dynallocate<symmetry>();
353 return ex_to<symmetry>(s);
359 return ex_to<symmetry>(s);
365 return ex_to<symmetry>(s);
371 return ex_to<symmetry>(s);
377 return ex_to<symmetry>(s);
383 return ex_to<symmetry>(s);
389 return ex_to<symmetry>(s);
393 exvector::iterator
v;
402 GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
403 auto ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
404 while (ait != aitend) {
405 int cmpval =
v[*ait].compare(
v[*bit]);
417 exvector::iterator
v;
428 GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
429 auto ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
430 while (ait != aitend) {
431 v[*ait].swap(
v[*bit]);
441 if (
symm.indices.size() < 2)
442 return std::numeric_limits<int>::max();
445 bool something_changed =
false;
448 while (first !=
last) {
450 int child_sign =
canonicalize(v, ex_to<symmetry>(*first));
453 if (child_sign != std::numeric_limits<int>::max()) {
454 something_changed =
true;
480 return something_changed ? sign : std::numeric_limits<int>::max();
485 static ex symm(
const ex & e, exvector::const_iterator first, exvector::const_iterator
last,
bool asymmetric)
488 unsigned num =
last - first;
496 unsigned *iv =
new unsigned[num], *iv2;
497 for (
unsigned i=0; i<num; i++)
499 iv2 = (asymmetric ?
new unsigned[num] :
nullptr);
505 while (std::next_permutation(iv, iv + num)) {
507 for (
unsigned i=0; i<num; i++)
511 memcpy(iv2, iv, num *
sizeof(
unsigned));
514 sum_v.push_back(term);
516 ex sum = dynallocate<add>(sum_v);
537 unsigned num =
last - first;
543 lst new_lst = orig_lst;
548 for (
unsigned i=0; i<num-1; i++) {
549 ex perm = new_lst.
op(0);
560 return symm(*
this, v.begin(), v.end(),
false);
567 return symm(*
this, v.begin(), v.end(),
true);
unsigned calchash() const override
Compute the hash value of an object and if it makes sense to store it in the objects status_flags...
int canonicalize(exvector::iterator v, const symmetry &symm)
Canonicalize the order of elements of an expression vector, according to the symmetry properties defi...
This class describes the symmetry of a group of indices.
symmetry & add(const symmetry &c)
Add child node, check index sets for consistency.
unsigned hashvalue
hash value
ex op(size_t i) const override
Return operand/member at position i.
const_iterator end() const noexcept
Interface to GiNaC's symmetry definitions.
ex subs(const exmap &m, unsigned options=0) const
container & remove_first()
Remove first element.
const symmetry & symmetric4()
const basic & setflag(unsigned f) const
Set some status_flags.
int permutation_sign(It first, It last)
ex symmetrize_cyclic(const ex &thisex)
ex antisymmetrize(const ex &thisex)
static const symmetry & index2()
void do_print_tree(const print_tree &c, unsigned level) const
symmetry_type type
Type of symmetry described by this node.
Archiving of GiNaC expressions.
Interface to GiNaC's sums of expressions.
void operator()(const ex &lh, const ex &rh)
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
const symmetry & antisymmetric2()
static const symmetry & index3()
bool has_nonsymmetric() const
Check whether this node involves anything non symmetric.
ex symmetrize_cyclic() const
Symmetrize expression by cyclic permutation over its free indices.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...
symmetry_type
Type of symmetry.
const_iterator begin() const noexcept
bool has_cyclic() const
Check whether this node involves a cyclic symmetry.
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
const symmetry & antisymmetric3()
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
container & append(const ex &b)
Add element at back.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
static unsigned make_hash_seed(const std::type_info &tinfo)
We need a hash function which gives different values for objects of different types.
symmetry(unsigned i)
Create leaf node that represents one index.
ex antisymmetrize() const
Antisymmetrize expression over its free indices.
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
const_iterator end() const
std::vector< ex > exvector
bool operator()(const ex &lh, const ex &rh) const
Interface to GiNaC's overloaded operators.
void shaker_sort(It first, It last, Cmp comp, Swap swapit)
exvector children
Vector of child nodes.
Base class for print_contexts.
Definition of GiNaC's lst.
static ex symm(const ex &e, exvector::const_iterator first, exvector::const_iterator last, bool asymmetric)
void archive(archive_node &n) const override
Save (a.k.a.
void do_print(const print_context &c, unsigned level) const
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
const_iterator begin() const
const symmetry & symmetric3()
Lightweight wrapper for GiNaC's symbolic objects.
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
ex symmetrize() const
Symmetrize expression over its free indices.
void read_archive(const archive_node &n, lst &syms) override
Read (a.k.a.
ex symmetrize(const ex &thisex)
void validate(unsigned n)
Verify that all indices of this node are in the range [0..n-1].
const symmetry & symmetric2()
.calchash() has already done its job
std::set< unsigned > indices
Sorted union set of all indices handled by this node.
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
const symmetry & antisymmetric4()
void cyclic_permutation(It first, It last, It new_first, Swap swapit)
Wrapper template for making GiNaC classes out of STL containers.
.expand(0) has already done its job (other expand() options ignore this flag)
Makes the interface to the underlying bignum package available.
sy_is_less(exvector::iterator v_)
const numeric factorial(const numeric &n)
Factorial combinatorial function.
static const symmetry & index1()
sy_swap(exvector::iterator v_, bool &s)
static const symmetry & index0()
const symmetry & not_symmetric()
.eval() has already done its job
Context for tree-like output for debugging.
unsigned flags
of type status_flags
GINAC_BIND_UNARCHIVER(add)