GiNaC 1.8.9
relational.cpp
Go to the documentation of this file.
1
4
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());
116 print_operator(c, o);
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 << ",'";
129 print_operator(c, o);
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{
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{
232 const relational &oth = static_cast<const relational &>(other);
233
234 return o == oth.o;
235}
236
238{
239 GINAC_ASSERT(lh.return_type()==rh.return_type());
240 return lh.return_type();
241}
242
244{
245 GINAC_ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo());
246 return lh.return_type_tinfo();
247}
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:
316 case not_equal:
318 case less:
320 case less_or_equal:
321 return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
322 case greater:
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
bool find_unsigned(const std::string &name, unsigned &ret, unsigned index=0) const
Retrieve property of type "unsigned" from node.
Definition archive.cpp:435
void add_unsigned(const std::string &name, unsigned value)
Add property of type "unsigned int" to node.
Definition archive.cpp:399
bool find_ex(const std::string &name, ex &ret, lst &sym_lst, unsigned index=0) const
Retrieve property of type "ex" from node.
Definition archive.cpp:476
void add_ex(const std::string &name, const ex &value)
Add property of type "ex" to node.
Definition archive.cpp:409
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
friend class ex
Definition basic.h:108
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
bool is_equal(const ex &other) const
Definition ex.h:346
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
@ 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
std::ostream & s
stream to output to
Definition print.h:108
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
ex rhs() const
Definition relational.h:82
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,...
ex lhs() const
Definition relational.h:81
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
Type-specific hash seed.
Definition add.cpp:36
bool is_zero(const ex &thisex)
Definition ex.h:836
container< std::list > lst
Definition lst.h:32
std::map< ex, ex, ex_is_less > exmap
Definition basic.h:50
B & dynallocate(Args &&... args)
Constructs a new (class basic or derived) B object on the heap.
Definition basic.h:334
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
attribute_pure const T & ex_to(const ex &e)
Return a reference to the basic-derived class T object embedded in an expression.
Definition ex.h:978
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
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)
bool is_exactly_a(const basic &obj)
Check if obj is a T, not including base classes.
Definition basic.h:320
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.