Program Listing for File as_real_imag.cpp¶
↰ Return to documentation for file (symengine/symengine/as_real_imag.cpp
)
#include <symengine/visitor.h>
#include <symengine/basic.h>
namespace SymEngine
{
class RealImagVisitor : public BaseVisitor<RealImagVisitor>
{
private:
Ptr<RCP<const Basic>> real_, imag_;
public:
RealImagVisitor(const Ptr<RCP<const Basic>> &real,
const Ptr<RCP<const Basic>> &imag)
: real_{real}, imag_{imag}
{
}
void apply(const Basic &b)
{
b.accept(*this);
}
void bvisit(const Mul &x)
{
RCP<const Basic> rest = one;
RCP<const Basic> fre_ = one, fim_ = zero;
for (const auto &arg : x.get_args()) {
apply(*arg);
std::tie(fre_, fim_)
= std::make_tuple(sub(mul(fre_, *real_), mul(fim_, *imag_)),
add(mul(fre_, *imag_), mul(fim_, *real_)));
}
*real_ = fre_;
*imag_ = fim_;
}
void bvisit(const Add &x)
{
RCP<const Basic> t;
umap_basic_num dr, dim;
RCP<const Number> coefr = zero, coefim = zero, coef;
for (const auto &arg : x.get_args()) {
apply(*arg);
if (is_a_Number(**real_)) {
iaddnum(outArg(coefr), rcp_static_cast<const Number>(*real_));
} else {
Add::as_coef_term(*real_, outArg(coef), outArg(t));
Add::dict_add_term(dr, coef, t);
}
if (is_a_Number(**imag_)) {
iaddnum(outArg(coefim), rcp_static_cast<const Number>(*imag_));
} else {
Add::as_coef_term(*imag_, outArg(coef), outArg(t));
Add::dict_add_term(dim, coef, t);
}
}
*real_ = Add::from_dict(coefr, std::move(dr));
*imag_ = Add::from_dict(coefim, std::move(dim));
}
void bvisit(const Pow &x)
{
RCP<const Basic> exp_;
exp_ = x.get_exp();
apply(*x.get_base());
if (eq(**imag_, *zero)) {
*real_ = x.rcp_from_this();
*imag_ = zero;
return;
}
if (is_a<Integer>(*exp_)) {
RCP<const Basic> expx;
if (eq(*Gt(exp_, zero), *boolTrue)) {
expx = expand(x.rcp_from_this());
} else {
auto magn = add(mul(*real_, *real_), mul(*imag_, *imag_));
*real_ = div(*real_, magn);
*imag_ = div(neg(*imag_), magn);
expx = expand(pow(add(*real_, mul(*imag_, I)), neg(exp_)));
}
if (eq(*expx, x))
throw SymEngineException("Not Implemented");
apply(*expx);
} else if (is_a<Rational>(*exp_)) {
auto magn = sqrt(add(mul(*real_, *real_), mul(*imag_, *imag_)));
auto ang = atan2(*imag_, *real_);
magn = pow(magn, exp_);
ang = mul(ang, exp_);
*real_ = mul(magn, cos(ang));
*imag_ = mul(magn, sin(ang));
} else {
throw SymEngineException("Not Implemented");
}
}
void bvisit(const ComplexBase &x)
{
*real_ = x.real_part();
*imag_ = x.imaginary_part();
}
void bvisit(const Infty &x)
{
if (eq(x, *ComplexInf)) {
*real_ = Nan;
*imag_ = Nan;
} else {
*real_ = x.rcp_from_this();
*imag_ = zero;
}
}
void bvisit(const Sin &x)
{
apply(*x.get_arg());
std::tie(*real_, *imag_) = std::make_tuple(
mul(sin(*real_), cosh(*imag_)), mul(sinh(*imag_), cos(*real_)));
}
void bvisit(const Cos &x)
{
apply(*x.get_arg());
std::tie(*real_, *imag_)
= std::make_tuple(mul(cos(*real_), cosh(*imag_)),
neg(mul(sinh(*imag_), sin(*real_))));
}
void bvisit(const Tan &x)
{
apply(*x.get_arg());
if (eq(**imag_, *zero)) {
*real_ = x.rcp_from_this();
*imag_ = zero;
return;
}
auto i2 = integer(2);
auto twice_real_ = mul(i2, *real_), twice_imag_ = mul(i2, *imag_);
auto den = add(cos(twice_real_), cosh(twice_imag_));
*real_ = div(sin(twice_real_), den);
*imag_ = div(sinh(twice_imag_), den);
}
void bvisit(const Csc &x)
{
apply(*div(one, sin(x.get_arg())));
}
void bvisit(const Sec &x)
{
apply(*div(one, cos(x.get_arg())));
}
void bvisit(const Cot &x)
{
apply(*x.get_arg());
if (eq(**imag_, *zero)) {
*real_ = x.rcp_from_this();
return;
}
auto i2 = integer(2);
auto twice_real_ = mul(i2, *real_), twice_imag_ = mul(i2, *imag_);
auto den = sub(cos(twice_real_), cosh(twice_imag_));
*real_ = neg(div(sin(twice_real_), den));
*imag_ = neg(div(sinh(twice_imag_), den));
}
void bvisit(const Sinh &x)
{
apply(*x.get_arg());
std::tie(*real_, *imag_) = std::make_tuple(
mul(sinh(*real_), cos(*imag_)), mul(sin(*imag_), cosh(*real_)));
}
void bvisit(const Cosh &x)
{
apply(*x.get_arg());
std::tie(*real_, *imag_) = std::make_tuple(
mul(cosh(*real_), cos(*imag_)), mul(sin(*imag_), sinh(*real_)));
}
void bvisit(const Tanh &x)
{
apply(*x.get_arg());
if (eq(**imag_, *zero)) {
*real_ = x.rcp_from_this();
return;
}
auto i2 = integer(2);
auto sinh_re = sinh(*real_), cos_im = cos(*imag_);
auto den = add(pow(sinh_re, i2), pow(cos_im, i2));
*real_ = div(mul(sinh_re, cosh(*real_)), den);
*imag_ = div(mul(sin(*imag_), cos_im), den);
}
void bvisit(const Csch &x)
{
apply(*div(one, sinh(x.get_arg())));
}
void bvisit(const Sech &x)
{
apply(*div(one, cosh(x.get_arg())));
}
void bvisit(const Coth &x)
{
apply(*x.get_arg());
if (eq(**imag_, *zero)) {
*real_ = x.rcp_from_this();
return;
}
auto i2 = integer(2);
auto sinh_re = sinh(*real_), sin_im = sin(*imag_);
auto den = add(pow(sinh_re, i2), pow(sin_im, i2));
*real_ = div(mul(sinh_re, cosh(*real_)), den);
*imag_ = neg(div(mul(sin_im, cos(*imag_)), den));
}
void bvisit(const Abs &x)
{
*real_ = x.rcp_from_this();
*imag_ = zero;
}
void bvisit(const Function &x)
{
throw SymEngineException(
"Not Implemented classes for real and imaginary parts");
}
void bvisit(const Symbol &x)
{
throw SymEngineException(
"Not Implemented classes for real and imaginary parts");
}
void bvisit(const Basic &x)
{
*real_ = x.rcp_from_this();
*imag_ = zero;
}
};
void as_real_imag(const RCP<const Basic> &x, const Ptr<RCP<const Basic>> &real,
const Ptr<RCP<const Basic>> &imag)
{
RealImagVisitor v(real, imag);
v.apply(*x);
}
} // SymEngine