Loading...
Searching...
No Matches
SymEngine::Add Class Reference

The base class for representing addition in symbolic expressions. More...

#include <add.h>

+ Inheritance diagram for SymEngine::Add:
+ Collaboration diagram for SymEngine::Add:

Public Member Functions

virtual void accept (Visitor &v) const
 
virtual void accept (EvalRealDoubleVisitorFinal &v) const
 
 Add (const RCP< const Number > &coef, umap_basic_num &&dict)
 Default constructor. More...
 
virtual hash_t __hash__ () const
 Generates the hash representation. More...
 
virtual bool __eq__ (const Basic &o) const
 Test equality. More...
 
virtual int compare (const Basic &o) const
 Compares Add objects. More...
 
void as_two_terms (const Ptr< RCP< const Basic > > &a, const Ptr< RCP< const Basic > > &b) const
 Converts the Add into a sum of two Basic objects. More...
 
bool is_canonical (const RCP< const Number > &coef, const umap_basic_num &dict) const
 Checks if a given dictionary and coeffient is in cannonical form. More...
 
virtual vec_basic get_args () const
 Returns the arguments of the Add. More...
 
const RCP< const Number > & get_coef () const
 
const umap_basic_numget_dict () const
 
- Public Member Functions inherited from SymEngine::Basic
TypeID get_type_code () const
 
 Basic ()
 Constructor. More...
 
 Basic (const Basic &)=delete
 Delete the copy constructor and assignment.
 
Basicoperator= (const Basic &)=delete
 Assignment operator in continuation with above.
 
 Basic (Basic &&)=delete
 Delete the move constructor and assignment.
 
Basicoperator= (Basic &&)=delete
 Assignment operator in continuation with above.
 
virtual hash_t __hash__ () const =0
 
hash_t hash () const
 
virtual bool __eq__ (const Basic &o) const =0
 Test equality. More...
 
bool __neq__ (const Basic &o) const
 true if this is not equal to o. More...
 
int __cmp__ (const Basic &o) const
 Comparison operator. More...
 
virtual int compare (const Basic &o) const =0
 
std::string __str__ () const
 
std::string dumps () const
 Returns a string of the instance serialized. More...
 
RCP< const Basicsubs (const map_basic_basic &subs_dict) const
 Substitutes 'subs_dict' into 'self'. More...
 
RCP< const Basicxreplace (const map_basic_basic &subs_dict) const
 
virtual RCP< const Basicexpand_as_exp () const
 expands the special function in terms of exp function More...
 
virtual vec_basic get_args () const =0
 Returns the list of arguments. More...
 
virtual void accept (Visitor &v) const =0
 
virtual void accept (EvalRealDoubleVisitorFinal &v) const =0
 
RCP< const Basicdiff (const RCP< const Symbol > &x, bool cache=true) const
 
- Public Member Functions inherited from SymEngine::EnableRCPFromThis< Basic >
RCP< Basicrcp_from_this ()
 Get RCP<T> pointer to self (it will cast the pointer to T) More...
 
RCP< const Basicrcp_from_this () const
 Get RCP<const T> pointer to self (it will cast the pointer to const T) More...
 
RCP< const T2 > rcp_from_this_cast () const
 Get RCP<T2> pointer to self (it will cast the pointer to T2) More...
 
unsigned int use_count () const
 

Static Public Member Functions

static RCP< const Basicfrom_dict (const RCP< const Number > &coef, umap_basic_num &&d)
 Create an appropriate instance from dictionary quickly. More...
 
static void dict_add_term (umap_basic_num &d, const RCP< const Number > &coef, const RCP< const Basic > &t)
 Adds a new term to the expression. More...
 
static void coef_dict_add_term (const Ptr< RCP< const Number > > &coef, umap_basic_num &d, const RCP< const Number > &c, const RCP< const Basic > &term)
 Updates the numerical coefficient and the dictionary. More...
 
static void as_coef_term (const RCP< const Basic > &self, const Ptr< RCP< const Number > > &coef, const Ptr< RCP< const Basic > > &term)
 Converts a Basic self into the form of coefficient * term. More...
 
