- made nops() return unsigned instead of int
[ginac.git] / ginac / symbol.cpp
1 /** @file symbol.cpp
2  *
3  *  Implementation of GiNaC's symbolic objects. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2000 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 #include <string>
24 #include <stdexcept>
25
26 #include "symbol.h"
27 #include "lst.h"
28 #include "utils.h"
29 #include "idx.h"
30 #include "debugmsg.h"
31
32 #ifndef NO_GINAC_NAMESPACE
33 namespace GiNaC {
34 #endif // ndef NO_GINAC_NAMESPACE
35
36 //////////
37 // default constructor, destructor, copy constructor assignment operator and helpers
38 //////////
39
40 symbol::symbol() : basic(TINFO_symbol)
41 {
42     debugmsg("symbol default constructor",LOGLEVEL_CONSTRUCT);
43     serial=next_serial++;
44     name=autoname_prefix()+ToString(serial);
45     asexinfop=new assigned_ex_info;
46     setflag(status_flags::evaluated);
47 }
48
49 symbol::~symbol()
50 {
51     debugmsg("symbol destructor",LOGLEVEL_DESTRUCT);
52     destroy(0);
53 }
54
55 symbol::symbol(symbol const & other)
56 {
57     debugmsg("symbol copy constructor",LOGLEVEL_CONSTRUCT);
58     copy(other);
59 }
60
61 void symbol::copy(symbol const & other)
62 {
63     basic::copy(other);
64     name=other.name;
65     serial=other.serial;
66     asexinfop=other.asexinfop;
67     ++asexinfop->refcount;
68 }
69
70 void symbol::destroy(bool call_parent)
71 {
72     if (--asexinfop->refcount == 0) {
73         delete asexinfop;
74     }
75     if (call_parent) {
76         basic::destroy(call_parent);
77     }
78 }
79
80 // how should the following be interpreted?
81 // symbol x;
82 // symbol y;
83 // x=y;
84 // probably as: x=ex(y);
85
86 //////////
87 // other constructors
88 //////////
89
90 // public
91
92 symbol::symbol(string const & initname) : basic(TINFO_symbol)
93 {
94     debugmsg("symbol constructor from string",LOGLEVEL_CONSTRUCT);
95     name=initname;
96     serial=next_serial++;
97     asexinfop=new assigned_ex_info;
98     setflag(status_flags::evaluated);
99 }
100
101 //////////
102 // functions overriding virtual functions from bases classes
103 //////////
104
105 // public
106
107 basic * symbol::duplicate() const
108 {
109     debugmsg("symbol duplicate",LOGLEVEL_DUPLICATE);
110     return new symbol(*this);
111 }
112
113 void symbol::print(ostream & os, unsigned upper_precedence) const
114 {
115     debugmsg("symbol print",LOGLEVEL_PRINT);
116     os << name;
117 }
118
119 void symbol::printraw(ostream & os) const
120 {
121     debugmsg("symbol printraw",LOGLEVEL_PRINT);
122     os << "symbol(" << "name=" << name << ",serial=" << serial
123        << ",hash=" << hashvalue << ",flags=" << flags << ")";
124 }
125
126 void symbol::printtree(ostream & os, unsigned indent) const
127 {
128     debugmsg("symbol printtree",LOGLEVEL_PRINT);
129     os << string(indent,' ') << name << " (symbol): "
130        << "serial=" << serial
131        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
132        << ", flags=" << flags << endl;
133 }
134
135 void symbol::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
136 {
137     debugmsg("symbol print csrc", LOGLEVEL_PRINT);
138     os << name;
139 }
140
141 bool symbol::info(unsigned inf) const
142 {
143     if (inf==info_flags::symbol) return true;
144     if (inf==info_flags::polynomial ||
145         inf==info_flags::integer_polynomial ||
146         inf==info_flags::cinteger_polynomial ||
147         inf==info_flags::rational_polynomial ||
148         inf==info_flags::crational_polynomial ||
149         inf==info_flags::rational_function) {
150         return true;
151     } else {
152         return basic::info(inf);
153     }
154 }
155
156 ex symbol::expand(unsigned options) const
157 {
158     return this->hold();
159 }
160
161 bool symbol::has(ex const & other) const
162 {
163     if (is_equal(*other.bp)) return true;
164     return false;
165 }
166
167 int symbol::degree(symbol const & s) const
168 {
169     return compare_same_type(s)==0 ? 1 : 0;
170 }
171
172 int symbol::ldegree(symbol const & s) const
173 {
174     return compare_same_type(s)==0 ? 1 : 0;
175 }
176
177 ex symbol::coeff(symbol const & s, int const n) const
178 {
179     if (compare_same_type(s)==0) {
180         return n==1 ? _ex1() : _ex0();
181     } else {
182         return n==0 ? *this : _ex0();
183     }
184 }
185
186 ex symbol::eval(int level) const
187 {
188     if (level == -max_recursion_level) {
189         throw(std::runtime_error("max recursion level reached"));
190     }
191     
192     if (asexinfop->is_assigned) {
193         setflag(status_flags::evaluated);
194         if (level==1) {
195             return (asexinfop->assigned_expression);
196         } else {
197             return (asexinfop->assigned_expression).eval(level);
198         }
199     } else {
200         return this->hold();
201     }
202 }
203
204 ex symbol::subs(lst const & ls, lst const & lr) const
205 {
206     GINAC_ASSERT(ls.nops()==lr.nops());
207 #ifdef DO_GINAC_ASSERT
208     for (unsigned i=0; i<ls.nops(); i++) {
209         GINAC_ASSERT(is_ex_exactly_of_type(ls.op(i),symbol)||
210                is_ex_of_type(ls.op(i),idx));
211     }
212 #endif // def DO_GINAC_ASSERT
213
214     for (unsigned i=0; i<ls.nops(); i++) {
215         if (is_ex_exactly_of_type(ls.op(i),symbol)) {
216             if (compare_same_type(ex_to_symbol(ls.op(i)))==0) return lr.op(i);
217         }
218     }
219     return *this;
220 }
221
222 // protected
223
224 int symbol::compare_same_type(basic const & other) const
225 {
226     GINAC_ASSERT(is_of_type(other,symbol));
227     const symbol *o = static_cast<const symbol *>(&other);
228     if (serial==o->serial) return 0;
229     return serial < o->serial ? -1 : 1;
230 }
231
232 bool symbol::is_equal_same_type(basic const & other) const
233 {
234     GINAC_ASSERT(is_of_type(other,symbol));
235     const symbol *o = static_cast<const symbol *>(&other);
236     return serial==o->serial;
237 }
238
239 unsigned symbol::return_type(void) const
240 {
241     return return_types::commutative;
242 }
243    
244 unsigned symbol::return_type_tinfo(void) const
245 {
246     return tinfo_key;
247 }
248
249 unsigned symbol::calchash(void) const
250 {
251     // return golden_ratio_hash(tinfo()) ^ serial;
252     hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555555U ^ serial));
253     setflag(status_flags::hash_calculated);
254     return hashvalue;
255 }
256
257 //////////
258 // virtual functions which can be overridden by derived classes
259 //////////
260
261 // none
262
263 //////////
264 // non-virtual functions in this class
265 //////////
266
267 // public
268
269 void symbol::assign(ex const & value)
270 {
271     asexinfop->is_assigned=1;
272     asexinfop->assigned_expression=value;
273     clearflag(status_flags::evaluated);
274 }
275
276 void symbol::unassign(void)
277 {
278     if (asexinfop->is_assigned) {
279         asexinfop->is_assigned=0;
280         asexinfop->assigned_expression=_ex0();
281     }
282     setflag(status_flags::evaluated);
283 }
284
285 // private
286
287 string & symbol::autoname_prefix(void)
288 {
289     static string * s=new string("symbol");
290     return *s;
291 }
292
293 //////////
294 // static member variables
295 //////////
296
297 // private
298
299 unsigned symbol::next_serial=0;
300
301 // string const symbol::autoname_prefix="symbol";
302
303 //////////
304 // global constants
305 //////////
306
307 const symbol some_symbol;
308 type_info const & typeid_symbol=typeid(some_symbol);
309
310 //////////
311 // subclass assigned_ex_info
312 //////////
313
314 /** Default ctor.  Defaults to unassigned. */
315 symbol::assigned_ex_info::assigned_ex_info(void) : is_assigned(0), refcount(1)
316 {
317 }
318
319 #ifndef NO_GINAC_NAMESPACE
320 } // namespace GiNaC
321 #endif // ndef NO_GINAC_NAMESPACE