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