GiNaC 1.8.7
relational.cpp
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "relational.h"
24#include "operators.h"
25#include "numeric.h"
26#include "archive.h"
27#include "utils.h"
28#include "hash_seed.h"
29
30#include <iostream>
31#include <stdexcept>
32
33namespace GiNaC {
34
37 print_func<print_tree>(&relational::do_print_tree).
38 print_func<print_python_repr>(&relational::do_print_python_repr))
39
40
41// default constructor
43
45
47// other constructors
49
50// public
51
52relational::relational(const ex & lhs, const ex & rhs, operators oper) :
53 lh(lhs), rh(rhs), o(oper) { }
54
56// archiving
58
60{
61 inherited::read_archive(n, sym_lst);
62 unsigned int opi;
63 if (!(n.find_unsigned("op", opi)))
64 throw (std::runtime_error("unknown relational operator in archive"));
65 o = (operators)opi;
66 n.find_ex("lh", lh, sym_lst);
67 n.find_ex("rh", rh, sym_lst);
68}
70
72{
73 inherited::archive(n);
74 n.add_ex("lh", lh);
75 n.add_ex("rh", rh);
76 n.add_unsigned("op", o);
77}
78
80// functions overriding virtual functions from base classes
82
83// public
84
86{
87 switch (o) {
89 c.s << "==";
90 break;
92 c.s << "!=";
93 break;
95 c.s << "<";
96 break;
98 c.s << "<=";
99 break;
101 c.s << ">";
102 break;
104 c.s << ">=";
105 break;
106 default:
107 c.s << "(INVALID RELATIONAL OPERATOR)";
108 break;
109 }
110}
111
112void relational::do_print(const print_context & c, unsigned level) const
113{
114 if (precedence() <= level)
115 c.s << "(";
116 lh.print(c, precedence());
118 rh.print(c, precedence());
119 if (precedence() <= level)
120 c.s << ")";
121}
122
123void relational::do_print_python_repr(const print_python_repr & c, unsigned level) const
124{
125 c.s << class_name() << '(';
126 lh.print(c);
127 c.s << ',';
128 rh.print(c);
129 c.s << ",'";
131 c.s << "')";
132}
133
134bool relational::info(unsigned inf) const
135{
136 switch (inf) {
138 return 1;
140 return o==equal;
142 return o==not_equal;
144 return o==less;
146 return o==less_or_equal;
148 return o==greater;
150 return o==greater_or_equal;
151 }
152 return 0;
153}
154
155size_t relational::nops() const
156{
157 return 2;
158}
159
160ex relational::op(size_t i) const
161{
162 GINAC_ASSERT(i<2);
163
164 return i==0 ? lh : rh;
165}
166
168{
169 const ex &mapped_lh = f(lh);
170 const ex &mapped_rh = f(rh);
171
172 if (!are_ex_trivially_equal(lh, mapped_lh)
173 || !are_ex_trivially_equal(rh, mapped_rh))
174 return dynallocate<relational>(mapped_lh, mapped_rh, o);
175 else
176 return *this;
177}
178
179ex relational::subs(const exmap & m, unsigned options) const
180{
181 const ex & subsed_lh = lh.subs(m, options);
182 const ex & subsed_rh = rh.subs(m, options);
183
184 if (!are_ex_trivially_equal(lh, subsed_lh) || !are_ex_trivially_equal(rh, subsed_rh))
185 return relational(subsed_lh, subsed_rh, o).subs_one_level(m, options);
186 else
187 return subs_one_level(m, options);
188}
189
191{
192 return lh.eval_ncmul(v);
193}
194
195// protected
196
197int relational::compare_same_type(const basic & other) const
198{
199 GINAC_ASSERT(is_exactly_a<relational>(other));
200 const relational &oth = static_cast<const relational &>(other);
201 if (o==oth.o && lh.is_equal(oth.lh) && rh.is_equal(oth.rh))
202 return 0;
203 switch (o) {
204 case equal:
205 case not_equal:
206 if (oth.o!=o)
207 return (o < oth.o) ? -1 : 1;
208 break;
209 case less:
210 if (oth.o!=greater)
211 return (o < oth.o) ? -1 : 1;
212 break;
213 case less_or_equal:
214 if (oth.o!=greater_or_equal)
215 return (o < oth.o) ? -1 : 1;
216 break;
217 case greater:
218 if (oth.o!=less)
219 return (o < oth.o) ? -1 : 1;
220 break;
221 case greater_or_equal:
222 if (oth.o!=less_or_equal)
223 return (o < oth.o) ? -1 : 1;
224 break;
225 }
226 const int lcmpval = lh.compare(oth.lh);
227 return (lcmpval!=0) ? lcmpval : rh.compare(oth.rh);
228}
229
230bool relational::match_same_type(const basic & other) const
231{
232 GINAC_ASSERT(is_exactly_a<relational>(other));
233 const relational &oth = static_cast<const relational &>(other);
234
235 return o == oth.o;
236}
237
239{
241 return lh.return_type();
242}
243
249
250unsigned relational::calchash() const
251{
252 unsigned v = make_hash_seed(typeid(*this));
253 unsigned lhash = lh.gethash();
254 unsigned rhash = rh.gethash();
255
256 v = rotate_left(v);
257 switch(o) {
258 case equal:
259 case not_equal:
260 if (lhash>rhash) {
261 v ^= lhash;
262 lhash = rhash;
263 } else {
264 v ^= rhash;
265 }
266 break;
267 case less:
268 case less_or_equal:
269 v ^= rhash;
270 break;
271 case greater:
272 case greater_or_equal:
273 v ^= lhash;
274 lhash = rhash;
275 break;
276 }
277 v = rotate_left(v);
278 v ^= lhash;
279
280 // store calculated hash value only if object is already evaluated
283 hashvalue = v;
284 }
285
286 return v;
287}
288
290// new virtual functions which can be overridden by derived classes
292
293// none
294
296// non-virtual functions in this class
298
300{
301 return cond? &safe_bool_helper::nonnull : nullptr;
302}
303
309relational::operator relational::safe_bool() const
310{
311 const ex df = lh-rh; // like ::canonical() method
312 // We treat numeric and symbolic expression differently
313 if (is_exactly_a<numeric>(df)) {
314 switch (o) {
315 case equal:
316 return make_safe_bool(ex_to<numeric>(df).is_zero());
317 case not_equal:
318 return make_safe_bool(!ex_to<numeric>(df).is_zero());
319 case less:
320 return make_safe_bool(ex_to<numeric>(df)<(*_num0_p));
321 case less_or_equal:
322 return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
323 case greater:
324 return make_safe_bool(ex_to<numeric>(df)>(*_num0_p));
325 case greater_or_equal:
326 return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p));
327 default:
328 throw(std::logic_error("invalid relational operator"));
329 }
330 } else {
331 // The conversion for symbolic expressions is based on the info flags
332 switch (o) {
333 case equal:
334 return make_safe_bool(df.is_zero());
335 case not_equal:
336 return make_safe_bool(! df.is_zero());
337 case less:
339 case less_or_equal:
341 case greater:
343 case greater_or_equal:
345 default:
346 throw(std::logic_error("invalid relational operator"));
347 }
348 }
349}
350
354{
355 return relational(lh-rh, _ex0, o);
356}
357
358} // namespace GiNaC
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition assertion.h:33
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Definition archive.h:49
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition basic.h:105
const basic & setflag(unsigned f) const
Set some status_flags.
Definition basic.h:288
unsigned hashvalue
hash value
Definition basic.h:303
unsigned flags
of type status_flags
Definition basic.h:302
ex subs_one_level(const exmap &m, unsigned options) const
Helper function for subs().
Definition basic.cpp:585
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition basic.cpp:719
void do_print_tree(const print_tree &c, unsigned level) const
Tree output to stream.
Definition basic.cpp:175
Wrapper template for making GiNaC classes out of STL containers.
Definition container.h:73
Lightweight wrapper for GiNaC's symbolic objects.
Definition ex.h:72
unsigned gethash() const
Definition ex.h:233
bool is_equal(const ex &other) const
Definition ex.h:345
ex eval_ncmul(const exvector &v) const
Definition ex.h:123
unsigned return_type() const
Definition ex.h:230
return_type_t return_type_tinfo() const
Definition ex.h:231
ex subs(const exmap &m, unsigned options=0) const
Definition ex.h:841
bool info(unsigned inf) const
Definition ex.h:132
int compare(const ex &other) const
Definition ex.h:322
bool is_zero() const
Definition ex.h:213
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Definition ex.cpp:56
@ relation_greater_or_equal
Definition flags.h:243
@ relation_less_or_equal
Definition flags.h:241
Base class for print_contexts.
Definition print.h:103
Context for python-parsable output.
Definition print.h:139
This class holds a relation consisting of two expressions and a logical relation between them.
Definition relational.h:35
void read_archive(const archive_node &n, lst &syms) override
Read (a.k.a.
void archive(archive_node &n) const override
Save (a.k.a.
void(safe_bool_helper::* safe_bool)()
Definition relational.h:94
safe_bool make_safe_bool(bool) const
relational(const ex &lhs, const ex &rhs, operators oper=equal)
ex op(size_t i) const override
Return operand/member at position i.
ex canonical() const
Returns an equivalent relational with zero right-hand side.
void do_print(const print_context &c, unsigned level) const
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Definition relational.h:55
return_type_t return_type_tinfo() const override
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
unsigned calchash() const override
Compute the hash value of an object and if it makes sense to store it in the objects status_flags,...
unsigned return_type() const override
ex eval_ncmul(const exvector &v) const override
ex map(map_function &f) const override
Construct new expression by applying the specified function to all sub-expressions (one level only,...
void do_print_python_repr(const print_python_repr &c, unsigned level) const
bool info(unsigned inf) const override
Information about the object.
size_t nops() const override
Number of operands/members.
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
@ evaluated
.eval() has already done its job
Definition flags.h:203
@ hash_calculated
.calchash() has already done its job
Definition flags.h:205
unsigned options
Definition factor.cpp:2475
size_t n
Definition factor.cpp:1432
size_t c
Definition factor.cpp:757
mvec m
Definition factor.cpp:758
Type-specific hash seed.
Definition add.cpp:38
bool is_zero(const ex &thisex)
Definition ex.h:835
std::map< ex, ex, ex_is_less > exmap
Definition basic.h:50
bool are_ex_trivially_equal(const ex &e1, const ex &e2)
Compare two objects of class quickly without doing a deep tree traversal.
Definition ex.h:699
ex rhs(const ex &thisex)
Definition ex.h:832
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT_T(lst, basic, print_func< print_context >(&lst::do_print). print_func< print_tree >(&lst::do_print_tree)) template<> bool ls GINAC_BIND_UNARCHIVER)(lst)
Specialization of container::info() for lst.
Definition lst.cpp:42
ex lhs(const ex &thisex)
Definition ex.h:829
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
Definition idx.cpp:45
static unsigned make_hash_seed(const std::type_info &tinfo)
We need a hash function which gives different values for objects of different types.
Definition hash_seed.h:36
unsigned rotate_left(unsigned n)
Rotate bits of unsigned value by one bit to the left.
Definition utils.h:48
static void print_operator(const print_context &c, relational::operators o)
const ex _ex0
Definition utils.cpp:369
std::vector< ex > exvector
Definition basic.h:48
const numeric * _num0_p
Definition utils.cpp:367
Makes the interface to the underlying bignum package available.
Interface to GiNaC's overloaded operators.
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
Definition registrar.h:185
Interface to relations between expressions.
Function object for map().
Definition basic.h:85
To distinguish between different kinds of non-commutative objects.
Definition registrar.h:44
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.