GiNaC 1.8.10
relational.cpp
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2026 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "relational.h"
23#include "operators.h"
24#include "numeric.h"
25#include "archive.h"
26#include "utils.h"
27#include "hash_seed.h"
28
29#include <stdexcept>
30
31namespace GiNaC {
32
35 print_func<print_tree>(&relational::do_print_tree).
36 print_func<print_python_repr>(&relational::do_print_python_repr))
37
38
39// default constructor
41
43
45// other constructors
47
48// public
49
50relational::relational(const ex & lhs, const ex & rhs, operators oper) :
51 lh(lhs), rh(rhs), o(oper) { }
52
54// archiving
56
58{
59 inherited::read_archive(n, sym_lst);
60 unsigned int opi;
61 if (!(n.find_unsigned("op", opi)))
62 throw (std::runtime_error("unknown relational operator in archive"));
63 o = (operators)opi;
64 n.find_ex("lh", lh, sym_lst);
65 n.find_ex("rh", rh, sym_lst);
66}
68
70{
71 inherited::archive(n);
72 n.add_ex("lh", lh);
73 n.add_ex("rh", rh);
74 n.add_unsigned("op", o);
75}
76
78// functions overriding virtual functions from base classes
80
81// public
82
84{
85 switch (o) {
87 c.s << "==";
88 break;
90 c.s << "!=";
91 break;
93 c.s << "<";
94 break;
96 c.s << "<=";
97 break;
99 c.s << ">";
100 break;
102 c.s << ">=";
103 break;
104 default:
105 c.s << "(INVALID RELATIONAL OPERATOR)";
106 break;
107 }
108}
109
110void relational::do_print(const print_context & c, unsigned level) const
111{
112 if (precedence() <= level)
113 c.s << "(";
114 lh.print(c, precedence());
116 rh.print(c, precedence());
117 if (precedence() <= level)
118 c.s << ")";
119}
120
121void relational::do_print_python_repr(const print_python_repr & c, unsigned level) const
122{
123 c.s << class_name() << '(';
124 lh.print(c);
125 c.s << ',';
126 rh.print(c);
127 c.s << ",'";
129 c.s << "')";
130}
131
132bool relational::info(unsigned inf) const
133{
134 switch (inf) {
136 return 1;
138 return o==equal;
140 return o==not_equal;
142 return o==less;
144 return o==less_or_equal;
146 return o==greater;
148 return o==greater_or_equal;
149 }
150 return 0;
151}
152
153size_t relational::nops() const
154{
155 return 2;
156}
157
158ex relational::op(size_t i) const
159{
160 GINAC_ASSERT(i<2);
161
162 return i==0 ? lh : rh;
163}
164
166{
167 const ex &mapped_lh = f(lh);
168 const ex &mapped_rh = f(rh);
169
170 if (!are_ex_trivially_equal(lh, mapped_lh)
171 || !are_ex_trivially_equal(rh, mapped_rh))
172 return dynallocate<relational>(mapped_lh, mapped_rh, o);
173 else
174 return *this;
175}
176
177ex relational::subs(const exmap & m, unsigned options) const
178{
179 const ex & subsed_lh = lh.subs(m, options);
180 const ex & subsed_rh = rh.subs(m, options);
181
182 if (!are_ex_trivially_equal(lh, subsed_lh) || !are_ex_trivially_equal(rh, subsed_rh))
183 return relational(subsed_lh, subsed_rh, o).subs_one_level(m, options);
184 else
185 return subs_one_level(m, options);
186}
187
189{
190 return lh.eval_ncmul(v);
191}
192
193// protected
194
195int relational::compare_same_type(const basic & other) const
196{
197 GINAC_ASSERT(is_exactly_a<relational>(other));
198 const relational &oth = static_cast<const relational &>(other);
199 if (o==oth.o && lh.is_equal(oth.lh) && rh.is_equal(oth.rh))
200 return 0;
201 switch (o) {
202 case equal:
203 case not_equal:
204 if (oth.o!=o)
205 return (o < oth.o) ? -1 : 1;
206 break;
207 case less:
208 if (oth.o!=greater)
209 return (o < oth.o) ? -1 : 1;
210 break;
211 case less_or_equal:
212 if (oth.o!=greater_or_equal)
213 return (o < oth.o) ? -1 : 1;
214 break;
215 case greater:
216 if (oth.o!=less)
217 return (o < oth.o) ? -1 : 1;
218 break;
219 case greater_or_equal:
220 if (oth.o!=less_or_equal)
221 return (o < oth.o) ? -1 : 1;
222 break;
223 }
224 const int lcmpval = lh.compare(oth.lh);
225 return (lcmpval!=0) ? lcmpval : rh.compare(oth.rh);
226}
227
228bool relational::match_same_type(const basic & other) const
229{
230 GINAC_ASSERT(is_exactly_a<relational>(other));
231 const relational &oth = static_cast<const relational &>(other);
232
233 return o == oth.o;
234}
235
237{
239 return lh.return_type();
240}
241
247
248unsigned relational::calchash() const
249{
250 unsigned v = make_hash_seed(typeid(*this));
251 unsigned lhash = lh.gethash();
252 unsigned rhash = rh.gethash();
253
254 v = rotate_left(v);
255 switch(o) {
256 case equal:
257 case not_equal:
258 if (lhash>rhash) {
259 v ^= lhash;
260 lhash = rhash;
261 } else {
262 v ^= rhash;
263 }
264 break;
265 case less:
266 case less_or_equal:
267 v ^= rhash;
268 break;
269 case greater:
270 case greater_or_equal:
271 v ^= lhash;
272 lhash = rhash;
273 break;
274 }
275 v = rotate_left(v);
276 v ^= lhash;
277
278 // store calculated hash value only if object is already evaluated
281 hashvalue = v;
282 }
283
284 return v;
285}
286
288// new virtual functions which can be overridden by derived classes
290
291// none
292
294// non-virtual functions in this class
296
298{
299 return cond? &safe_bool_helper::nonnull : nullptr;
300}
301
307relational::operator relational::safe_bool() const
308{
309 const ex df = lh-rh; // like ::canonical() method
310 // We treat numeric and symbolic expression differently
311 if (is_exactly_a<numeric>(df)) {
312 switch (o) {
313 case equal:
314 return make_safe_bool(ex_to<numeric>(df).is_zero());
315 case not_equal:
316 return make_safe_bool(!ex_to<numeric>(df).is_zero());
317 case less:
318 return make_safe_bool(ex_to<numeric>(df)<(*_num0_p));
319 case less_or_equal:
320 return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
321 case greater:
322 return make_safe_bool(ex_to<numeric>(df)>(*_num0_p));
323 case greater_or_equal:
324 return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p));
325 default:
326 throw(std::logic_error("invalid relational operator"));
327 }
328 } else {
329 // The conversion for symbolic expressions is based on the info flags
330 switch (o) {
331 case equal:
332 return make_safe_bool(df.is_zero());
333 case not_equal:
334 return make_safe_bool(! df.is_zero());
335 case less:
337 case less_or_equal:
339 case greater:
341 case greater_or_equal:
343 default:
344 throw(std::logic_error("invalid relational operator"));
345 }
346 }
347}
348
352{
353 return relational(lh-rh, _ex0, o);
354}
355
356} // namespace GiNaC
Archiving of GiNaC expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition assertion.h:32
This class stores all properties needed to record/retrieve the state of one object of class basic (or...
Definition archive.h:48
This class is the ABC (abstract base class) of GiNaC's class hierarchy.
Definition basic.h:104
const basic & setflag(unsigned f) const
Set some status_flags.
Definition basic.h:287
unsigned hashvalue
hash value
Definition basic.h:302
unsigned flags
of type status_flags
Definition basic.h:301
ex subs_one_level(const exmap &m, unsigned options) const
Helper function for subs().
Definition basic.cpp:584
virtual int compare_same_type(const basic &other) const
Returns order relation between two objects of same type.
Definition basic.cpp:718
void do_print_tree(const print_tree &c, unsigned level) const
Tree output to stream.
Definition basic.cpp:174
Wrapper template for making GiNaC classes out of STL containers.
Definition container.h:72
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:54
@ relation_greater_or_equal
Definition flags.h:242
@ relation_less_or_equal
Definition flags.h:240
Base class for print_contexts.
Definition print.h:101
Context for python-parsable output.
Definition print.h:137
This class holds a relation consisting of two expressions and a logical relation between them.
Definition relational.h:34
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:93
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:54
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:202
@ hash_calculated
.calchash() has already done its job
Definition flags.h:204
unsigned options
Definition factor.cpp:2473
size_t n
Definition factor.cpp:1431
size_t c
Definition factor.cpp:756
mvec m
Definition factor.cpp:757
Type-specific hash seed.
Definition add.cpp:35
bool is_zero(const ex &thisex)
Definition ex.h:835
std::map< ex, ex, ex_is_less > exmap
Definition basic.h:49
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:43
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:47
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:41
const ex _ex0
Definition utils.cpp:368
std::vector< ex > exvector
Definition basic.h:47
const numeric * _num0_p
Definition utils.cpp:366
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:183
Interface to relations between expressions.
Function object for map().
Definition basic.h:84
To distinguish between different kinds of non-commutative objects.
Definition registrar.h:42
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.