Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
352 lines (296 loc) · 11.1 KB

File metadata and controls

352 lines (296 loc) · 11.1 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/**
* @file basic.h
* @author SymEngine Developers
* @date 2021-03-01
* @brief The base class for SymEngine
*
* Created on: 2012-07-11
*
*/
#ifndef SYMENGINE_BASIC_H
#define SYMENGINE_BASIC_H
// Include all C++ headers here
#include <sstream>
#include <typeinfo>
#include <map>
#include <vector>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>
#include <type_traits>
#include <functional>
#include <algorithm>
#include <symengine/symengine_config.h>
#include <symengine/symengine_exception.h>
#ifdef WITH_SYMENGINE_THREAD_SAFE
#include <atomic>
#endif
#include <symengine/dict.h>
//! Main namespace for SymEngine package
namespace SymEngine
{
enum TypeID {
#define SYMENGINE_INCLUDE_ALL
#define SYMENGINE_ENUM(type, Class) type,
#include "symengine/type_codes.inc"
#undef SYMENGINE_ENUM
#undef SYMENGINE_INCLUDE_ALL
//!< The 'TypeID_Count' returns the number of elements in 'TypeID'. For this
//!< to work, do not assign numbers to the elements above (or if you do, you
//!< must assign the correct count below).
TypeID_Count
};
std::string type_code_name(TypeID id);
#include "basic-methods.inc"
class Visitor;
class Symbol;
/**
* @class Basic
* @brief The lowest unit of symbolic representation
*
* @details Classes like `Add`, `Mul`, `Pow` are initialized through their
* constructor using their internal representation. `Add`, `Mul` have a 'coeff'
* and 'dict', while `Pow` has 'base' and 'exp'. There are restrictions on what
* 'coeff' and 'dict' can be (for example 'coeff' cannot be zero in `Mul`, and
* if `Mul` is used inside `Add`, then `Mul`'s coeff must be one, etc.). All
* these restrictions are checked when `WITH_SYMENGINE_ASSERT` is enabled inside
* the constructors using the is_canonical() method. That way, you don't have to
* worry about creating `Add` / `Mul` / `Pow` with wrong arguments, as it will
* be caught by the tests. In the Release mode no checks are done, so you can
* construct `Add` / `Mul` / `Pow` very quickly. The idea is that depending on
* the algorithm, you sometimes know that things are already canonical, so you
* simply pass it directly to the constructors of the `Basic` classes and you
* avoid expensive type checking and canonicalization. At the same time, you
* need to make sure that tests are still running with `WITH_SYMENGINE_ASSERT`
* enabled, so that the `Basic` classes are never in an inconsistent state.
*
* Summary: always try to construct the expressions `Add` / `Mul` / `Pow`
* directly using their constructors and all the knowledge that you have for
* the given algorithm, that way things will be very fast. If you want slower
* but simpler code, you can use the add(), mul(), pow() functions that peform
* general and possibly slow canonicalization first.
*
* @note Any `Basic` class can be used in a "dictionary", due to the methods:
*
* __hash__()
* __eq__(o)
*
* @warning Subclasses must implement `__hash__()` and `__eq__()`
*
*/
class Basic : public EnableRCPFromThis<Basic>
{
private:
//! Private variables
// The hash_ is defined as mutable, because its value is initialized to 0
// in the constructor and then it can be changed in Basic::hash() to the
// current hash (which is always the same for the given instance). The
// state of the instance does not change, so we define hash_ as mutable.
#if defined(WITH_SYMENGINE_THREAD_SAFE)
mutable std::atomic<hash_t> hash_; // This holds the hash value
#else
mutable hash_t hash_; // This holds the hash value
#endif // WITH_SYMENGINE_THREAD_SAFE
public:
#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
virtual TypeID get_type_code() const = 0;
#else
TypeID type_code_;
inline TypeID get_type_code() const
{
return type_code_;
};
#endif
//! Constructor
Basic() : hash_{0} {}
// Destructor must be explicitly defined as virtual here to avoid problems
// with undefined behavior while deallocating derived classes.
virtual ~Basic() {}
//! Delete the copy constructor and assignment
Basic(const Basic &) = delete;
//! Assignment operator in continuation with above
Basic &operator=(const Basic &) = delete;
//! Delete the move constructor and assignment
Basic(Basic &&) = delete;
//! Assignment operator in continuation with above
Basic &operator=(Basic &&) = delete;
/**
* Calculates the hash of the given SymEngine class.
* Use Basic.hash() which gives a cached version of the hash.
* @return 64-bit integer value for the hash
*/
virtual hash_t __hash__() const = 0;
/** Returns the hash of the SymEngine class:
* This method caches the value
*
* Use `std::hash` to get the hash. Example:
*
* RCP<const Symbol> x = symbol("x");
* std::hash<Basic> hash_fn;
* std::cout << hash_fn(*x);
*
* @return 64-bit integer value for the hash
*/
hash_t hash() const;
/**
* @brief Test equality
*
* @details A virtual function for testing the equality of two `Basic`
* objects
* @deprecated Use eq(const Basic &a, const Basic &b) non-member method
*
* @param o a constant reference to object to test against
* @return True if `this` is equal to `o`
*/
virtual bool __eq__(const Basic &o) const = 0;
//! true if `this` is not equal to `o`.
bool __neq__(const Basic &o) const;
//! Comparison operator.
int __cmp__(const Basic &o) const;
/*! Returns -1, 0, 1 for `this < o, this == o, this > o`. This method is
used when you want to sort things like `x+y+z` into canonical order.
This function assumes that `o` is the same type as `this`. Use ` __cmp__`
if you want general comparison.
*/
virtual int compare(const Basic &o) const = 0;
/*! Returns string representation of `self`.
*/
std::string __str__() const;
//! Returns a string of the instance serialized.
std::string dumps() const;
//! Creates an instance of a serialized string.
static RCP<const Basic> loads(const std::string &);
//! Substitutes 'subs_dict' into 'self'.
RCP<const Basic> subs(const map_basic_basic &subs_dict) const;
RCP<const Basic> xreplace(const map_basic_basic &subs_dict) const;
//! expands the special function in terms of exp function
virtual RCP<const Basic> expand_as_exp() const
{
throw NotImplementedError("Not Implemented");
}
//! Returns the list of arguments
virtual vec_basic get_args() const = 0;
SYMENGINE_INCLUDE_METHODS_BASE()
RCP<const Basic> diff(const RCP<const Symbol> &x, bool cache = true) const;
};
//! Our hash:
struct RCPBasicHash {
//! Returns the hashed value.
size_t operator()(const RCP<const Basic> &k) const
{
return static_cast<size_t>(k->hash());
}
};
//! Our comparison `(==)`
struct RCPBasicKeyEq {
//! Comparison Operator `==`
bool operator()(const RCP<const Basic> &x, const RCP<const Basic> &y) const
{
return eq(*x, *y);
}
};
//! Our less operator `(<)`:
struct RCPBasicKeyLess {
//! true if `x < y`, false otherwise
bool operator()(const RCP<const Basic> &x, const RCP<const Basic> &y) const
{
hash_t xh = x->hash(), yh = y->hash();
if (xh != yh)
return xh < yh;
if (eq(*x, *y))
return false;
return x->__cmp__(*y) == -1;
}
};
// Convenience functions
//! Checks equality for `a` and `b`
bool eq(const Basic &a, const Basic &b);
//! Checks inequality for `a` and `b`
bool neq(const Basic &a, const Basic &b);
/*! Returns true if `b` is exactly of type `T`. Example:
`is_a<Symbol>(b)` : true if "b" is of type Symbol
*/
template <class T>
bool is_a(const Basic &b);
//! Returns true if `b` is an atom. i.e. b.get_args returns an empty vector
bool is_a_Atom(const Basic &b);
/*! Returns true if `b` is of type T or any of its subclasses.
* Example:
is_a_sub<Symbol>(b) // true if `b` is of type `Symbol` or any Symbol's
subclass
*/
template <class T>
bool is_a_sub(const Basic &b);
//! Returns true if `a` and `b` are exactly the same type `T`.
bool is_same_type(const Basic &a, const Basic &b);
//! Expands `self`
RCP<const Basic> expand(const RCP<const Basic> &self, bool deep = true);
void as_numer_denom(const RCP<const Basic> &x,
const Ptr<RCP<const Basic>> &numer,
const Ptr<RCP<const Basic>> &denom);
void as_real_imag(const RCP<const Basic> &x, const Ptr<RCP<const Basic>> &real,
const Ptr<RCP<const Basic>> &imag);
RCP<const Basic> rewrite_as_exp(const RCP<const Basic> &x);
RCP<const Basic> rewrite_as_sin(const RCP<const Basic> &x);
RCP<const Basic> rewrite_as_cos(const RCP<const Basic> &x);
// Common subexpression elimination of symbolic expressions
// Return a vector of replacement pairs and a vector of reduced exprs
void cse(vec_pair &replacements, vec_basic &reduced_exprs,
const vec_basic &exprs);
/*! This `<<` overloaded function simply calls `p.__str__`, so it allows any
Basic
type to be printed.
This prints using: `std::cout << *x;`
*/
std::ostream &operator<<(std::ostream &out, const SymEngine::Basic &p);
/*! Standard `hash_combine()` function. Example of usage:
hash_t seed1 = 0;
hash_combine<std::string>(seed1, "x");
hash_combine<std::string>(seed1, "y");
You can use it with any SymEngine class:
RCP<const Symbol> x = symbol("x");
RCP<const Symbol> y = symbol("y");
hash_t seed2 = 0;
hash_combine<Basic>(seed2, *x);
hash_combine<Basic>(seed2, *y);
*/
template <class T>
void hash_combine(hash_t &seed, const T &v);
const char *get_version();
} // namespace SymEngine
namespace std
{
//! Specialise `std::hash` for Basic.
template <>
struct hash<SymEngine::Basic>;
} // namespace std
//! Inline members and functions
#include "basic-inl.h"
#include <symengine/tribool.h>
// Macro to define the type_code_id variable and its getter method
#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
#define IMPLEMENT_TYPEID(SYMENGINE_ID) \
/*! Type_code_id shared by all instances */ \
const static TypeID type_code_id = SYMENGINE_ID; \
/*! Virtual function that gives the type_code_id of the object */ \
virtual TypeID get_type_code() const \
{ \
return type_code_id; \
}; \
SYMENGINE_INCLUDE_METHODS_DERIVED()
#else
#define IMPLEMENT_TYPEID(SYMENGINE_ID) \
/*! Type_code_id shared by all instances */ \
const static TypeID type_code_id = SYMENGINE_ID; \
SYMENGINE_INCLUDE_METHODS_DERIVED()
#endif
#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
#define SYMENGINE_ASSIGN_TYPEID()
#else
#define SYMENGINE_ASSIGN_TYPEID() this->type_code_ = type_code_id;
#endif
#endif
Morty Proxy This is a proxified and sanitized view of the page, visit original site.