9dad5cc70c3178f6b9f3167e1fd3576c8155477a
[ginac.git] / ginac / relational.cpp
1 /** @file relational.cpp
2  *
3  *  Implementation of relations between expressions
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 <stdexcept>
23
24 #include "ginac.h"
25
26 //////////
27 // default constructor, destructor, copy constructor assignment operator and helpers
28 //////////
29
30 // public
31
32 relational::relational() : basic(TINFO_RELATIONAL)
33 {
34     debugmsg("relational default constructor",LOGLEVEL_CONSTRUCT);
35 }
36
37 relational::~relational()
38 {
39     debugmsg("relational destructor",LOGLEVEL_DESTRUCT);
40     destroy(0);
41 }
42
43 relational::relational(relational const & other)
44 {
45     debugmsg("relational copy constructor",LOGLEVEL_CONSTRUCT);
46     copy(other);
47 }
48
49 relational const & relational::operator=(relational const & other)
50 {
51     debugmsg("relational operator=",LOGLEVEL_ASSIGNMENT);
52     if (this != &other) {
53         destroy(1);
54         copy(other);
55     }
56     return *this;
57 }
58
59 // protected
60
61 void relational::copy(relational const & other)
62 {
63     basic::copy(other);
64     lh=other.lh;
65     rh=other.rh;
66     o=other.o;
67 }
68
69 void relational::destroy(bool call_parent)
70 {
71     if (call_parent) basic::destroy(call_parent);
72 }
73
74 //////////
75 // other constructors
76 //////////
77
78 // public
79
80 relational::relational(ex const & lhs, ex const & rhs, operators oper) : basic(TINFO_RELATIONAL)
81 {
82     debugmsg("relational constructor ex,ex,operator",LOGLEVEL_CONSTRUCT);
83     lh=lhs;
84     rh=rhs;
85     o=oper;
86 }
87
88 //////////
89 // functions overriding virtual functions from bases classes
90 //////////
91
92 // public
93
94 basic * relational::duplicate() const
95 {
96     debugmsg("relational duplicate",LOGLEVEL_DUPLICATE);
97     return new relational(*this);
98 }
99
100 bool relational::info(unsigned inf) const
101 {
102     switch (inf) {
103     case info_flags::relation:
104         return 1;
105     case info_flags::relation_equal:
106         return o==equal;
107     case info_flags::relation_not_equal:
108         return o==not_equal;
109     case info_flags::relation_less:
110         return o==less;
111     case info_flags::relation_less_or_equal:
112         return o==less_or_equal;
113     case info_flags::relation_greater:
114         return o==greater;
115     case info_flags::relation_greater_or_equal:
116         return o==greater_or_equal;
117     }
118     return 0;
119 }
120
121 int relational::nops() const
122 {
123     return 2;
124 }
125
126 ex & relational::let_op(int const i)
127 {
128     ASSERT(i>=0);
129     ASSERT(i<2);
130
131     return i==0 ? lh : rh;
132 }
133     
134 ex relational::eval(int level) const
135 {
136     if (level==1) {
137         return this->hold();
138     }
139     if (level == -max_recursion_level) {
140         throw(std::runtime_error("max recursion level reached"));
141     }
142     return (new relational(lh.eval(level-1),rh.eval(level-1),o))->
143             setflag(status_flags::dynallocated  |
144                     status_flags::evaluated );
145 }
146
147 ex relational::evalf(int level) const
148 {
149     if (level==1) {
150         return *this;
151     }
152     if (level == -max_recursion_level) {
153         throw(std::runtime_error("max recursion level reached"));
154     }
155     return (new relational(lh.eval(level-1),rh.eval(level-1),o))->
156             setflag(status_flags::dynallocated);
157 }
158
159 ex relational::simplify_ncmul(exvector const & v) const
160 {
161     return lh.simplify_ncmul(v);
162 }
163
164 // protected
165
166 int relational::compare_same_type(basic const & other) const
167 {
168     ASSERT(is_exactly_of_type(other, relational));
169     relational const & oth=static_cast<relational const &>(const_cast<basic &>(other));
170     
171     int cmpval;
172     
173     if (o == oth.o) {
174         cmpval=lh.compare(oth.lh);
175         if (cmpval==0) {
176             return rh.compare(oth.rh);
177         } else {
178             return cmpval;
179         }
180     }
181     if (o<oth.o) {
182         return -1;
183     } else {
184         return 1;
185     }
186 }
187
188 unsigned relational::return_type(void) const
189 {
190     ASSERT(lh.return_type()==rh.return_type());
191     return lh.return_type();
192 }
193    
194 unsigned relational::return_type_tinfo(void) const
195 {
196     ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo());
197     return lh.return_type_tinfo();
198 }
199
200 //////////
201 // new virtual functions which can be overridden by derived classes
202 //////////
203
204 // none
205
206 //////////
207 // non-virtual functions in this class
208 //////////
209
210 #include <iostream>
211
212 relational::operator bool() const
213 {
214     // please note that (a<b) == false does not imply (a>=b) == true
215     // a false result means the comparison is either false or undecidable
216     // (except for !=, where true means unequal or undecidable)
217     ex df=lh-rh;
218     if (!is_ex_exactly_of_type(df,numeric)) {
219         return o==not_equal ? true : false; // cannot decide on non-numerical results
220     }
221     int cmpval=ex_to_numeric(df).compare(numZERO());
222     switch (o) {
223     case equal:
224         return cmpval==0;
225         break;
226     case not_equal:
227         return cmpval!=0;
228         break;
229     case less:
230         return cmpval<0;
231         break;
232     case less_or_equal:
233         return cmpval<=0;
234         break;
235     case greater:
236         return cmpval>0;
237         break;
238     case greater_or_equal:
239         return cmpval>=0;
240         break;
241     default:
242         throw(std::logic_error("invalid relational operator"));
243     }
244     return 0;
245 }
246
247 //////////
248 // static member variables
249 //////////
250
251 // protected
252
253 unsigned relational::precedence=20;
254
255 //////////
256 // global constants
257 //////////
258
259 const relational some_relational;
260 type_info const & typeid_relational=typeid(some_relational);
261