]> www.ginac.de Git - ginac.git/blob - ginac/relational.cpp
- Removed obsolete (even for Cint!) malloc_alloc template arguments.
[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 "print.h"
28 #include "archive.h"
29 #include "utils.h"
30 #include "debugmsg.h"
31
32 namespace GiNaC {
33
34 GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic)
35
36 //////////
37 // default ctor, dtor, copy ctor assignment operator and helpers
38 //////////
39
40 relational::relational() : basic(TINFO_relational)
41 {
42         debugmsg("relational default ctor",LOGLEVEL_CONSTRUCT);
43 }
44
45 void relational::copy(const relational & other)
46 {
47         basic::copy(other);
48         lh=other.lh;
49         rh=other.rh;
50         o=other.o;
51 }
52
53 DEFAULT_DESTROY(relational)
54
55 //////////
56 // other ctors
57 //////////
58
59 // public
60
61 relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(TINFO_relational)
62 {
63         debugmsg("relational ctor ex,ex,operator",LOGLEVEL_CONSTRUCT);
64         lh=lhs;
65         rh=rhs;
66         o=oper;
67 }
68
69 //////////
70 // archiving
71 //////////
72
73 relational::relational(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
74 {
75         debugmsg("relational ctor from archive_node", LOGLEVEL_CONSTRUCT);
76         unsigned int opi;
77         if (!(n.find_unsigned("op", opi)))
78                 throw (std::runtime_error("unknown relational operator in archive"));
79         o = (operators)opi;
80         n.find_ex("lh", lh, sym_lst);
81         n.find_ex("rh", rh, sym_lst);
82 }
83
84 void relational::archive(archive_node &n) const
85 {
86         inherited::archive(n);
87         n.add_ex("lh", lh);
88         n.add_ex("rh", rh);
89         n.add_unsigned("op", o);
90 }
91
92 DEFAULT_UNARCHIVE(relational)
93
94 //////////
95 // functions overriding virtual functions from bases classes
96 //////////
97
98 // public
99
100 void relational::print(const print_context & c, unsigned level) const
101 {
102         debugmsg("relational print",LOGLEVEL_PRINT);
103
104         if (is_of_type(c, print_tree)) {
105
106                 inherited::print(c, level);
107
108         } else {
109
110                 if (precedence() <= level)
111                         c.s << "(";
112                 lh.print(c, precedence());
113                 switch (o) {
114                 case equal:
115                         c.s << "==";
116                         break;
117                 case not_equal:
118                         c.s << "!=";
119                         break;
120                 case less:
121                         c.s << "<";
122                         break;
123                 case less_or_equal:
124                         c.s << "<=";
125                         break;
126                 case greater:
127                         c.s << ">";
128                         break;
129                 case greater_or_equal:
130                         c.s << ">=";
131                         break;
132                 default:
133                         c.s << "(INVALID RELATIONAL OPERATOR)";
134                 }
135                 rh.print(c, precedence());
136                 if (precedence() <= level)
137                         c.s << ")";
138         }
139 }
140
141 bool relational::info(unsigned inf) const
142 {
143         switch (inf) {
144         case info_flags::relation:
145                 return 1;
146         case info_flags::relation_equal:
147                 return o==equal;
148         case info_flags::relation_not_equal:
149                 return o==not_equal;
150         case info_flags::relation_less:
151                 return o==less;
152         case info_flags::relation_less_or_equal:
153                 return o==less_or_equal;
154         case info_flags::relation_greater:
155                 return o==greater;
156         case info_flags::relation_greater_or_equal:
157                 return o==greater_or_equal;
158         }
159         return 0;
160 }
161
162 unsigned relational::nops() const
163 {
164         return 2;
165 }
166
167 ex & relational::let_op(int i)
168 {
169         GINAC_ASSERT(i>=0);
170         GINAC_ASSERT(i<2);
171
172         return i==0 ? lh : rh;
173 }
174
175 ex relational::map(map_func f) const
176 {
177         return (new relational(f(lh), f(rh), o))->setflag(status_flags::dynallocated);
178 }
179         
180 ex relational::eval(int level) const
181 {
182         if (level==1)
183                 return this->hold();
184         
185         if (level == -max_recursion_level)
186                 throw(std::runtime_error("max recursion level reached"));
187         
188         return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated | status_flags::evaluated);
189 }
190
191 ex relational::evalf(int level) const
192 {
193         if (level==1)
194                 return *this;
195         
196         if (level==-max_recursion_level)
197                 throw(std::runtime_error("max recursion level reached"));
198         
199         return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated);
200 }
201
202 ex relational::simplify_ncmul(const exvector & v) const
203 {
204         return lh.simplify_ncmul(v);
205 }
206
207 // protected
208
209 int relational::compare_same_type(const basic & other) const
210 {
211         GINAC_ASSERT(is_exactly_of_type(other, relational));
212         const relational & oth=static_cast<const relational &>(const_cast<basic &>(other));
213         
214         int cmpval;
215         
216         if (o == oth.o) {
217                 cmpval = lh.compare(oth.lh);
218                 if (cmpval==0)
219                         return rh.compare(oth.rh);
220                 else
221                         return cmpval;
222         }
223         if (o<oth.o)
224                 return -1;
225         else
226                 return 1;
227 }
228
229 unsigned relational::return_type(void) const
230 {
231         GINAC_ASSERT(lh.return_type()==rh.return_type());
232         return lh.return_type();
233 }
234    
235 unsigned relational::return_type_tinfo(void) const
236 {
237         GINAC_ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo());
238         return lh.return_type_tinfo();
239 }
240
241 //////////
242 // new virtual functions which can be overridden by derived classes
243 //////////
244
245 /** Left hand side of relational. */
246 ex relational::lhs(void) const
247 {
248         return lh;
249 }
250
251 /** Right hand side of relational. */
252 ex relational::rhs(void) const
253 {
254         return rh;    
255 }
256
257 //////////
258 // non-virtual functions in this class
259 //////////
260
261 relational::operator bool() const
262 {
263         // please note that (a<b) == false does not imply (a>=b) == true
264         // a false result means the comparison is either false or undecidable
265         // (except for !=, where true means unequal or undecidable)
266         ex df = lh-rh;
267         if (!is_ex_exactly_of_type(df,numeric))
268                 // cannot decide on non-numerical results
269                 return o==not_equal ? true : false;
270         
271         int cmpval = ex_to_numeric(df).compare(_num0());
272         switch (o) {
273         case equal:
274                 return cmpval==0;
275         case not_equal:
276                 return cmpval!=0;
277         case less:
278                 return cmpval<0;
279         case less_or_equal:
280                 return cmpval<=0;
281         case greater:
282                 return cmpval>0;
283         case greater_or_equal:
284                 return cmpval>=0;
285         default:
286                 throw(std::logic_error("invalid relational operator"));
287         }
288 }
289
290 } // namespace GiNaC