- Static Public Member Functions inherited from SymEngine::Basic
static RCP< const Basicloads (const std::string &)
 Creates an instance of a serialized string. More...
 

Static Public Attributes

static const TypeID type_code_id = SYMENGINE_ADD
 

Private Attributes

RCP< const Numbercoef_
 
umap_basic_num dict_
 

Related Functions

(Note that these are not member functions.)

RCP< const Basicadd (const RCP< const Basic > &a, const RCP< const Basic > &b)
 Adds two objects (safely). More...
 
RCP< const Basicadd (const vec_basic &a)
 Sums the elements of a vector. More...
 
RCP< const Basicsub (const RCP< const Basic > &a, const RCP< const Basic > &b)
 Substracts b from a. More...
 

Additional Inherited Members

- Data Fields inherited from SymEngine::Basic
TypeID type_code_
 

Detailed Description

The base class for representing addition in symbolic expressions.

Internally this is implemented in as a numeric coefficient coef_ and a dictionary dict_ of key-value pairs. Consider the following example:

Add(coef_, {{key1, value1}, {key2, value2}, ... })

This represents the following expression,

 coef_ + key1*value1 + key2*value2 + ...

coef_ and the values of the dictionary may be numeric coefficients like Integer, RealDouble, Complex while their corresponding keys can be any symbolic expression except numeric coefficients and Mul objects with coefficient != 1.

For example, the following are valid representations

 Add(1, {{x, 2}, {y, 5}})
 Add(0, {{x, 1}, {y, 4}, {z, 3}})

