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

#include <mul.h>

+ Inheritance diagram for SymEngine::Mul:
+ Collaboration diagram for SymEngine::Mul:

Public Member Functions

virtual void accept (Visitor &v) const
 
virtual void accept (EvalRealDoubleVisitorFinal &v) const
 
 Mul (const RCP< const Number > &coef, map_basic_basic &&dict)
 
virtual hash_t __hash__ () const
 
virtual bool __eq__ (const Basic &o) const
 
virtual int compare (const Basic &o) const
 
void as_two_terms (const Ptr< RCP< const Basic > > &a, const Ptr< RCP< const Basic > > &b) const
 Rewrite as 2 terms. More...
 
void power_num (const Ptr< RCP< const Number > > &coef, map_basic_basic &d, const RCP< const Number > &exp) const
 Power all terms with the exponent exp More...
 
bool is_canonical (const RCP< const Number > &coef, const map_basic_basic &dict) const
 
virtual vec_basic get_args () const
 Returns the list of arguments. More...
 
const RCP< const Number > & get_coef () const
 
const map_basic_basicget_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, map_basic_basic &&d)
 Create a Mul from a dict. More...
 
static void dict_add_term (map_basic_basic &d, const RCP< const Basic > &exp, const RCP< const Basic > &t)
 Add terms to dict. More...
 
static void dict_add_term_new (const Ptr< RCP< const Number > > &coef, map_basic_basic &d, const RCP< const Basic > &exp, const RCP< const Basic > &t)
 
static void as_base_exp (const RCP< const Basic > &self, const Ptr< RCP< const Basic > > &exp, const Ptr< RCP< const Basic > > &base)
 Convert to a base and exponent form. 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_MUL
 the dictionary of the rest (e.g. x*y in 2*x*y) More...
 

Private Attributes

RCP< const Numbercoef_
 
map_basic_basic dict_
 The coefficient (e.g. 2 in 2*x*y) More...
 

Additional Inherited Members

- Data Fields inherited from SymEngine::Basic
TypeID type_code_
 

Detailed Description

Mul class keeps a product of symbolic expressions. Internal representation of an Mul is a numeric coefficient coef_ and a dictionary dict_ of key-value pairs.

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

This represents the following expression,

 coef_ * key1^value1 * key2^value2 * ...

coef_ is an objecct of type Number, i.e. a numeric coefficient like Integer, RealDouble, Complex.

For example, the following are valid representations

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

Following are invalid representations. (valid equivalent is shown next to them)

When key is a numeric and value is an integers,

Mul(2, {{3, 2}, {x, 2}}) -> Mul(18, {{x, 2}}) Mul(2, {{I, 3}, {x, 2}}) -> Mul(-2*I, {{x, 2}})

When key is an integer and value is a Rational not in the range (0, 1)

Mul(2, {{3, 3/2}, {x, 2}}) -> Mul(6, {{3, 1/2}, {x, 2}}) Mul(2, {{3, -1/2}, {x, 2}}) -> Mul(2/3, {{3, 1/2}, {x, 2}})

When the value is zero

Mul(3, {{x, 0}, {y, 2}}) -> Mul(3, {{y, 2}})

When key and value are numeric and one of them is inexact

Mul(2, {{3, 0.5}, {x, 2}}) -> Mul(3.464..., {x, 2}})

When coef_ is one and the dictionary is of size 1

Mul(1, {{x, 2}}) -> Pow(x, 2)

When coef_ is zero

Mul(0, {{x, 2}}) -> Integer(0) Mul(0.0, {{x, 2}}) -> RealDouble(0.0)

When key is 1

Mul(2, {{1, x}, {x, 2}}) -> Mul(2, {{x, 2}})

When value is zero

Mul(2, {{1, x}, {x, 2}}) -> Mul(2, {{x, 2}})

Definition at line 73 of file mul.h.

Constructor & Destructor Documentation

◆ Mul()

