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