1 #ifndef SYMENGINE_SERIES_VISITOR_H
2 #define SYMENGINE_SERIES_VISITOR_H
9 template <
typename Poly,
typename Coeff,
typename Series>
21 : var(var_), varname(varname_), prec(prec_)
24 RCP<const Series> series(
const RCP<const Basic> &x)
26 return make_rcp<Series>(apply(x), varname, prec);
29 Poly apply(
const RCP<const Basic> &x)
36 void bvisit(
const Add &x)
39 for (
const auto &term : x.get_dict()) {
40 temp += apply(term.first) * apply(term.second);
44 void bvisit(
const Mul &x)
46 Poly temp(apply(x.get_coef()));
47 for (
const auto &term : x.get_dict()) {
48 temp = Series::mul(temp, apply(pow(term.first, term.second)), prec);
52 void bvisit(
const Pow &x)
55 if (is_a<Integer>(*
exp)) {
56 const Integer &ii = (down_cast<const Integer &>(*
exp));
58 throw SymEngineException(
"series power exponent size");
64 p = Series::pow(p, sh, prec);
65 }
else if (sh == -1) {
66 p = Series::series_invert(p, var, prec);
71 p = Series::pow(Series::series_invert(p, var, prec), -sh, prec);
74 }
else if (is_a<Rational>(*
exp)) {
75 const Rational &rat = (down_cast<const Rational &>(*
exp));
78 if (not mp_fits_slong_p(expnumz) or not mp_fits_slong_p(expdenz))
79 throw SymEngineException(
"series rational power exponent size");
80 const int num = numeric_cast<int>(mp_get_si(expnumz));
81 const int den = numeric_cast<int>(mp_get_si(expdenz));
84 Series::series_nthroot(apply(base), den, var, prec));
88 p = Series::pow(proot, num, prec);
89 }
else if (num == -1) {
90 p = Series::series_invert(proot, var, prec);
92 p = Series::series_invert(Series::pow(proot, -num, prec), var,
95 }
else if (
eq(*E, *base)) {
96 p = Series::series_exp(apply(
exp), var, prec);
98 p = Series::series_exp(
99 Poly(apply(
exp) * Series::series_log(apply(base), var, prec)),
107 RCP<const Symbol> s =
symbol(varname);
110 RCP<const Basic> const_term = d->subs(m);
111 if (const_term == d) {
112 p = Series::convert(*d);
115 Poly res_p(apply(
expand(const_term)));
119 for (
unsigned int i = 1; i < prec; i++) {
124 res_p += Series::pow(var, i, prec)
125 * (prod * apply(
expand(d->subs(m))));
130 void bvisit(
const Gamma &x)
132 RCP<const Symbol> s =
symbol(varname);
133 RCP<const Basic> arg = x.
get_args()[0];
134 if (
eq(*arg->subs({{s, zero}}), *zero)) {
135 RCP<const Basic> g =
gamma(
add(arg, one));
136 if (is_a<Gamma>(*g)) {
137 bvisit(down_cast<const Function &>(*g));
138 p *= Series::pow(var, -1, prec);
143 bvisit(implicit_cast<const Function &>(x));
147 void bvisit(
const Series &x)
149 if (x.get_var() != varname) {
150 throw NotImplementedError(
"Multivariate Series not implemented");
152 if (x.get_degree() < prec) {
153 throw SymEngineException(
"Series with lesser prec found");
157 void bvisit(
const Integer &x)
159 p = Series::convert(x);
161 void bvisit(
const Rational &x)
163 p = Series::convert(x);
165 void bvisit(
const Complex &x)
167 p = Series::convert(x);
169 void bvisit(
const RealDouble &x)
171 p = Series::convert(x);
173 void bvisit(
const ComplexDouble &x)
175 p = Series::convert(x);
177 #ifdef HAVE_SYMENGINE_MPFR
178 void bvisit(
const RealMPFR &x)
180 p = Series::convert(x);
183 #ifdef HAVE_SYMENGINE_MPC
184 void bvisit(
const ComplexMPC &x)
186 p = Series::convert(x);
189 void bvisit(
const Sin &x)
191 x.get_arg()->accept(*
this);
192 p = Series::series_sin(p, var, prec);
194 void bvisit(
const Cos &x)
196 x.get_arg()->accept(*
this);
197 p = Series::series_cos(p, var, prec);
199 void bvisit(
const Tan &x)
201 x.get_arg()->accept(*
this);
202 p = Series::series_tan(p, var, prec);
204 void bvisit(
const Cot &x)
206 x.get_arg()->accept(*
this);
207 p = Series::series_cot(p, var, prec);
209 void bvisit(
const Csc &x)
211 x.get_arg()->accept(*
this);
212 p = Series::series_csc(p, var, prec);
214 void bvisit(
const Sec &x)
216 x.get_arg()->accept(*
this);
217 p = Series::series_sec(p, var, prec);
219 void bvisit(
const Log &x)
221 x.get_arg()->accept(*
this);
222 p = Series::series_log(p, var, prec);
224 void bvisit(
const ASin &x)
226 x.get_arg()->accept(*
this);
227 p = Series::series_asin(p, var, prec);
229 void bvisit(
const ACos &x)
231 x.get_arg()->accept(*
this);
232 p = Series::series_acos(p, var, prec);
234 void bvisit(
const ATan &x)
236 x.get_arg()->accept(*
this);
237 p = Series::series_atan(p, var, prec);
239 void bvisit(
const Sinh &x)
241 x.get_arg()->accept(*
this);
242 p = Series::series_sinh(p, var, prec);
244 void bvisit(
const Cosh &x)
246 x.get_arg()->accept(*
this);
247 p = Series::series_cosh(p, var, prec);
249 void bvisit(
const Tanh &x)
251 x.get_arg()->accept(*
this);
252 p = Series::series_tanh(p, var, prec);
254 void bvisit(
const ASinh &x)
256 x.get_arg()->accept(*
this);
257 p = Series::series_asinh(p, var, prec);
259 void bvisit(
const ATanh &x)
261 x.get_arg()->accept(*
this);
262 p = Series::series_atanh(p, var, prec);
264 void bvisit(
const LambertW &x)
266 x.get_arg()->accept(*
this);
267 p = Series::series_lambertw(p, var, prec);
269 void bvisit(
const Symbol &x)
271 if (x.get_name() == varname) {
272 p = Series::var(x.get_name());
274 p = Series::convert(x);
277 void bvisit(
const Constant &x)
279 p = Series::convert(x);
281 void bvisit(
const Basic &x)
283 if (!has_symbol(x, *
symbol(varname))) {
284 p = Series::convert(x);
286 throw NotImplementedError(
"Not Implemented");
292 :
public BaseVisitor<NeedsSymbolicExpansionVisitor, StopVisitor>
295 RCP<const Symbol> x_;
299 template <
typename T,
301 = enable_if_t<std::is_base_of<TrigBase, T>::value
303 void bvisit(
const T &f)
305 auto arg = f.get_arg();
307 if (arg->subs(subsx0)->__neq__(*
integer(0))) {
313 void bvisit(
const Pow &pow)
315 auto base = pow.get_base();
316 auto exp = pow.get_exp();
319 if ((base->__eq__(*E) and exp->subs(subsx0)->__neq__(*
integer(0)))
321 and down_cast<const Number &>(*exp).is_negative()
322 and base->subs(subsx0)->__eq__(*
integer(0)))) {
328 void bvisit(
const Log &f)
332 if (arg->subs(subsx0)->__eq__(*
integer(0))) {
344 void bvisit(
const Basic &x) {}
346 bool apply(
const Basic &b,
const RCP<const Symbol> &x)
351 postorder_traversal_stop(b, *
this);
The base class for representing addition in symbolic expressions.
const RCP< const Number > & get_coef() const
The lowest unit of symbolic representation.
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
const integer_class & as_integer_class() const
Convert to integer_class.
vec_basic get_args() const override
Returns the list of arguments.
RCP< const Basic > get_arg() const
RCP< const Basic > get_exp() const
RCP< const Basic > get_base() const
const rational_class & as_rational_class() const
Convert to rational_class.
Main namespace for SymEngine package.
bool is_a_Number(const Basic &b)
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > gamma(const RCP< const Basic > &arg)
Canonicalize Gamma:
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
RCP< const Basic > expand(const RCP< const Basic > &self, bool deep=true)
Expands self