]> www.ginac.de Git - ginac.git/blob - ginac/symmetry.h
should work with readline 4.1 again
[ginac.git] / ginac / symmetry.h
1 /** @file symmetry.h
2  *
3  *  Interface to GiNaC's symmetry definitions. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2001 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #ifndef __GINAC_SYMMETRY_H__
24 #define __GINAC_SYMMETRY_H__
25
26 #include <set>
27
28 #include "ex.h"
29
30 namespace GiNaC {
31
32
33 class sy_is_less;
34 class sy_swap;
35
36 /** This class describes the symmetry of a group of indices. These objects
37  *  can be grouped into a tree to form complex mixed symmetries. */
38 class symmetry : public basic
39 {
40         friend class sy_is_less;
41         friend class sy_swap;
42         friend int canonicalize(exvector::iterator v, const symmetry &symm);
43
44         GINAC_DECLARE_REGISTERED_CLASS(symmetry, basic)
45
46         // types
47 public:
48         /** Type of symmetry */
49         typedef enum {
50                 none,          /**< no symmetry properties */
51                 symmetric,     /**< totally symmetric */
52                 antisymmetric, /**< totally antisymmetric */
53                 cyclic         /**< cyclic symmetry */
54         } symmetry_type;
55
56         // other constructors
57 public:
58         /** Create leaf node that represents one index. */
59         symmetry(unsigned i);
60
61         /** Create node with two children. */
62         symmetry(symmetry_type t, const symmetry &c1, const symmetry &c2);
63
64         // functions overriding virtual functions from base classes
65 public:
66         void print(const print_context & c, unsigned level = 0) const;
67
68         // non-virtual functions in this class
69 public:
70         /** Get symmetry type. */
71         symmetry_type get_type() const {return type;}
72
73         /** Set symmetry type. */
74         void set_type(symmetry_type t) {type = t;}
75
76         /** Add child node, check index sets for consistency. */
77         symmetry &add(const symmetry &c);
78
79         /** Verify that all indices of this node are in the range [0..n-1].
80          *  This function throws an exception if the verification fails.
81          *  If the top node has a type != none and no children, add all indices
82          *  in the range [0..n-1] as children. */
83         void validate(unsigned n);
84
85         /** Check whether this node actually represents any kind of symmetry. */
86         bool has_symmetry(void) const {return type != none || !children.empty(); }
87
88         // member variables
89 private:
90         /** Type of symmetry described by this node. */
91         symmetry_type type;
92
93         /** Sorted union set of all indices handled by this node. */
94         std::set<unsigned> indices;
95
96         /** Vector of child nodes. */
97         exvector children;
98 };
99
100
101 // global functions
102 inline symmetry &ex_to_nonconst_symmetry(const ex &e)
103 {
104         return static_cast<symmetry &>(*e.bp);
105 }
106
107 inline symmetry sy_none(void) { return symmetry(); }
108 inline symmetry sy_none(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::none, c1, c2); }
109 inline symmetry sy_none(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::none, c1, c2).add(c3); }
110 inline symmetry sy_none(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::none, c1, c2).add(c3).add(c4); }
111
112 inline symmetry sy_symm(void) { symmetry s; s.set_type(symmetry::symmetric); return s; }
113 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::symmetric, c1, c2); }
114 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::symmetric, c1, c2).add(c3); }
115 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::symmetric, c1, c2).add(c3).add(c4); }
116
117 inline symmetry sy_anti(void) { symmetry s; s.set_type(symmetry::antisymmetric); return s; }
118 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::antisymmetric, c1, c2); }
119 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::antisymmetric, c1, c2).add(c3); }
120 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::antisymmetric, c1, c2).add(c3).add(c4); }
121
122 inline symmetry sy_cycl(void) { symmetry s; s.set_type(symmetry::cyclic); return s; }
123 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::cyclic, c1, c2); }
124 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::cyclic, c1, c2).add(c3); }
125 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::cyclic, c1, c2).add(c3).add(c4); }
126
127 /** Canonicalize the order of elements of an expression vector, according to
128  *  the symmetry properties defined in a symmetry tree.
129  *
130  *  @param v Start of expression vector
131  *  @param symm Root node of symmetry tree
132  *  @return the overall sign introduced by the reordering (+1, -1 or 0)
133  *          or INT_MAX if nothing changed */
134 extern int canonicalize(exvector::iterator v, const symmetry &symm);
135
136 /** Symmetrize expression over a set of objects (symbols, indices). */
137 ex symmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
138
139 /** Symmetrize expression over a set of objects (symbols, indices). */
140 inline ex symmetrize(const ex & e, const exvector & v)
141 {
142         return symmetrize(e, v.begin(), v.end());
143 }
144
145 /** Antisymmetrize expression over a set of objects (symbols, indices). */
146 ex antisymmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
147
148 /** Antisymmetrize expression over a set of objects (symbols, indices). */
149 inline ex antisymmetrize(const ex & e, const exvector & v)
150 {
151         return antisymmetrize(e, v.begin(), v.end());
152 }
153
154 /** Symmetrize expression by cyclic permuation over a set of objects
155  *  (symbols, indices). */
156 ex symmetrize_cyclic(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
157
158 /** Symmetrize expression by cyclic permutation over a set of objects
159  *  (symbols, indices). */
160 inline ex symmetrize_cyclic(const ex & e, const exvector & v)
161 {
162         return symmetrize(e, v.begin(), v.end());
163 }
164
165 // utility functions
166
167 /** Specialization of is_exactly_a<symmetry>(obj) for symmetry objects. */
168 template<> inline bool is_exactly_a<symmetry>(const basic & obj)
169 {
170         return obj.tinfo()==TINFO_symmetry;
171 }
172
173 } // namespace GiNaC
174
175 #endif // ndef __GINAC_SYMMETRY_H__