8000 Fix Mul canonical to match that of Pow canonical by bocklund · Pull Request #1900 · symengine/symengine · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix Mul canonical to match that of Pow canonical #1900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
8000
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 21 additions & 27 deletions symengine/mul.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ bool Mul::is_canonical(const RCP<const Number> &coef,
if (is_a<Pow>(*p.first) && is_a<Integer>(*p.second))
return false;
// e.g. 0.5^2.0 should be represented as 0.25
if (is_a_Number(*p.first)
and not down_cast<const Number &>(*p.first).is_exact()
and is_a_Number(*p.second)
and not down_cast<const Number &>(*p.second).is_exact())
if (is_a_Number(*p.first) and is_a_Number(*p.second)
and (not down_cast<const Number &>(*p.first).is_exact()
or not down_cast<const Number &>(*p.second).is_exact()))
return false;
}
return true;
Expand Down Expand Up @@ -182,13 +181,12 @@ void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef,
auto it = d.find(t);
if (it == d.end()) {
// Don't check for `exp = 0` here
// `pow` for Complex is not expanded by default
if (is_a<Integer>(*t) or is_a<Rational>(*t)) {
if (is_a<Integer>(*t) or is_a<Rational>(*t) or is_a<Complex>(*t)) {
if (is_a<Integer>(*exp)) {
imulnum(outArg(*coef),
pownum(rcp_static_cast<const Number>(t),
rcp_static_cast<const Number>(exp)));
} else if (is_a<Rational>(*exp)) {
} else if (is_a<Rational>(*exp) and not is_a<Complex>(*t)) {
RCP<const Basic> res;
if (is_a<Integer>(*t)) {
res = down_cast<const Rational &>(*exp).rpowrat(
Expand All @@ -208,17 +206,18 @@ void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef,
} else {
insert(d, t, exp);
}
} else if (is_a_Number(*exp)
and not down_cast<const Number &>(*exp).is_exact()) {
imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
down_cast<const Number &>(*exp)));
} else {
insert(d, t, exp);
}
} else if (is_a<Integer>(*exp) and is_a<Complex>(*t)) {
if (down_cast<const Integer &>(*exp).is_one()) {
imulnum(outArg(*coef), rcp_static_cast<const Number>(t));
} else if (down_cast<const Integer &>(*exp).is_minus_one()) {
idivnum(outArg(*coef), rcp_static_cast<const Number>(t));
} else {
insert(d, t, exp);
}
} else if (is_a_Number(*t) and is_a_Number(*exp)
and (not down_cast<const Number &>(*exp).is_exact()
or not down_cast<const Number &>(*t).is_exact())) {
imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
down_cast<const Number &>(*exp)));
} else {
insert(d, t, exp);
}
Expand All @@ -232,8 +231,7 @@ void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef,
it->second = add(it->second, exp);

if (is_a<Integer>(*it->second)) {
// `pow` for Complex is not expanded by default
if (is_a<Integer>(*t) or is_a<Rational>(*t)) {
if (is_a<Integer>(*t) or is_a<Rational>(*t) or is_a<Complex>(*t)) {
if (not down_cast<const Integer &>(*(it->second)).is_zero()) {
imulnum(outArg(*coef),
pownum(rcp_static_cast<const Number>(t),
Expand All @@ -244,16 +242,6 @@ void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef,
} else if (down_cast<const Integer &>(*(it->second)).is_zero()) {
d.erase(it);
return;
} else if (is_a<Complex>(*t)) {
if (down_cast<const Integer &>(*(it->second)).is_one()) {
imulnum(outArg(*coef), rcp_static_cast<const Number>(t));
d.erase(it);
} else if (down_cast<const Integer &>(*(it->second))
.is_minus_one()) {
idivnum(outArg(*coef), rcp_static_cast<const Number>(t));
d.erase(it);
}
return;
}
} else if (is_a<Rational>(*it->second)) {
if (is_a<Integer>(*t) or is_a<Rational>(*t)) {
Expand Down Expand Up @@ -307,6 +295,12 @@ void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef,
d.erase(it);
}
}
} else if (is_a_Number(*t)
and (not down_cast<const Number &>(*it->second)
.is_exact()
or not down_cast<const Number &>(*t).is_exact())) {
imulnum(outArg(*coef), down_cast<const Number &>(*t).pow(
down_cast<const Number &>(*exp)));
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions symengine/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ bool Pow::is_canonical(const Basic &base, const Basic &exp) const
and is_a<Integer>(exp))
return false;
// e.g. 0.5^2.0 should be represented as 0.25
if (is_a_Number(base) and not down_cast<const Number &>(base).is_exact()
and is_a_Number(exp) and not down_cast<const Number &>(exp).is_exact())
if (is_a_Number(base) and is_a_Number(exp)
and (not down_cast<const Number &>(base).is_exact()
or not down_cast<const Number &>(exp).is_exact()))
return false;
return true;
}
Expand Down
8 changes: 8 additions & 0 deletions symengine/tests/basic/test_subs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ TEST_CASE("Mul: subs", "[subs]")
r1 = div(sin(x), x);
d[x] = zero;
REQUIRE(eq(*r1->subs(d), *Nan));

d.clear();
r1 = mul(real_double(2.0), x);
// xreplace with an empty mapping dict should be a no-op
r2 = r1->xreplace(d);
std::cout << "r1: " << *r1 << std::endl;
std::cout << "r2: " << *r2 << std::endl;
REQUIRE(eq(*r1, *r2));
}

TEST_CASE("Pow: subs", "[subs]")
Expand Down
4 changes: 2 additions & 2 deletions symengine/utilities/matchpycpp/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ dependencies:
- python 3.7.*
- pip
- pip:
- git+git://github.com/sympy/sympy.git@a22a512c#egg=sympy
- git+git://github.com/HPAC/matchpy.git@e17ba426f1a8cbb1aa6ca2080469445ce588e879#egg=matchpy
- git+https://github.com/sympy/sympy.git@a22a512c#egg=sympy
- git+https://github.com/HPAC/matchpy.git@e17ba426f1a8cbb1aa6ca2080469445ce588e879#egg=matchpy

0