The following representations are invalid (their valid equivalent is shown next to each of them)

 Add(1, {{x, 1}, {2*y, 3})   -> Add(1, {{x, 1}, {y, 6}})
 Add(0, {{x, 2}})             -> Mul(2, {{x, 1}})
 Add(1, {{x, 2}, {4, 6}})    -> Add(25, {{x, 2}})

A visual aid (from the SymEngine Wiki) for understanding this class in the broader context of the data structure for mathematical expressions is:

Sample Expression Data Structure
See also
Basic for an explanation of how the intialization works in conjuction to the constructors of the Basic class and the guarantees in Release.

Definition at line 26 of file add.h.

Constructor & Destructor Documentation

◆ Add()

SymEngine::Add::Add ( const RCP< const Number > &  coef,
umap_basic_num &&  dict 
)

Default constructor.

Precondition
Input must be in cannonical form.
Parameters
coefnumeric coefficient.
dictdictionary of the expression without the coefficient.

Constructs Add from a dictionary by copying the contents of the dictionary.

Definition at line 64 of file add.cpp.

65 : coef_{coef}, dict_{std::move(dict)} {
66 SYMENGINE_ASSIGN_TYPEID()
67 SYMENGINE_ASSERT(is_canonical(coef, dict_))}
umap_basic_num dict_
Definition: add.h:31
RCP< const Number > coef_
Definition: add.h:29
bool is_canonical(const RCP< const Number > &coef, const umap_basic_num &dict) const
Checks if a given dictionary and coeffient is in cannonical form.
Definition: add.cpp:348
T move(T... args)

Member Function Documentation

◆ __eq__()

bool SymEngine::Add::__eq__ ( const Basic o) const
virtual

Test equality.

Deprecated:
Use eq(const Basic &a, const Basic &b) instead.
Parameters
oa constant reference to object to test against.
Returns
True if this is equal to o.

This older implementation compares the elements of the coefficients and expressions for two objects.

Implements SymEngine::Basic.

Definition at line 88 of file add.cpp.

89{
90 if (is_a<Add>(o) and eq(*coef_, *(down_cast<const Add &>(o).coef_))
91 and unified_eq(dict_, down_cast<const Add &>(o).dict_))
92 return true;
93
94 return false;
95}
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21

◆ __hash__()

hash_t SymEngine::Add::__hash__ ( ) const
virtual

Generates the hash representation.

See also
Basic for an implementation to get the cached version.
Returns
64-bit integer value for the hash.

This uses Basic.hash() to give a cached version of the hash.

Implements SymEngine::Basic.

Definition at line 72 of file add.cpp.

73{
74 hash_t seed = SYMENGINE_ADD, temp;
75 hash_combine<Basic>(seed, *coef_);
76 for (const auto &p : dict_) {
77 temp = p.first->hash();
78 hash_combine<Basic>(temp, *(p.second));
79 seed ^= temp;
80 }
81 return seed;
82}

◆ accept() [1/2]

virtual void SymEngine::Add::accept ( EvalRealDoubleVisitorFinal v) const
virtual

Implements SymEngine::Basic.

◆ accept() [2/2]

virtual void SymEngine::Add::accept ( Visitor v) const
virtual

Implements SymEngine::Basic.

◆ as_coef_term()

void SymEngine::Add::as_coef_term ( const RCP< const Basic > &  self,
const Ptr< RCP< const Number > > &  coef,
const Ptr< RCP< const Basic > > &  term 
)
static

Converts a Basic self into the form of coefficient * term.

Parameters
coefnumerical coefficient.
termthe term.
Returns
Void.

This function converts the its representation as per the following logic:

  • If self is a Mul return the coefficient and the remaining term.
  • If self is not Mul or Add the coefficient is set one and the term is unchanged.
  • If self is a Number the term is set one and the coefficient is unchanged.

Definition at line 306 of file add.cpp.

309{
310 if (is_a<Mul>(*self)) {
311 if (neq(*(down_cast<const Mul &>(*self).get_coef()), *one)) {
312 *coef = (down_cast<const Mul &>(*self)).get_coef();
313 // We need to copy our 'dict_' here, as 'term' has to have its own.
314 map_basic_basic d2 = (down_cast<const Mul &>(*self)).get_dict();
315 *term = Mul::from_dict(one, std::move(d2));
316 } else {
317 *coef = one;
318 *term = self;
319 }
320 } else if (is_a_Number(*self)) {
321 *coef = rcp_static_cast<const Number>(self);
322 *term = one;
323 } else {
324 SYMENGINE_ASSERT(not is_a<Add>(*self));
325 *coef = one;
326 *term = self;
327 }
328}
const RCP< const Number > & get_coef() const
Definition: add.h:142
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
Definition: mul.cpp:115
bool is_a_Number(const Basic &b)
Definition: number.h:130
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29

◆ as_two_terms()

void SymEngine::Add::as_two_terms ( const Ptr< RCP< const Basic > > &  a,
const Ptr< RCP< const Basic > > &  b 
) const

Converts the Add into a sum of two Basic objects.

Parameters
afirst basic object.
bsecond basic object.
Returns
Void.

This implementation first converts a to a Mul and then performs addition.

Definition at line 287 of file add.cpp.

289{
290 auto p = dict_.begin();
291 *a = mul(p->first, p->second);
292 umap_basic_num d = dict_;
293 d.erase(p->first);
295}
T begin(T... args)
static RCP< const Basic > from_dict(const RCP< const Number > &coef, umap_basic_num &&d)
Create an appropriate instance from dictionary quickly.
Definition: add.cpp:140
T erase(T... args)
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition: mul.cpp:352

◆ coef_dict_add_term()

void SymEngine::Add::coef_dict_add_term ( const Ptr< RCP< const Number > > &  coef,
umap_basic_num d,
const RCP< const Number > &  c,
const RCP< const Basic > &  term 
)
static

Updates the numerical coefficient and the dictionary.

Parameters
coefthe numerical coefficient.
dthe dictionary containing the expression.
cthe numerical coefficient to be added.
termthe new term.
Returns
Void.

This implements the following logic:

  • If both c and term are numbers, then the term (c* term) is added to the existing coeff.
  • If term is not a number then the pair (c, term) is used to update the existing dict d (as a pair c, term).
  • In case term is Add and c=1, expands the Add into the coeff and d.

Definition at line 261 of file add.cpp.

264{
265 if (is_a_Number(*term)) {
266 iaddnum(coef, mulnum(c, rcp_static_cast<const Number>(term)));
267 } else if (is_a<Add>(*term)) {
268 if (c->is_one()) {
269 for (const auto &q : (down_cast<const Add &>(*term)).dict_)
270 Add::dict_add_term(d, q.second, q.first);
271 iaddnum(coef, down_cast<const Add &>(*term).coef_);
272 } else {
273 Add::dict_add_term(d, c, term);
274 }
275 } else {
276 RCP<const Number> coef2;
277 RCP<const Basic> t;
278 Add::as_coef_term(term, outArg(coef2), outArg(t));
279 Add::dict_add_term(d, mulnum(c, coef2), t);
280 }
281}
static void dict_add_term(umap_basic_num &d, const RCP< const Number > &coef, const RCP< const Basic > &t)
Adds a new term to the expression.
Definition: add.cpp:237
static void as_coef_term(const RCP< const Basic > &self, const Ptr< RCP< const Number > > &coef, const Ptr< RCP< const Basic > > &term)
Converts a Basic self into the form of coefficient * term.
Definition: add.cpp:306
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
Definition: number.h:93

◆ compare()

int SymEngine::Add::compare ( const Basic o) const
virtual

Compares Add objects.

Parameters
oobject to test against.
See also
unified_compare() for the actual implementation.
Returns
1 if this is equal to o otherwise (-1).

This function takes a Basic object, checks if it is an Add object, and subsequently compares exhaustively:

  • The number of elements.
  • The coefficients.
  • Each element of the dictionary.
Note
Since the map_basic_num representation is not cached by Add after being computed, this is slow.

<

Todo:
cache adict and bdict

Implements SymEngine::Basic.

Definition at line 107 of file add.cpp.

108{
109 SYMENGINE_ASSERT(is_a<Add>(o))
110 const Add &s = down_cast<const Add &>(o);
111 // # of elements
112 if (dict_.size() != s.dict_.size())
113 return (dict_.size() < s.dict_.size()) ? -1 : 1;
114
115 // coef
116 int cmp = coef_->__cmp__(*s.coef_);
117 if (cmp != 0)
118 return cmp;
119
120 // Compare dictionaries (slow):
122 map_basic_num adict(dict_.begin(), dict_.end());
123 map_basic_num bdict(s.dict_.begin(), s.dict_.end());
124 return unified_compare(adict, bdict);
125}
Add(const RCP< const Number > &coef, umap_basic_num &&dict)
Default constructor.
Definition: add.cpp:64
T end(T... args)
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
T size(T... args)

◆ dict_add_term()

void SymEngine::Add::dict_add_term ( umap_basic_num d,
const RCP< const Number > &  coef,
const RCP< const Basic > &  t 
)
static

Adds a new term to the expression.

Precondition
The coefficient of the new term is non-zero.
Parameters
ddictionary to be updated.
coefnew coefficient.
tnew term.
Returns
Void.

Adds (coeff*t) to the dict d inplace.

Warning
We assume that t has no numerical coefficients, and coef has only numerical coefficients.

Definition at line 237 of file add.cpp.

239{
240 auto it = d.find(t);
241 if (it == d.end()) {
242 // Not found, add it in if it is nonzero:
243 if (not(coef->is_zero()))
244 insert(d, t, coef);
245 } else {
246 iaddnum(outArg(it->second), coef);
247 if (it->second->is_zero())
248 d.erase(it);
249 }
250}
void insert(T1 &m, const T2 &first, const T3 &second)
Definition: dict.h:83

◆ from_dict()

RCP< const Basic > SymEngine::Add::from_dict ( const RCP< const Number > &  coef,
umap_basic_num &&  d 
)
static

Create an appropriate instance from dictionary quickly.

Precondition
The dictionary must be in canonical form.
See also
Mul for how Pow gets returned.
Basic for the guarantees and expectations.
Parameters
coefthe numeric coefficient.
dthe dictionary of the expression without the coefficient.
Returns
coef if the dictionary is empty (size 0).
Mul if the dictionary has one element which is a Mul.
Integer if the dictionary has one element which is a Integer.
Symbol if the dictionary has one element which is a Symbol.
Pow if the dictionary has one element which is a Pow.
Add if the size of the dictionary is greater than 1.

Quick implementation which depends only on the size of d.

The speed benefits also arise from the fact that when using the SymEngine::RCP in production mode (which is not thread safe) then when a single Mul object is encountered, instead of copying its dict_, it is reused instead.

That is, when WITH_SYMENGINE_THREAD_SAFE is not defined and WITH_SYMENGINE_RCP is defined, we can "steal" its dictionary by explictly casting away the const'ness. Since the refcount_ is 1, nothing else is using the Mul.

Definition at line 140 of file add.cpp.

142{
143 if (d.size() == 0) {
144 return coef;
145 } else if (d.size() == 1 and coef->is_zero()) {
146 auto p = d.begin();
147 if (is_a<Integer>(*(p->second))) {
148 if (down_cast<const Integer &>(*(p->second)).is_zero()) {
149 return p->second; // Symbol
150 }
151 if (down_cast<const Integer &>(*(p->second)).is_one()) {
152 return p->first; // Integer
153 }
154 if (is_a<Mul>(*(p->first))) {
155#if !defined(WITH_SYMENGINE_THREAD_SAFE) && defined(WITH_SYMENGINE_RCP)
156 if (down_cast<const Mul &>(*(p->first)).use_count() == 1) {
157 // We can steal the dictionary:
158 // Cast away const'ness, so that we can move 'dict_', since
159 // 'p->first' will be destroyed when 'd' is at the end of
160 // this function, so we "steal" its dict_ to avoid an
161 // unnecessary copy. We know the refcount_ is one, so
162 // nobody else is using the Mul except us.
163 const map_basic_basic &d2
164 = down_cast<const Mul &>(*(p->first)).get_dict();
165 map_basic_basic &d3 = const_cast<map_basic_basic &>(d2);
166 return Mul::from_dict(p->second, std::move(d3));
167 } else {
168#else
169 {
170#endif
171 // We need to copy the dictionary:
172 map_basic_basic d2
173 = down_cast<const Mul &>(*(p->first)).get_dict();
174 return Mul::from_dict(
175 p->second,
176 std::move(d2)); // Can return a Pow object here
177 }
178 }
179 map_basic_basic m;
180 if (is_a<Pow>(*(p->first))) {
181 insert(m, down_cast<const Pow &>(*(p->first)).get_base(),
182 down_cast<const Pow &>(*(p->first)).get_exp());
183 } else {
184 insert(m, p->first, one);
185 }
186 return make_rcp<const Mul>(p->second,
187 std::move(m)); // Returns a Mul from here
188 }
189 map_basic_basic m;
190 if (is_a_Number(*p->second)) {
191 if (is_a<Mul>(*(p->first))) {
192#if !defined(WITH_SYMENGINE_THREAD_SAFE) && defined(WITH_SYMENGINE_RCP)
193 if (down_cast<const Mul &>(*(p->first)).use_count() == 1) {
194 // We can steal the dictionary:
195 // Cast away const'ness, so that we can move 'dict_', since
196 // 'p->first' will be destroyed when 'd' is at the end of
197 // this function, so we "steal" its dict_ to avoid an
198 // unnecessary copy. We know the refcount_ is one, so
199 // nobody else is using the Mul except us.
200 const map_basic_basic &d2
201 = down_cast<const Mul &>(*(p->first)).get_dict();
202 map_basic_basic &d3 = const_cast<map_basic_basic &>(d2);
203 return Mul::from_dict(p->second, std::move(d3));
204 } else {
205#else
206 {
207#endif
208 // We need to copy the dictionary:
209 map_basic_basic d2
210 = down_cast<const Mul &>(*(p->first)).get_dict();
211 return Mul::from_dict(p->second,
212 std::move(d2)); // May return a Pow
213 }
214 }
215 if (is_a<Pow>(*p->first)) {
216 insert(m, down_cast<const Pow &>(*(p->first)).get_base(),
217 down_cast<const Pow &>(*(p->first)).get_exp());
218 } else {
219 insert(m, p->first, one);
220 }
221 return make_rcp<const Mul>(p->second, std::move(m));
222 } else {
223 insert(m, p->first, one);
224 insert(m, p->second, one);
225 return make_rcp<const Mul>(one, std::move(m));
226 }
227 } else {
228 return make_rcp<const Add>(coef, std::move(d)); // returns an Add
229 }
230}

◆ get_args()

vec_basic SymEngine::Add::get_args ( ) const
virtual

Returns the arguments of the Add.

Returns
list of arguments.
const reference to the coefficient of the Add.

For an Add of the form:

Add(coef_, {{key1, value1}, {key2, value2}, ... })

If coef_ is non-zero it returns:

{coef_, key1*value1, key2*value2, ... }

otherwise it returns:

{key1*value1, key2*value2, ... }

Implements SymEngine::Basic.

Definition at line 397 of file add.cpp.

398{
399 vec_basic args;
400 if (not coef_->is_zero()) {
401 args.reserve(dict_.size() + 1);
402 args.push_back(coef_);
403 } else {
404 args.reserve(dict_.size());
405 }
406 for (const auto &p : dict_) {
407 if (eq(*p.second, *one)) {
408 args.push_back(p.first);
409 } else {
410 args.push_back(Add::from_dict(zero, {{p.first, p.second}}));
411 }
412 }
413 return args;
414}
T reserve(T... args)

◆ get_coef()

const RCP< const Number > & SymEngine::Add::get_coef ( ) const
inline
Returns
const reference to the dictionary of the Add

Definition at line 142 of file add.h.

◆ get_dict()

const umap_basic_num & SymEngine::Add::get_dict ( ) const
inline

Definition at line 148 of file add.h.

149 {
150 return dict_;
151 }

◆ is_canonical()

bool SymEngine::Add::is_canonical ( const RCP< const Number > &  coef,
const umap_basic_num dict 
) const

Checks if a given dictionary and coeffient is in cannonical form.

Parameters
coefnumerical coefficient.
dictdictionary of remaining expression terms.
Returns
true if canonical.

This function ensures that each term in dict is in canonical form. The implementation in the form of a exclusion list (defaults to true).

Note
Canonical form requires the existance of both coef and dict, so null coefficients and purely numerical (empty dictionaries) are also not considered to be in canonical form. Also, the ordering is important, it must be (coeff, dict) and not (dict, coeff).

Some non-cannonical forms are:

  • $0 + x$.
  • $0 + 2x$.
  • $ 2 \times 3 $.
  • $ x \times 0 $.
  • $ 1 \times x $ has the wrong order.
  • $ 3x \times 2 $ is actually just $6x$.

Definition at line 348 of file add.cpp.

350{
351 if (coef == null)
352 return false;
353 if (dict.size() == 0)
354 return false;
355 if (dict.size() == 1) {
356 // e.g. 0 + x, 0 + 2x
357 if (coef->is_zero())
358 return false;
359 }
360 // Check that each term in 'dict' is in canonical form
361 for (const auto &p : dict) {
362 if (p.first == null)
363 return false;
364 if (p.second == null)
365 return false;
366 // e.g. 2*3
367 if (is_a_Number(*p.first))
368 return false;
369 // e.g. 1*x (={1:x}), this should rather be just x (={x:1})
370 if (is_a<Integer>(*p.first)
371 and down_cast<const Integer &>(*p.first).is_one())
372 return false;
373 // e.g. x*0
374 if (is_a_Number(*p.second)
375 and down_cast<const Number &>(*p.second).is_zero())
376 return false;
377
378 // e.g. {3x: 2}, this should rather be just {x: 6}
379 if (is_a<Mul>(*p.first)
380 and not(down_cast<const Mul &>(*p.first).get_coef()->is_one()))
381 return false;
382 }
383 return true;
384}

Friends And Related Function Documentation

◆ add() [1/2]

RCP< const Basic > add ( const RCP< const Basic > &  a,
const RCP< const Basic > &  b 
)
related

Adds two objects (safely).

Parameters
ais a Basic object.
bis a Basic object.
Returns
a+b in its most aproriate form.

Definition at line 425 of file add.cpp.

426{
428 RCP<const Number> coef;
429 RCP<const Basic> t;
430 if (is_a<Add>(*a) and is_a<Add>(*b)) {
431 coef = (down_cast<const Add &>(*a)).get_coef();
432 d = (down_cast<const Add &>(*a)).get_dict();
433 for (const auto &p : (down_cast<const Add &>(*b)).get_dict())
434 Add::dict_add_term(d, p.second, p.first);
435 iaddnum(outArg(coef), down_cast<const Add &>(*b).get_coef());
436 } else if (is_a<Add>(*a)) {
437 coef = (down_cast<const Add &>(*a)).get_coef();
438 d = (down_cast<const Add &>(*a)).get_dict();
439 if (is_a_Number(*b)) {
440 if (not down_cast<const Number &>(*b).is_zero()) {
441 iaddnum(outArg(coef), rcp_static_cast<const Number>(b));
442 }
443 } else {
444 RCP<const Number> coef2;
445 Add::as_coef_term(b, outArg(coef2), outArg(t));
446 Add::dict_add_term(d, coef2, t);
447 }
448 } else if (is_a<Add>(*b)) {
449 coef = (down_cast<const Add &>(*b)).get_coef();
450 d = (down_cast<const Add &>(*b)).get_dict();
451 if (is_a_Number(*a)) {
452 if (not down_cast<const Number &>(*a).is_zero()) {
453 iaddnum(outArg(coef), rcp_static_cast<const Number>(a));
454 }
455 } else {
456 RCP<const Number> coef2;
457 Add::as_coef_term(a, outArg(coef2), outArg(t));
458 Add::dict_add_term(d, coef2, t);
459 }
460 } else {
461 Add::as_coef_term(a, outArg(coef), outArg(t));
462 Add::dict_add_term(d, coef, t);
463 Add::as_coef_term(b, outArg(coef), outArg(t));
464 Add::dict_add_term(d, coef, t);
465 auto it = d.find(one);
466 if (it == d.end()) {
467 coef = zero;
468 } else {
469 coef = it->second;
470 d.erase(it);
471 }
472 return Add::from_dict(coef, std::move(d));
473 }
474 return Add::from_dict(coef, std::move(d));
475}
T find(T... args)

◆ add() [2/2]

RCP< const Basic > add ( const vec_basic a)
related

Sums the elements of a vector.

Parameters
ais a vector.
Returns
sum of elements of the input vector a.

Definition at line 481 of file add.cpp.

482{
484 RCP<const Number> coef = zero;
485 for (const auto &i : a) {
486 Add::coef_dict_add_term(outArg(coef), d, one, i);
487 }
488 return Add::from_dict(coef, std::move(d));
489}
static void coef_dict_add_term(const Ptr< RCP< const Number > > &coef, umap_basic_num &d, const RCP< const Number > &c, const RCP< const Basic > &term)
Updates the numerical coefficient and the dictionary.
Definition: add.cpp:261

◆ sub()

RCP< const Basic > sub ( const RCP< const Basic > &  a,
const RCP< const Basic > &  b 
)
related

Substracts b from a.

Parameters
ais the minuend.
bis the subtrahend.
Returns
the difference a-b.

Definition at line 495 of file add.cpp.

496{
497 return add(a, mul(minus_one, b));
498}
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425

Field Documentation

◆ coef_

RCP<const Number> SymEngine::Add::coef_
private

The numeric coefficient of the expression (e.g. 2 in 2+x+y).

Definition at line 29 of file add.h.

◆ dict_

umap_basic_num SymEngine::Add::dict_
private

The expression without its coefficient as a dictionary (e.g. x+y in 2+x+y).

Definition at line 31 of file add.h.

◆ type_code_id

const TypeID SymEngine::Add::type_code_id = SYMENGINE_ADD
static

Type_code_id shared by all instances

Definition at line 35 of file add.h.


The documentation for this class was generated from the following files: