GiNaC 1.8.8
relational.cpp
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2025 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 <stdexcept>
31
32namespace GiNaC {
33
36 print_func<print_tree>(&relational::do_print_tree).
37 print_func<print_python_repr>(&relational::do_print_python_repr))
38
39
40// default constructor
42
44
46// other constructors
48
49// public
50
51relational::relational(const ex & lhs, const ex & rhs, operators oper) :
52 lh(lhs), rh(rhs), o(oper) { }
53
55// archiving
57
59{
60 inherited::read_archive(n, sym_lst);
61 unsigned int opi;
62 if (!(n.find_unsigned("op", opi)))
63 throw (std::runtime_error("unknown relational operator in archive"));
64 o = (operators)opi;
65 n.find_ex("lh", lh, sym_lst);
66 n.find_ex("rh", rh, sym_lst);
67}
69
71{
72 inherited::archive(n);
73 n.add_ex("lh", lh);
74 n.add_ex("rh", rh);
75 n.add_unsigned("op", o);
76}
77
79// functions overriding virtual functions from base classes
81
82// public
83
85{
86 switch (o) {
88 c.s << "==";
89 break;
91 c.s << "!=";
92 break;
94 c.s << "<";
95 break;
97 c.s << "<=";
98 break;
100 c.s << ">";
101 break;
103 c.s << ">=";
104 break;
105 default:
106 c.s << "(INVALID RELATIONAL OPERATOR)";
107 break;
108 }
109}
110
111void relational::do_print(const print_context & c, unsigned level) const
112{
113 if (precedence() <= level)
114 c.s << "(";
115 lh.print(c, precedence());
117 rh.print(c, precedence());
118 if (precedence() <= level)
119 c.s << ")";
120}
121
122void relational::do_print_python_repr(const print_python_repr & c, unsigned level) const
123{
124 c.s << class_name() << '(';
125 lh.print(c);
126 c.s << ',';
127 rh.print(c);
128 c.s << ",'";
130 c.s << "')";
131}
132
133bool relational::info(unsigned inf) const
134{
135 switch (inf) {
137 return 1;
139 return o==equal;
141 return o==not_equal;
143 return o==less;
145 return o==less_or_equal;
147 return o==greater;
149 return o==greater_or_equal;
150 }
151 return 0;
152}
153
154size_t relational::nops() const
155{
156 return 2;
157}
158
159ex relational::op(size_t i) const
160{
161 GINAC_ASSERT(i<2);
162
163 return i==0 ? lh : rh;
164}
165
167{
168 const ex &mapped_lh = f(lh);
169 const ex &mapped_rh = f(rh);
170
171 if (!are_ex_trivially_equal(lh, mapped_lh)
172 || !are_ex_trivially_equal(rh, mapped_rh))
173 return dynallocate<relational>(mapped_lh, mapped_rh, o);
174 else
175 return *this;
176}
177
178ex relational::subs(const exmap & m, unsigned options) const
179{
180 const ex & subsed_lh = lh.subs(m, options);
181 const ex & subsed_rh = rh.subs(m, options);
182
183 if (!are_ex_trivially_equal(lh, subsed_lh) || !are_ex_trivially_equal(rh, subsed_rh))
184 return relational(subsed_lh, subsed_rh, o).subs_one_level(m, options);
185 else
186 return subs_one_level(m, options);
187}
188
190{
191 return lh.eval_ncmul(v);
192}
193
194// protected
195
196int relational::compare_same_type(const basic & other) const
197{
198 GINAC_ASSERT(is_exactly_a<relational>(other));
199 const relational &oth = static_cast<const relational &>(other);
200 if (o==oth.o && lh.is_equal(oth.lh) && rh.is_equal(oth.rh))
201 return 0;
202 switch (o) {
203 case equal:
204 case not_equal:
205 if (oth.o!=o)
206 return (o < oth.o) ? -1 : 1;
207 break;
208 case less:
209 if (oth.o!=greater)
210 return (o < oth.o) ? -1 : 1;
211 break;
212 case less_or_equal:
213 if (oth.o!=greater_or_equal)
214 return (o < oth.o) ? -1 : 1;
215 break;
216 case greater:
217 if (oth.o!=less)
218 return (o < oth.o) ? -1 : 1;
219 break;
220 case greater_or_equal:
221 if (oth.o!=less_or_equal)
222 return (o < oth.o) ? -1 : 1;
223 break;
224 }
225 const int lcmpval = lh.compare(oth.lh);
226 return (lcmpval!=0) ? lcmpval : rh.compare(oth.rh);
227}
228
229bool relational::match_same_type(const basic & other) const
230{
231 GINAC_ASSERT(is_exactly_a<relational>(other));
232 const relational &oth = static_cast<const relational &>(other);
233
234 return o == oth.o;
235}
236
238{
240 return lh.return_type();
241}
242
248
249unsigned relational::calchash() const
250{
251 unsigned v = make_hash_seed(typeid(*this));
252 unsigned lhash = lh.gethash();
253 unsigned rhash = rh.gethash();
254
255 v = rotate_left(v);
256 switch(o) {
257 case equal:
258 case not_equal:
259 if (lhash>rhash) {
260 v ^= lhash;
261 lhash = rhash;
262 } else {
263 v ^= rhash;
264 }
265 break;
266 case less:
267 case less_or_equal:
268 v ^= rhash;
269 break;
270 case greater:
271 case greater_or_equal:
272 v ^= lhash;
273 lhash = rhash;
274 break;
275 }
276 v = rotate_left(v);
277 v ^= lhash;
278
279 // store calculated hash value only if object is already evaluated
282 hashvalue = v;
283 }
284
285 return v;
286}
287
289// new virtual functions which can be overridden by derived classes
291
292// none
293
295// non-virtual functions in this class
297
299{
300 return cond? &safe_bool_helper::nonnull : nullptr;
301}
302
308relational::operator relational::safe_bool() const
309{
310 const ex df = lh-rh; // like ::canonical() method
311 // We treat numeric and symbolic expression differently
312 if (is_exactly_a<numeric>(df)) {
313 switch (o) {
314 case equal:
315 return make_safe_bool(ex_to<numeric>(df).is_zero());
316 case not_equal:
317 return make_safe_bool(!ex_to<numeric>(df).is_zero());
318 case less:
319 return make_safe_bool(ex_to<numeric>(df)<(*_num0_p));
320 case less_or_equal:
321 return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
322 case greater:
323 return make_safe_bool(ex_to<numeric>(df)>(*_num0_p));
324 case greater_or_equal:
325 return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p));
326 default:
327 throw(std::logic_error("invalid relational operator"));
328 }
329 } else {
330 // The conversion for symbolic expressions is based on the info flags
331 switch (o) {
332 case equal:
333 return make_safe_bool(df.is_zero());
334 case not_equal:
335 return make_safe_bool(! df.is_zero());
336 case less:
338 case less_or_equal:
340 case greater:
342 case greater_or_equal:
344 default:
345 throw(std::logic_error("invalid relational operator"));
346 }
347 }
348}
349
353{
354 return relational(lh-rh, _ex0, o);
355}
356
357} // 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:73
unsigned gethash() const
Definition ex.h:234
bool is_equal(const ex &other) const
Definition ex.h:346
ex eval_ncmul(const exvector &v) const
Definition ex.h:124
unsigned return_type() const
Definition ex.h:231
return_type_t return_type_tinfo() const
Definition ex.h:232
ex subs(const exmap &m, unsigned options=0) const
Definition ex.h:842
bool info(unsigned inf) const
Definition ex.h:133
int compare(const ex &other) const
Definition ex.h:323
bool is_zero() const
Definition ex.h:214
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Definition ex.cpp:55
@ relation_greater_or_equal
Definition flags.h:243
@ relation_less_or_equal
Definition flags.h:241
Base class for print_contexts.
Definition print.h:102
Context for python-parsable output.
Definition print.h:138
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:2474
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:36
bool is_zero(const ex &thisex)
Definition ex.h:836
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:700
ex rhs(const ex &thisex)
Definition ex.h:833
ex lhs(const ex &thisex)
Definition ex.h:830
print_func< print_context >(&varidx::do_print). print_func< print_latex >(&varidx
Definition idx.cpp:44
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)
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.
#define GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(classname, supername, options)
Macro for inclusion in the implementation of each registered class.
Definition registrar.h:184
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:43
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.