SymEngine::Mul::Mul ( const RCP< const Number > &  coef,
map_basic_basic &&  dict 
)

Constructs Mul from a dictionary by copying the contents of the dictionary:

Definition at line 10 of file mul.cpp.

11 : coef_{coef}, dict_{std::move(dict)}
12{
13 SYMENGINE_ASSIGN_TYPEID()
14 SYMENGINE_ASSERT(is_canonical(coef, dict_))
15}
bool is_canonical(const RCP< const Number > &coef, const map_basic_basic &dict) const
Definition: mul.cpp:17
map_basic_basic dict_
The coefficient (e.g. 2 in 2*x*y)
Definition: mul.h:78
T move(T... args)

Member Function Documentation

◆ __eq__()

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

Equality comparator

Parameters
o- Object to be compared with
Returns
whether the 2 objects are equal

Implements SymEngine::Basic.

Definition at line 89 of file mul.cpp.

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

◆ __hash__()

hash_t SymEngine::Mul::__hash__ ( ) const
virtual
Returns
size of the hash

Implements SymEngine::Basic.

Definition at line 78 of file mul.cpp.

79{
80 hash_t seed = SYMENGINE_MUL;
81 hash_combine<Basic>(seed, *coef_);
82 for (const auto &p : dict_) {
83 hash_combine<Basic>(seed, *(p.first));
84 hash_combine<Basic>(seed, *(p.second));
85 }
86 return seed;
87}

◆ accept() [1/2]

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

Implements SymEngine::Basic.

◆ accept() [2/2]

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

Implements SymEngine::Basic.

◆ as_base_exp()

void SymEngine::Mul::as_base_exp ( const RCP< const Basic > &  self,
const Ptr< RCP< const Basic > > &  exp,
const Ptr< RCP< const Basic > > &  base 
)
static

Convert to a base and exponent form.

Definition at line 320 of file mul.cpp.

323{
324 if (is_a_Number(*self)) {
325 // Always ensure it is of form |num| > |den|
326 // in case of Integers den = 1
327 if (is_a<Rational>(*self)) {
328 RCP<const Rational> self_new
329 = rcp_static_cast<const Rational>(self);
330 if (mp_abs(get_num(self_new->as_rational_class()))
331 < mp_abs(get_den(self_new->as_rational_class()))) {
332 *exp = minus_one;
333 *base = self_new->rdiv(*rcp_static_cast<const Number>(one));
334 } else {
335 *exp = one;
336 *base = self;
337 }
338 } else {
339 *exp = one;
340 *base = self;
341 }
342 } else if (is_a<Pow>(*self)) {
343 *exp = down_cast<const Pow &>(*self).get_exp();
344 *base = down_cast<const Pow &>(*self).get_base();
345 } else {
346 SYMENGINE_ASSERT(not is_a<Mul>(*self));
347 *exp = one;
348 *base = self;
349 }
350}
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
Definition: pow.cpp:271

◆ as_two_terms()

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

Rewrite as 2 terms.

