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

void accept (Visitor &v) const override
 
void accept (EvalRealDoubleVisitorFinal &v) const override
 
 Add (const RCP< const Number > &coef, umap_basic_num &&dict)
 Default constructor. More...
 
hash_t __hash__ () const override
 Generates the hash representation. More...
 
bool __eq__ (const Basic &o) const override
 Test equality. More...
 
int compare (const Basic &o) const override
 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...
 
vec_basic get_args () const override
 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.
 
 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.
 
hash_t hash () const
 
bool __neq__ (const Basic &o) const
 true if this is not equal to o. More...
 
int __cmp__ (const Basic &o) const
 Comparison operator.
 
std::string __str__ () const
 
std::string dumps () const
 Returns a string of the instance serialized.
 
RCP< const Basicsubs (const map_basic_basic &subs_dict) const
 Substitutes 'subs_dict' into 'self'.
 
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
 
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)
 
RCP< const Basicrcp_from_this () const
 Get RCP<const T> pointer to self (it will cast the pointer to const T)
 
RCP< const T2 > rcp_from_this_cast () const
 Get RCP<T2> pointer to self (it will cast the pointer to T2)
 
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.
 

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
overridevirtual

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
overridevirtual

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 }

◆ 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);
294  *b = Add::from_dict(coef_, std::move(d));
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
overridevirtual

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
overridevirtual

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.

◆ 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: