added setname/getname to idx
[ginac.git] / ginac / symbol.cpp
1 /** @file symbol.cpp
2  *
3  *  Implementation of GiNaC's symbolic objects.
4  *
5  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <string>
23 #include <stdexcept>
24
25 #include "symbol.h"
26 #include "lst.h"
27 #include "utils.h"
28 #include "idx.h"
29
30 //////////
31 // default constructor, destructor, copy constructor assignment operator and helpers
32 //////////
33
34 symbol::symbol() : basic(TINFO_symbol)
35 {
36     debugmsg("symbol default constructor",LOGLEVEL_CONSTRUCT);
37     serial=next_serial++;
38     name=autoname_prefix()+ToString(serial);
39     asexinfop=new assigned_ex_info;
40     setflag(status_flags::evaluated);
41 }
42
43 symbol::~symbol()
44 {
45     debugmsg("symbol destructor",LOGLEVEL_DESTRUCT);
46     destroy(0);
47 }
48
49 symbol::symbol(symbol const & other)
50 {
51     debugmsg("symbol copy constructor",LOGLEVEL_CONSTRUCT);
52     copy(other);
53 }
54
55 void symbol::copy(symbol const & other)
56 {
57     basic::copy(other);
58     name=other.name;
59     serial=other.serial;
60     asexinfop=other.asexinfop;
61     ++asexinfop->refcount;
62 }
63
64 void symbol::destroy(bool call_parent)
65 {
66     if (--asexinfop->refcount == 0) {
67         delete asexinfop;
68     }
69     if (call_parent) {
70         basic::destroy(call_parent);
71     }
72 }
73
74 // how should the following be interpreted?
75 // symbol x;
76 // symbol y;
77 // x=y;
78 // probably as: x=ex(y);
79
80 //////////
81 // other constructors
82 //////////
83
84 // public
85
86 symbol::symbol(string const & initname) : basic(TINFO_symbol)
87 {
88     debugmsg("symbol constructor from string",LOGLEVEL_CONSTRUCT);
89     name=initname;
90     serial=next_serial++;
91     asexinfop=new assigned_ex_info;
92     setflag(status_flags::evaluated);
93 }
94
95 //////////
96 // functions overriding virtual functions from bases classes
97 //////////
98
99 // public
100
101 basic * symbol::duplicate() const
102 {
103     debugmsg("symbol duplicate",LOGLEVEL_DUPLICATE);
104     return new symbol(*this);
105 }
106
107 bool symbol::info(unsigned inf) const
108 {
109     if (inf==info_flags::symbol) return true;
110     if (inf==info_flags::polynomial || inf==info_flags::integer_polynomial || inf==info_flags::rational_polynomial || inf==info_flags::rational_function) {
111         return true;
112     } else {
113         return basic::info(inf);
114     }
115 }
116
117 ex symbol::expand(unsigned options) const
118 {
119     return this->hold();
120 }
121
122 bool symbol::has(ex const & other) const
123 {
124     if (is_equal(*other.bp)) return true;
125     return false;
126 }
127
128 int symbol::degree(symbol const & s) const
129 {
130     return compare_same_type(s)==0 ? 1 : 0;
131 }
132
133 int symbol::ldegree(symbol const & s) const
134 {
135     return compare_same_type(s)==0 ? 1 : 0;
136 }
137
138 ex symbol::coeff(symbol const & s, int const n) const
139 {
140     if (compare_same_type(s)==0) {
141         return n==1 ? exONE() : exZERO();
142     } else {
143         return n==0 ? *this : exZERO();
144     }
145 }
146
147 ex symbol::eval(int level) const
148 {
149     if (level == -max_recursion_level) {
150         throw(std::runtime_error("max recursion level reached"));
151     }
152     
153     if (asexinfop->is_assigned) {
154         setflag(status_flags::evaluated);
155         if (level==1) {
156             return (asexinfop->assigned_expression);
157         } else {
158             return (asexinfop->assigned_expression).eval(level);
159         }
160     } else {
161         return this->hold();
162     }
163 }
164
165 ex symbol::subs(lst const & ls, lst const & lr) const
166 {
167     ASSERT(ls.nops()==lr.nops());
168 #ifdef DOASSERT
169     for (int i=0; i<ls.nops(); i++) {
170         ASSERT(is_ex_exactly_of_type(ls.op(i),symbol)||
171                is_ex_of_type(ls.op(i),idx));
172     }
173 #endif // def DOASSERT
174
175     for (int i=0; i<ls.nops(); i++) {
176         if (is_ex_exactly_of_type(ls.op(i),symbol)) {
177             if (compare_same_type(ex_to_symbol(ls.op(i)))==0) return lr.op(i);
178         }
179     }
180     return *this;
181 }
182
183 // protected
184
185 int symbol::compare_same_type(basic const & other) const
186 {
187     ASSERT(is_of_type(other,symbol));
188     const symbol *o = static_cast<const symbol *>(&other);
189     if (serial==o->serial) return 0;
190     return serial < o->serial ? -1 : 1;
191 }
192
193 bool symbol::is_equal_same_type(basic const & other) const
194 {
195     ASSERT(is_of_type(other,symbol));
196     const symbol *o = static_cast<const symbol *>(&other);
197     return serial==o->serial;
198 }
199
200 unsigned symbol::return_type(void) const
201 {
202     return return_types::commutative;
203 }
204    
205 unsigned symbol::return_type_tinfo(void) const
206 {
207     return tinfo_key;
208 }
209
210 unsigned symbol::calchash(void) const
211 {
212     // return golden_ratio_hash(tinfo()) ^ serial;
213     hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555555U ^ serial));
214     setflag(status_flags::hash_calculated);
215     return hashvalue;
216 }
217
218 //////////
219 // virtual functions which can be overridden by derived classes
220 //////////
221
222 // none
223
224 //////////
225 // non-virtual functions in this class
226 //////////
227
228 // public
229
230 void symbol::assign(ex const & value)
231 {
232     asexinfop->is_assigned=1;
233     asexinfop->assigned_expression=value;
234     clearflag(status_flags::evaluated);
235 }
236
237 void symbol::unassign(void)
238 {
239     if (asexinfop->is_assigned) {
240         asexinfop->is_assigned=0;
241         asexinfop->assigned_expression=exZERO();
242     }
243     setflag(status_flags::evaluated);
244 }
245
246 // private
247
248 string & symbol::autoname_prefix(void)
249 {
250     static string * s=new string("symbol");
251     return *s;
252 }
253
254 //////////
255 // static member variables
256 //////////
257
258 // private
259
260 unsigned symbol::next_serial=0;
261
262 // string const symbol::autoname_prefix="symbol";
263
264 //////////
265 // global constants
266 //////////
267
268 const symbol some_symbol;
269 type_info const & typeid_symbol=typeid(some_symbol);
270
271 //////////
272 // subclass assigned_ex_info
273 //////////
274
275 /** Default ctor.  Defaults to unassigned. */
276 symbol::assigned_ex_info::assigned_ex_info(void) : is_assigned(0), refcount(1)
277 {
278 }