]> www.ginac.de Git - ginac.git/blob - ginac/relational.cpp
skeleton implementation of new color class
[ginac.git] / ginac / relational.cpp
1 /** @file relational.cpp
2  *
3  *  Implementation of relations between expressions */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2001 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 <stdexcept>
24
25 #include "relational.h"
26 #include "numeric.h"
27 #include "archive.h"
28 #include "utils.h"
29 #include "debugmsg.h"
30
31 namespace GiNaC {
32
33 GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic)
34
35 //////////
36 // default ctor, dtor, copy ctor assignment operator and helpers
37 //////////
38
39 relational::relational() : basic(TINFO_relational)
40 {
41         debugmsg("relational default ctor",LOGLEVEL_CONSTRUCT);
42 }
43
44 void relational::copy(const relational & other)
45 {
46         basic::copy(other);
47         lh=other.lh;
48         rh=other.rh;
49         o=other.o;
50 }
51
52 DEFAULT_DESTROY(relational)
53
54 //////////
55 // other ctors
56 //////////
57
58 // public
59
60 relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(TINFO_relational)
61 {
62         debugmsg("relational ctor ex,ex,operator",LOGLEVEL_CONSTRUCT);
63         lh=lhs;
64         rh=rhs;
65         o=oper;
66 }
67
68 //////////
69 // archiving
70 //////////
71
72 relational::relational(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
73 {
74         debugmsg("relational ctor from archive_node", LOGLEVEL_CONSTRUCT);
75         unsigned int opi;
76         if (!(n.find_unsigned("op", opi)))
77                 throw (std::runtime_error("unknown relational operator in archive"));
78         o = (operators)opi;
79         n.find_ex("lh", lh, sym_lst);
80         n.find_ex("rh", rh, sym_lst);
81 }
82
83 void relational::archive(archive_node &n) const
84 {
85         inherited::archive(n);
86         n.add_ex("lh", lh);
87         n.add_ex("rh", rh);
88         n.add_unsigned("op", o);
89 }
90
91 DEFAULT_UNARCHIVE(relational)
92
93 //////////
94 // functions overriding virtual functions from bases classes
95 //////////
96
97 // public
98
99 void relational::print(std::ostream & os, unsigned upper_precedence) const
100 {
101         debugmsg("relational print",LOGLEVEL_PRINT);
102         if (precedence<=upper_precedence) os << "(";
103         lh.print(os,precedence);
104         switch (o) {
105         case equal:
106                 os << "==";
107                 break;
108         case not_equal:
109                 os << "!=";
110                 break;
111         case less:
112                 os << "<";
113                 break;
114         case less_or_equal:
115                 os << "<=";
116                 break;
117         case greater:
118                 os << ">";
119                 break;
120         case greater_or_equal:
121                 os << ">=";
122                 break;
123         default:
124                 os << "(INVALID RELATIONAL OPERATOR)";
125         }
126         rh.print(os,precedence);
127         if (precedence<=upper_precedence) os << ")";
128 }
129
130 void relational::printraw(std::ostream & os) const
131 {
132         debugmsg("relational printraw",LOGLEVEL_PRINT);
133         os << class_name() << "(";
134         lh.printraw(os);
135         os << ",";
136         rh.printraw(os);
137         os << ",";
138         switch (o) {
139         case equal:
140                 os << "==";
141                 break;
142         case not_equal:
143                 os << "!=";
144                 break;
145         case less:
146                 os << "<";
147                 break;
148         case less_or_equal:
149                 os << "<=";
150                 break;
151         case greater:
152                 os << ">";
153                 break;
154         case greater_or_equal:
155                 os << ">=";
156                 break;
157         default:
158                 os << "(INVALID RELATIONAL OPERATOR)";
159         }
160         os << ")";
161 }
162
163 void relational::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const
164 {
165         debugmsg("relational print csrc", LOGLEVEL_PRINT);
166         if (precedence<=upper_precedence)
167                 os << "(";
168
169         // Print left-hand expression
170         lh.bp->printcsrc(os, type, precedence);
171
172         // Print relational operator
173         switch (o) {
174                 case equal:
175                         os << "==";
176                         break;
177                 case not_equal:
178                         os << "!=";
179                         break;
180                 case less:
181                         os << "<";
182                         break;
183                 case less_or_equal:
184                         os << "<=";
185                         break;
186                 case greater:
187                         os << ">";
188                         break;
189                 case greater_or_equal:
190                         os << ">=";
191                         break;
192                 default:
193                         os << "(INVALID RELATIONAL OPERATOR)";
194                         break;
195         }
196
197         // Print right-hand operator
198         rh.bp->printcsrc(os, type, precedence);
199
200         if (precedence <= upper_precedence)
201                 os << ")";
202 }
203
204 bool relational::info(unsigned inf) const
205 {
206         switch (inf) {
207         case info_flags::relation:
208                 return 1;
209         case info_flags::relation_equal:
210                 return o==equal;
211         case info_flags::relation_not_equal:
212                 return o==not_equal;
213         case info_flags::relation_less:
214                 return o==less;
215         case info_flags::relation_less_or_equal:
216                 return o==less_or_equal;
217         case info_flags::relation_greater:
218                 return o==greater;
219         case info_flags::relation_greater_or_equal:
220                 return o==greater_or_equal;
221         }
222         return 0;
223 }
224
225 unsigned relational::nops() const
226 {
227         return 2;
228 }
229
230 ex & relational::let_op(int i)
231 {
232         GINAC_ASSERT(i>=0);
233         GINAC_ASSERT(i<2);
234
235         return i==0 ? lh : rh;
236 }
237         
238 ex relational::eval(int level) const
239 {
240         if (level==1)
241                 return this->hold();
242         
243         if (level == -max_recursion_level)
244                 throw(std::runtime_error("max recursion level reached"));
245         
246         return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated | status_flags::evaluated);
247 }
248
249 ex relational::evalf(int level) const
250 {
251         if (level==1)
252                 return *this;
253         
254         if (level==-max_recursion_level)
255                 throw(std::runtime_error("max recursion level reached"));
256         
257         return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated);
258 }
259
260 ex relational::simplify_ncmul(const exvector & v) const
261 {
262         return lh.simplify_ncmul(v);
263 }
264
265 // protected
266
267 int relational::compare_same_type(const basic & other) const
268 {
269         GINAC_ASSERT(is_exactly_of_type(other, relational));
270         const relational & oth=static_cast<const relational &>(const_cast<basic &>(other));
271         
272         int cmpval;
273         
274         if (o == oth.o) {
275                 cmpval = lh.compare(oth.lh);
276                 if (cmpval==0)
277                         return rh.compare(oth.rh);
278                 else
279                         return cmpval;
280         }
281         if (o<oth.o)
282                 return -1;
283         else
284                 return 1;
285 }
286
287 unsigned relational::return_type(void) const
288 {
289         GINAC_ASSERT(lh.return_type()==rh.return_type());
290         return lh.return_type();
291 }
292    
293 unsigned relational::return_type_tinfo(void) const
294 {
295         GINAC_ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo());
296         return lh.return_type_tinfo();
297 }
298
299 //////////
300 // new virtual functions which can be overridden by derived classes
301 //////////
302
303 /** Left hand side of relational. */
304 ex relational::lhs(void) const
305 {
306         return lh;
307 }
308
309 /** Right hand side of relational. */
310 ex relational::rhs(void) const
311 {
312         return rh;    
313 }
314
315 //////////
316 // non-virtual functions in this class
317 //////////
318
319 relational::operator bool() const
320 {
321         // please note that (a<b) == false does not imply (a>=b) == true
322         // a false result means the comparison is either false or undecidable
323         // (except for !=, where true means unequal or undecidable)
324         ex df = lh-rh;
325         if (!is_ex_exactly_of_type(df,numeric))
326                 // cannot decide on non-numerical results
327                 return o==not_equal ? true : false;
328         
329         int cmpval = ex_to_numeric(df).compare(_num0());
330         switch (o) {
331         case equal:
332                 return cmpval==0;
333         case not_equal:
334                 return cmpval!=0;
335         case less:
336                 return cmpval<0;
337         case less_or_equal:
338                 return cmpval<=0;
339         case greater:
340                 return cmpval>0;
341         case greater_or_equal:
342                 return cmpval>=0;
343         default:
344                 throw(std::logic_error("invalid relational operator"));
345         }
346 }
347
348 //////////
349 // static member variables
350 //////////
351
352 // protected
353
354 unsigned relational::precedence = 20;
355
356 } // namespace GiNaC