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
245{
247 return lh.return_type_tinfo();
248}
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
@ relation_not_equal
Definition: flags.h:239
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.
Definition: relational.cpp:59
void archive(archive_node &n) const override
Save (a.k.a.
Definition: relational.cpp:71
void(safe_bool_helper::* safe_bool)()
Definition: relational.h:94
safe_bool make_safe_bool(bool) const
Definition: relational.cpp:299
relational(const ex &lhs, const ex &rhs, operators oper=equal)
Definition: relational.cpp:52
ex op(size_t i) const override
Return operand/member at position i.
Definition: relational.cpp:160
ex canonical() const
Returns an equivalent relational with zero right-hand side.
Definition: relational.cpp:353
void do_print(const print_context &c, unsigned level) const
Definition: relational.cpp:112
unsigned precedence() const override
Return relative operator precedence (for parenthezing output).
Definition: relational.h:55
return_type_t return_type_tinfo() const override
Definition: relational.cpp:244
bool match_same_type(const basic &other) const override
Returns true if the attributes of two objects are similar enough for a match.
Definition: relational.cpp:230
unsigned calchash() const override
Compute the hash value of an object and if it makes sense to store it in the objects status_flags,...
Definition: relational.cpp:250
unsigned return_type() const override
Definition: relational.cpp:238
ex eval_ncmul(const exvector &v) const override
Definition: relational.cpp:190
ex map(map_function &f) const override
Construct new expression by applying the specified function to all sub-expressions (one level only,...
Definition: relational.cpp:167
void do_print_python_repr(const print_python_repr &c, unsigned level) const
Definition: relational.cpp:123
bool info(unsigned inf) const override
Information about the object.
Definition: relational.cpp:134
size_t nops() const override
Number of operands/members.
Definition: relational.cpp:155
ex subs(const exmap &m, unsigned options=0) const override
Substitute a set of objects by arbitrary expressions.
Definition: relational.cpp:179
@ 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
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
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(add, expairseq, print_func< print_context >(&add::do_print). print_func< print_latex >(&add::do_print_latex). print_func< print_csrc >(&add::do_print_csrc). print_func< print_tree >(&add::do_print_tree). print_func< print_python_repr >(&add::do_print_python_repr)) add
Definition: add.cpp:40
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)
Definition: relational.cpp:85
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 lst GINAC_BIND_UNARCHIVER(lst)
Specialization of container::info() for lst.
Definition: lst.cpp:42
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.
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.