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