]> www.ginac.de Git - ginac.git/blob - ginac/symbol.cpp
Texinfo interprets @strong{Note...} as a cross reference and gives a
[ginac.git] / ginac / symbol.cpp
1 /** @file symbol.cpp
2  *
3  *  Implementation of GiNaC's symbolic objects. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2010 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 "symbol.h"
24 #include "lst.h"
25 #include "archive.h"
26 #include "tostring.h"
27 #include "utils.h"
28 #include "hash_seed.h"
29 #include "inifcns.h"
30
31 #include <map>
32 #include <stdexcept>
33 #include <string>
34
35 namespace GiNaC {
36
37 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(symbol, basic,
38   print_func<print_context>(&symbol::do_print).
39   print_func<print_latex>(&symbol::do_print_latex).
40   print_func<print_tree>(&symbol::do_print_tree).
41   print_func<print_python_repr>(&symbol::do_print_python_repr))
42
43 //////////
44 // default constructor
45 //////////
46
47 // symbol
48
49 symbol::symbol() : serial(next_serial++), name(""), TeX_name("")
50 {
51         setflag(status_flags::evaluated | status_flags::expanded);
52 }
53
54 // realsymbol
55
56 realsymbol::realsymbol() : symbol() { }
57
58 // possymbol
59
60 possymbol::possymbol() : realsymbol() { }
61
62 //////////
63 // other constructors
64 //////////
65
66 // public
67
68 // symbol
69
70 symbol::symbol(const std::string & initname) : serial(next_serial++),
71         name(initname), TeX_name("")
72 {
73         setflag(status_flags::evaluated | status_flags::expanded);
74 }
75
76 symbol::symbol(const std::string & initname, const std::string & texname) :
77         serial(next_serial++), name(initname), TeX_name(texname)
78 {
79         setflag(status_flags::evaluated | status_flags::expanded);
80 }
81
82 // realsymbol
83         
84 realsymbol::realsymbol(const std::string & initname) : symbol(initname) { }
85
86 realsymbol::realsymbol(const std::string & initname, const std::string & texname)
87         : symbol(initname, texname) { }
88
89 // possymbol
90         
91 possymbol::possymbol(const std::string & initname) : realsymbol(initname) { }
92
93 possymbol::possymbol(const std::string & initname, const std::string & texname) 
94         : realsymbol(initname, texname) { }
95
96 //////////
97 // archiving
98 //////////
99
100 /** Read object from archive_node. */
101 void symbol::read_archive(const archive_node &n, lst &sym_lst)
102 {
103         inherited::read_archive(n, sym_lst);
104         serial = next_serial++;
105         std::string tmp_name;
106         n.find_string("name", tmp_name);
107
108         // If symbol is in sym_lst, return the existing symbol
109         for (lst::const_iterator it = sym_lst.begin(); it != sym_lst.end(); ++it) {
110                 if (is_a<symbol>(*it) && (ex_to<symbol>(*it).name == tmp_name)) {
111                         *this = ex_to<symbol>(*it);
112                         return;
113                 }
114         }
115         name = tmp_name;
116         if (!n.find_string("TeXname", TeX_name))
117                 TeX_name = std::string("");
118         setflag(status_flags::evaluated | status_flags::expanded);
119
120         setflag(status_flags::dynallocated);
121         sym_lst.append(*this);
122 }
123
124 /** Archive the object. */
125 void symbol::archive(archive_node &n) const
126 {
127         inherited::archive(n);
128         // XXX: we should not archive anonymous symbols.
129         if (!name.empty())
130                 n.add_string("name", name);
131         if (!TeX_name.empty())
132                 n.add_string("TeX_name", TeX_name);
133 }
134
135 //////////
136 // functions overriding virtual functions from base classes
137 //////////
138
139 /** Return default TeX name for symbol. This recognizes some greek letters. */
140 static const std::string& get_default_TeX_name(const std::string& name);
141
142 // public
143
144 void symbol::do_print(const print_context & c, unsigned level) const
145 {
146         if (!name.empty())
147                 c.s << name;
148         else
149                 c.s << "symbol" << serial;
150 }
151
152 void symbol::do_print_latex(const print_latex & c, unsigned level) const
153 {
154         if (!TeX_name.empty())
155                 c.s << TeX_name;
156         else if (!name.empty())
157                 c.s << get_default_TeX_name(name);
158         else
159                 c.s << "symbol" << serial;
160 }
161
162 void symbol::do_print_tree(const print_tree & c, unsigned level) const
163 {
164         c.s << std::string(level, ' ') << name << " (" << class_name() << ")" << " @" << this
165             << ", serial=" << serial
166             << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
167             << ", domain=" << get_domain()
168             << std::endl;
169 }
170
171 void symbol::do_print_python_repr(const print_python_repr & c, unsigned level) const
172 {
173         c.s << class_name() << "('";
174         if (!name.empty())
175                 c.s << name;
176         else
177                 c.s << "symbol" << serial;
178         if (!TeX_name.empty())
179                 c.s << "','" << TeX_name;
180         c.s << "')";
181 }
182
183 bool symbol::info(unsigned inf) const
184 {
185         switch (inf) {
186                 case info_flags::symbol:
187                 case info_flags::polynomial:
188                 case info_flags::integer_polynomial: 
189                 case info_flags::cinteger_polynomial: 
190                 case info_flags::rational_polynomial: 
191                 case info_flags::crational_polynomial: 
192                 case info_flags::rational_function: 
193                 case info_flags::expanded:
194                         return true;
195                 case info_flags::real:
196                         return get_domain() == domain::real || get_domain() == domain::positive;
197                 case info_flags::positive:
198                 case info_flags::nonnegative:
199                         return get_domain() == domain::positive;
200                 case info_flags::has_indices:
201                         return false;
202         }
203         return inherited::info(inf);
204 }
205
206 ex symbol::conjugate() const
207 {
208         return conjugate_function(*this).hold();
209 }
210
211 ex symbol::real_part() const
212 {
213         return real_part_function(*this).hold();
214 }
215
216 ex symbol::imag_part() const
217 {
218         return imag_part_function(*this).hold();
219 }
220
221 bool symbol::is_polynomial(const ex & var) const
222 {
223         return true;
224 }
225
226 // protected
227
228 /** Implementation of ex::diff() for single differentiation of a symbol.
229  *  It returns 1 or 0.
230  *
231  *  @see ex::diff */
232 ex symbol::derivative(const symbol & s) const
233 {
234         if (compare_same_type(s))
235                 return _ex0;
236         else
237                 return _ex1;
238 }
239
240 int symbol::compare_same_type(const basic & other) const
241 {
242         GINAC_ASSERT(is_a<symbol>(other));
243         const symbol *o = static_cast<const symbol *>(&other);
244         if (serial==o->serial) return 0;
245         return serial < o->serial ? -1 : 1;
246 }
247
248 bool symbol::is_equal_same_type(const basic & other) const
249 {
250         GINAC_ASSERT(is_a<symbol>(other));
251         const symbol *o = static_cast<const symbol *>(&other);
252         return serial==o->serial;
253 }
254
255 unsigned symbol::calchash() const
256 {
257         unsigned seed = make_hash_seed(typeid(*this));
258         hashvalue = golden_ratio_hash(seed ^ serial);
259         setflag(status_flags::hash_calculated);
260         return hashvalue;
261 }
262
263 //////////
264 // virtual functions which can be overridden by derived classes
265 //////////
266
267 // none
268
269 //////////
270 // non-virtual functions in this class
271 //////////
272
273 /** Return default TeX name for symbol. This recognizes some greek letters. */
274 static const std::string& get_default_TeX_name(const std::string& name)
275 {
276         static std::map<std::string, std::string> standard_names;
277         static bool names_initialized = false;
278         if (!names_initialized) {
279                 standard_names["alpha"] = std::string("\\alpha");
280                 standard_names["beta"] = std::string("\\beta");;
281                 standard_names["gamma"] = std::string("\\gamma");;
282                 standard_names["delta"] = std::string("\\delta");;
283                 standard_names["epsilon"] = std::string("\\epsilon");
284                 standard_names["varepsilon"] = std::string("\\varepsilon");
285                 standard_names["zeta"] = std::string("\\zeta");
286                 standard_names["eta" ] = std::string("\\eta" );
287                 standard_names["theta"] = std::string("\\theta");
288                 standard_names["vartheta"] = std::string("\\vartheta");
289                 standard_names["iota"] = std::string("\\iota");
290                 standard_names["kappa"] = std::string("\\kappa");
291                 standard_names["lambda"] = std::string("\\lambda");
292                 standard_names["mu"] = std::string("\\mu");
293                 standard_names["nu"] = std::string("\\nu");
294                 standard_names["xi"] = std::string("\\xi");
295                 standard_names["omicron"] = std::string("\\omicron");
296                 standard_names["pi"] = std::string("\\pi");
297                 standard_names["varpi"] = std::string("\\varpi");
298                 standard_names["rho"] = std::string("\\rho");
299                 standard_names["varrho"] = std::string("\\varrho");
300                 standard_names["sigma"] = std::string("\\sigma");
301                 standard_names["varsigma"] = std::string("\\varsigma");
302                 standard_names["tau"] = std::string("\\tau");
303                 standard_names["upsilon"] = std::string("\\upsilon");
304                 standard_names["phi"] = std::string("\\phi");
305                 standard_names["varphi"] = std::string("\\varphi");
306                 standard_names["chi"] = std::string("\\chi");
307                 standard_names["psi"] = std::string("\\psi");
308                 standard_names["omega"] = std::string("\\omega");
309                 standard_names["Gamma"] = std::string("\\Gamma");
310                 standard_names["Delta"] = std::string("\\Delta");
311                 standard_names["Theta"] = std::string("\\Theta");
312                 standard_names["Lambda"] = std::string("\\Lambda");
313                 standard_names["Xi"] = std::string("\\Xi");
314                 standard_names["Pi"] = std::string("\\Pi");
315                 standard_names["Sigma"] = std::string("\\Sigma");
316                 standard_names["Upsilon"] = std::string("\\Upsilon");
317                 standard_names["Phi"] = std::string("\\Phi");
318                 standard_names["Psi"] = std::string("\\Psi");
319                 standard_names["Omega"] = std::string("\\Omega");
320                 names_initialized = true;
321         }
322         std::map<std::string, std::string>::const_iterator it = standard_names.find(name);
323         if (it != standard_names.end())
324                 return it->second;
325         else
326                 return name;
327 }
328
329 GINAC_BIND_UNARCHIVER(symbol);
330 GINAC_BIND_UNARCHIVER(realsymbol);
331 GINAC_BIND_UNARCHIVER(possymbol);
332
333 //////////
334 // static member variables
335 //////////
336
337 // private
338
339 unsigned symbol::next_serial = 0;
340
341 } // namespace GiNaC