Example: if this=3*x**2*y**2*z**2, thena=x**2andb=3*y**2*z**2`

Definition at line 309 of file mul.cpp.

311{
312 // Example: if this=3*x**2*y**2*z**2, then a=x**2 and b=3*y**2*z**2
313 auto p = dict_.begin();
314 *a = pow(p->first, p->second);
315 map_basic_basic d = dict_;
316 d.erase(p->first);
317 *b = Mul::from_dict(coef_, std::move(d));
318}
T begin(T... args)
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
T erase(T... args)
T pow(T... args)

◆ compare()

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

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.

Implements SymEngine::Basic.

Definition at line 98 of file mul.cpp.

99{
100 SYMENGINE_ASSERT(is_a<Mul>(o))
101 const Mul &s = down_cast<const Mul &>(o);
102 // # of elements
103 if (dict_.size() != s.dict_.size())
104 return (dict_.size() < s.dict_.size()) ? -1 : 1;
105
106 // coef
107 int cmp = coef_->__cmp__(*s.coef_);
108 if (cmp != 0)
109 return cmp;
110
111 // Compare dictionaries:
112 return unified_compare(dict_, s.dict_);
113}
Mul(const RCP< const Number > &coef, map_basic_basic &&dict)
Definition: mul.cpp:10
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
T size(T... args)

◆ dict_add_term()

void SymEngine::Mul::dict_add_term ( map_basic_basic d,
const RCP< const Basic > &  exp,
const RCP< const Basic > &  t 
)
static

Add terms to dict.

Definition at line 150 of file mul.cpp.

152{
153 auto it = d.find(t);
154 if (it == d.end()) {
155 insert(d, t, exp);
156 } else {
157 // Very common case, needs to be fast:
158 if (is_a_Number(*it->second) and is_a_Number(*exp)) {
159 RCP<const Number> tmp = rcp_static_cast<const Number>(it->second);
160 iaddnum(outArg(tmp), rcp_static_cast<const Number>(exp));
161 if (tmp->is_zero()) {
162 d.erase(it);
163 } else {
164 it->second = tmp;
165 }
166 } else {
167 // General case:
168 it->second = add(it->second, exp);
169 if (is_number_and_zero(*it->second)) {
170 d.erase(it);
171 }
172 }
173 }
174}
bool is_number_and_zero(const Basic &b)
Definition: number.h:139
void insert(T1 &m, const T2 &first, const T3 &second)
Definition: dict.h:83
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425

◆ dict_add_term_new()

void SymEngine::Mul::dict_add_term_new ( const Ptr< RCP< const Number > > &  coef,
map_basic_basic d,
const RCP< const Basic > &  exp,
const RCP< const Basic > &  t 
)
static

Definition at line 177 of file mul.cpp.

180{
181 auto it = d.find(t);
182 if (it == d.end()) {
183 // Don't check for `exp = 0` here
184 if (is_a<Integer>(*t) or is_a<Rational>(*t) or is_a<Complex>(*t)) {
185 if (is_a<Integer>(*exp)) {
186 imulnum(outArg(*coef),
187 pownum(rcp_static_cast<const Number>(t),
188 rcp_static_cast<const Number>(exp)));
189 } else if (is_a<Rational>(*exp) and not is_a<Complex>(*t)) {
190 RCP<const Basic> res;
191 if (is_a<Integer>(*t)) {
192 res = down_cast<const Rational &>(*exp).rpowrat(
193 down_cast<const Integer &>(*t));
194 } else {
195 res = down_cast<const Rational &>(*t).powrat(
196 down_cast<const Rational &>(*exp));
197 }
198 if (is_a_Number(*res)) {
199 imulnum(outArg(*coef), rcp_static_cast<const Number>(res));
200 } else if (is_a<Mul>(*res)) {
201 RCP<const Mul> m = rcp_static_cast<const Mul>(res);
202 imulnum(outArg(*coef), m->coef_);
203 for (auto &p : m->dict_) {
204 Mul::dict_add_term_new(coef, d, p.second, p.first);
205 }
206 } else {
207 insert(d, t, exp);
208 }
209 } else if (is_a_Number(*exp)
210 and not down_cast<const Number &>(*exp).is_exact()) {
211 imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
212 down_cast<const Number &>(*exp)));
213 } else {
214 insert(d, t, exp);
215 }
216 } else if (is_a_Number(*t) and is_a_Number(*exp)
217 and (not down_cast<const Number &>(*exp).is_exact()
218 or not down_cast<const Number &>(*t).is_exact())) {
219 imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
220 down_cast<const Number &>(*exp)));
221 } else {
222 insert(d, t, exp);
223 }
224 } else {
225 // Very common case, needs to be fast:
226 if (is_a_Number(*exp) and is_a_Number(*it->second)) {
227 RCP<const Number> tmp = rcp_static_cast<const Number>(it->second);
228 iaddnum(outArg(tmp), rcp_static_cast<const Number>(exp));
229 it->second = tmp;
230 } else
231 it->second = add(it->second, exp);
232
233 if (is_a<Integer>(*it->second)) {
234 if (is_a<Integer>(*t) or is_a<Rational>(*t) or is_a<Complex>(*t)) {
235 if (not down_cast<const Integer &>(*(it->second)).is_zero()) {
236 imulnum(outArg(*coef),
237 pownum(rcp_static_cast<const Number>(t),
238 rcp_static_cast<const Number>(it->second)));
239 }
240 d.erase(it);
241 return;
242 } else if (down_cast<const Integer &>(*(it->second)).is_zero()) {
243 d.erase(it);
244 return;
245 }
246 } else if (is_a<Rational>(*it->second)) {
247 if (is_a<Integer>(*t) or is_a<Rational>(*t)) {
248 RCP<const Basic> res;
249 if (is_a<Integer>(*t)) {
250 res = down_cast<const Rational &>(*it->second)
251 .rpowrat(down_cast<const Integer &>(*t));
252 } else {
253 res = down_cast<const Rational &>(*t).powrat(
254 down_cast<const Rational &>(*it->second));
255 }
256 if (is_a_Number(*res)) {
257 d.erase(it);
258 imulnum(outArg(*coef), rcp_static_cast<const Number>(res));
259 return;
260 } else if (is_a<Mul>(*res)) {
261 d.erase(it);
262 RCP<const Mul> m = rcp_static_cast<const Mul>(res);
263 imulnum(outArg(*coef), m->coef_);
264 for (auto &p : m->dict_) {
265 Mul::dict_add_term_new(coef, d, p.second, p.first);
266 }
267 return;
268 }
269 }
270 }
271 if (is_a_Number(*it->second)) {
272 if (down_cast<const Number &>(*it->second).is_zero()) {
273 // In 1*x**0.0, result should be 1.0
274 imulnum(
275 outArg(*coef),
276 pownum(rcp_static_cast<const Number>(it->second), zero));
277 d.erase(it);
278 } else if (is_a<Mul>(*it->first)) {
279 RCP<const Mul> m = rcp_static_cast<const Mul>(it->first);
280 if (is_a<Integer>(*it->second)
281 or (neq(*m->coef_, *one) and neq(*m->coef_, *minus_one))) {
282 RCP<const Number> exp_
283 = rcp_static_cast<const Number>(it->second);
284 d.erase(it);
285 m->power_num(outArg(*coef), d, exp_);
286 }
287 } else if (eq(*it->first, *E)) {
288 RCP<const Number> p = rcp_static_cast<const Number>(it->second);
289 if (not p->is_exact()) {
290 // Evaluate E**0.2, but not E**2
291 RCP<const Basic> exp_ = p->get_eval().exp(*p);
292 if (is_a_Number(*exp_)) {
293 imulnum(outArg(*coef),
294 rcp_static_cast<const Number>(exp_));
295 d.erase(it);
296 }
297 }
298 } else if (is_a_Number(*t)
299 and (not down_cast<const Number &>(*it->second)
300 .is_exact()
301 or not down_cast<const Number &>(*t).is_exact())) {
302 imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
303 down_cast<const Number &>(*exp)));
304 }
305 }
306 }
307}
RCP< const Number > pownum(const RCP< const Number > &self, const RCP< const Number > &other)
Raise self to power other
Definition: number.h:105
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29

◆ from_dict()

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

Create a Mul from a dict.

Definition at line 115 of file mul.cpp.

117{
118 if (coef->is_zero())
119 return coef;
120 if (d.size() == 0) {
121 return coef;
122 } else if (d.size() == 1) {
123 auto p = d.begin();
124 if (is_a<Integer>(*(p->second))) {
125 if (coef->is_one()) {
126 if ((down_cast<const Integer &>(*(p->second))).is_one()) {
127 // For x**1 we simply return "x":
128 return p->first;
129 }
130 } else {
131 // For coef*x or coef*x**3 we simply return Mul:
132 return make_rcp<const Mul>(coef, std::move(d));
133 }
134 }
135 if (coef->is_one()) {
136 // Create a Pow() here:
137 if (eq(*p->second, *one)) {
138 return p->first;
139 }
140 return make_rcp<const Pow>(p->first, p->second);
141 } else {
142 return make_rcp<const Mul>(coef, std::move(d));
143 }
144 } else {
145 return make_rcp<const Mul>(coef, std::move(d));
146 }
147}

◆ get_args()

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

Returns the list of arguments.

Implements SymEngine::Basic.

Definition at line 507 of file mul.cpp.

508{
509 vec_basic args;
510 if (not coef_->is_one()) {
511 args.reserve(dict_.size() + 1);
512 args.push_back(coef_);
513 } else {
514 args.reserve(dict_.size());
515 }
516 for (const auto &p : dict_) {
517 if (eq(*p.second, *one)) {
518 args.push_back(p.first);
519 } else {
520 args.push_back(make_rcp<const Pow>(p.first, p.second));
521 }
522 }
523 return args;
524}
T reserve(T... args)

◆ get_coef()

const RCP< const Number > & SymEngine::Mul::get_coef ( ) const
inline

Definition at line 125 of file mul.h.

126 {
127 return coef_;
128 }

◆ get_dict()

const map_basic_basic & SymEngine::Mul::get_dict ( ) const
inline

Definition at line 129 of file mul.h.

130 {
131 return dict_;
132 }

◆ is_canonical()

bool SymEngine::Mul::is_canonical ( const RCP< const Number > &  coef,
const map_basic_basic dict 
) const
Returns
true if both coef and dict are in canonical form

Definition at line 17 of file mul.cpp.

19{
20 if (coef == null)
21 return false;
22 // e.g. 0*x*y
23 if (coef->is_zero())
24 return false;
25 if (dict.size() == 0)
26 return false;
27 if (dict.size() == 1) {
28 // e.g. 1*x, 1*x**2
29 if (coef->is_one())
30 return false;
31 }
32 // Check that each term in 'dict' is in canonical form
33 for (const auto &p : dict) {
34 if (p.first == null)
35 return false;
36 if (p.second == null)
37 return false;
38 // e.g. 2**3, (2/3)**4
39 // However for Complex no simplification is done
40 if ((is_a<Integer>(*p.first) or is_a<Rational>(*p.first))
41 and is_a<Integer>(*p.second))
42 return false;
43 // e.g. 0**x
44 if (is_a<Integer>(*p.first)
45 and down_cast<const Integer &>(*p.first).is_zero())
46 return false;
47 // e.g. 1**x
48 if (is_a<Integer>(*p.first)
49 and down_cast<const Integer &>(*p.first).is_one())
50 return false;
51 // e.g. x**0
52 if (is_a_Number(*p.second)
53 and down_cast<const Number &>(*p.second).is_zero())
54 return false;
55 // e.g. (x*y)**2 (={xy:2}), which should be represented as x**2*y**2
56 // (={x:2, y:2})
57 if (is_a<Mul>(*p.first)) {
58 if (is_a<Integer>(*p.second))
59 return false;
60 if (is_a_Number(*p.second)
61 and neq(*down_cast<const Mul &>(*p.first).coef_, *one)
62 and neq(*down_cast<const Mul &>(*p.first).coef_, *minus_one))
63 return false;
64 }
65 // e.g. x**2**y (={x**2:y}), which should be represented as x**(2y)
66 // (={x:2y})
67 if (is_a<Pow>(*p.first) && is_a<Integer>(*p.second))
68 return false;
69 // e.g. 0.5^2.0 should be represented as 0.25
70 if (is_a_Number(*p.first) and is_a_Number(*p.second)
71 and (not down_cast<const Number &>(*p.first).is_exact()
72 or not down_cast<const Number &>(*p.second).is_exact()))
73 return false;
74 }
75 return true;
76}

◆ power_num()

void SymEngine::Mul::power_num ( const Ptr< RCP< const Number > > &  coef,
map_basic_basic d,
const RCP< const Number > &  exp 
) const

Power all terms with the exponent exp

Definition at line 448 of file mul.cpp.

450{
451 if (exp->is_zero()) {
452 // (x*y)**(0.0) should return 1.0
453 imulnum(coef, pownum(rcp_static_cast<const Number>(exp), zero));
454 return;
455 }
456 RCP<const Basic> new_coef;
457 RCP<const Basic> new_exp;
458 if (is_a<Integer>(*exp)) {
459 // For eg. (3*y*(x**(1/2))**2 should be expanded to 9*x*y**2
460 new_coef = pow(coef_, exp);
461 for (const auto &p : dict_) {
462 new_exp = mul(p.second, exp);
463 if (is_a<Integer>(*new_exp) and is_a<Mul>(*p.first)) {
464 down_cast<const Mul &>(*p.first).power_num(
465 coef, d, rcp_static_cast<const Number>(new_exp));
466 } else {
467 // No need for additional dict checks here.
468 // The dict should be of standard form before this is
469 // called.
470 Mul::dict_add_term_new(coef, d, new_exp, p.first);
471 }
472 }
473 } else {
474 if (coef_->is_negative() and not coef_->is_minus_one()) {
475 // (-3*x*y)**(1/2) -> 3**(1/2)*(-x*y)**(1/2)
476 new_coef = pow(coef_->mul(*minus_one), exp);
477 map_basic_basic d1 = dict_;
478 Mul::dict_add_term_new(coef, d, exp,
479 Mul::from_dict(minus_one, std::move(d1)));
480 } else if (coef_->is_positive() and not coef_->is_one()) {
481 // (3*x*y)**(1/2) -> 3**(1/2)*(x*y)**(1/2)
482 new_coef = pow(coef_, exp);
483 map_basic_basic d1 = dict_;
484 Mul::dict_add_term_new(coef, d, exp,
485 Mul::from_dict(one, std::move(d1)));
486 } else {
487 // ((1+2*I)*x*y)**(1/2) is kept as it is
488 new_coef = one;
489 Mul::dict_add_term_new(coef, d, exp, this->rcp_from_this());
490 }
491 }
492 if (is_a_Number(*new_coef)) {
493 imulnum(coef, rcp_static_cast<const Number>(new_coef));
494 } else if (is_a<Mul>(*new_coef)) {
495 RCP<const Mul> tmp = rcp_static_cast<const Mul>(new_coef);
496 imulnum(coef, tmp->coef_);
497 for (const auto &q : tmp->dict_) {
498 Mul::dict_add_term_new(coef, d, q.second, q.first);
499 }
500 } else {
501 RCP<const Basic> _exp, t;
502 Mul::as_base_exp(new_coef, outArg(_exp), outArg(t));
503 Mul::dict_add_term_new(coef, d, _exp, t);
504 }
505}
RCP< Basic > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
static void as_base_exp(const RCP< const Basic > &self, const Ptr< RCP< const Basic > > &exp, const Ptr< RCP< const Basic > > &base)
Convert to a base and exponent form.
Definition: mul.cpp:320
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition: mul.cpp:352

Field Documentation

◆ coef_

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

Definition at line 76 of file mul.h.

◆ dict_

map_basic_basic SymEngine::Mul::dict_
private

The coefficient (e.g. 2 in 2*x*y)

Definition at line 78 of file mul.h.

◆ type_code_id

const TypeID SymEngine::Mul::type_code_id = SYMENGINE_MUL
static

the dictionary of the rest (e.g. x*y in 2*x*y)

Type_code_id shared by all instances

Definition at line 81 of file mul.h.


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