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