2#include <symengine/subs.h>
3#include <symengine/symengine_casts.h>
9extern RCP<const Basic> i2;
16 RCP<const Basic> diff = zero;
20 vec_basic v =
self.get_args();
21 vec_basic
vdiff(v.size());
24 for (
unsigned i = 0; i < v.size(); i++) {
35 for (
unsigned i = 0; i < v.size(); i++) {
42 if (count == 1
and eq(*v[i], *x)) {
43 return Derivative::create(
self.rcp_from_this(), {x});
61static bool fdiff(
const Ptr<RCP<const Basic>> &
ret,
const Zeta &
self,
73static bool fdiff(
const Ptr<RCP<const Basic>> &
ret,
const UpperGamma &
self,
86static bool fdiff(
const Ptr<RCP<const Basic>> &
ret,
const LowerGamma &
self,
98static bool fdiff(
const Ptr<RCP<const Basic>> &
ret,
const PolyGamma &
self,
109static bool fdiff(
const Ptr<RCP<const Basic>> &
ret,
const Function &
self,
117static inline RCP<const Basic> diff_upolyflint(
const P &
self,
const Symbol &x)
119 if (
self.get_var()->__eq__(x)) {
120 return P::from_container(
self.get_var(),
self.get_poly().derivative());
122 return P::from_dict(
self.get_var(), {{}});
126template <
typename Poly,
typename Dict>
127static inline RCP<const Basic> diff_upoly(
const Poly &self,
const Symbol &x)
129 if (self.get_var()->__eq__(x)) {
131 for (
auto it = self.begin(); it != self.end(); ++it) {
133 d[it->first - 1] = it->second * it->first;
135 return Poly::from_dict(self.get_var(),
std::move(d));
137 return Poly::from_dict(self.get_var(), {{}});
141template <
typename Container,
typename Poly>
142static RCP<const Basic> diff_mpoly(
const MSymEnginePoly<Container, Poly> &self,
143 const RCP<const Symbol> &x)
145 using Dict =
typename Container::dict_type;
146 using Vec =
typename Container::vec_type;
149 if (self.get_vars().find(x) != self.get_vars().end()) {
150 auto i = self.get_vars().begin();
151 unsigned int index = 0;
152 while (!(*i)->__eq__(*x)) {
156 for (
auto bucket : self.get_poly().dict_) {
157 if (bucket.first[index] != 0) {
158 Vec v = bucket.first;
160 dict.insert({v, bucket.second * bucket.first[index]});
164 v.
insert(v.begin(), self.get_vars().begin(), self.get_vars().end());
165 return Poly::from_dict(v,
std::move(dict));
168 vs.
insert(vs.begin(), self.get_vars().begin(), self.get_vars().end());
169 return Poly::from_dict(vs, {{}});
175void DiffVisitor::bvisit(
const Basic &self)
177 result_ = Derivative::create(self.rcp_from_this(), {x});
186#define DIFF0(CLASS) \
187 void DiffVisitor::bvisit(const CLASS &self) \
189 result_ = Derivative::create(self.rcp_from_this(), {x}); \
192DIFF0(UnivariateSeries)
197void DiffVisitor::bvisit(
const Number &self)
202void DiffVisitor::bvisit(
const Constant &self)
207void DiffVisitor::bvisit(
const Symbol &self)
209 if (x->get_name() == self.get_name()) {
216void DiffVisitor::bvisit(
const Log &self)
218 apply(self.get_arg());
219 result_ =
mul(
div(one, self.get_arg()), result_);
222void DiffVisitor::bvisit(
const Abs &self)
224 apply(self.get_arg());
225 if (
eq(*result_, *zero)) {
228 result_ = Derivative::create(self.rcp_from_this(), {x});
232void DiffVisitor::bvisit(
const Zeta &self)
234 result_ = fdiff(self, x, *
this);
237void DiffVisitor::bvisit(
const LowerGamma &self)
239 result_ = fdiff(self, x, *
this);
241void DiffVisitor::bvisit(
const UpperGamma &self)
243 result_ = fdiff(self, x, *
this);
245void DiffVisitor::bvisit(
const PolyGamma &self)
247 result_ = fdiff(self, x, *
this);
249void DiffVisitor::bvisit(
const UnevaluatedExpr &self)
251 result_ = Derivative::create(self.rcp_from_this(), {x});
253void DiffVisitor::bvisit(
const TwoArgFunction &self)
255 result_ = fdiff(self, x, *
this);
258void DiffVisitor::bvisit(
const ASech &self)
260 apply(self.get_arg());
266void DiffVisitor::bvisit(
const ACoth &self)
268 apply(self.get_arg());
269 result_ =
mul(
div(one,
sub(one,
pow(self.get_arg(), i2))), result_);
272void DiffVisitor::bvisit(
const ATanh &self)
274 apply(self.get_arg());
275 result_ =
mul(
div(one,
sub(one,
pow(self.get_arg(), i2))), result_);
278void DiffVisitor::bvisit(
const ACosh &self)
280 apply(self.get_arg());
284void DiffVisitor::bvisit(
const ACsch &self)
286 apply(self.get_arg());
289 pow(self.get_arg(), i2))),
293void DiffVisitor::bvisit(
const ASinh &self)
295 apply(self.get_arg());
299void DiffVisitor::bvisit(
const Coth &self)
301 apply(self.get_arg());
302 result_ =
mul(
div(minus_one,
pow(
sinh(self.get_arg()), i2)), result_);
305void DiffVisitor::bvisit(
const Tanh &self)
307 apply(self.get_arg());
308 result_ =
mul(
sub(one,
pow(
tanh(self.get_arg()), i2)), result_);
311void DiffVisitor::bvisit(
const Sech &self)
313 apply(self.get_arg());
319void DiffVisitor::bvisit(
const Cosh &self)
321 apply(self.get_arg());
322 result_ =
mul(
sinh(self.get_arg()), result_);
325void DiffVisitor::bvisit(
const Csch &self)
327 apply(self.get_arg());
333void DiffVisitor::bvisit(
const Sinh &self)
335 apply(self.get_arg());
336 result_ =
mul(
cosh(self.get_arg()), result_);
339void DiffVisitor::bvisit(
const Subs &self)
341 RCP<const Basic> d = zero, t;
342 if (self.get_dict().count(x) == 0) {
343 apply(self.get_arg());
344 d = result_->subs(self.get_dict());
346 for (
const auto &p : self.get_dict()) {
349 if (
neq(*t, *zero)) {
350 if (is_a<Symbol>(*p.first)) {
351 d =
add(d,
mul(t, diff(self.get_arg(),
352 rcp_static_cast<const Symbol>(p.first))
353 ->subs(self.get_dict())));
355 result_ = Derivative::create(self.rcp_from_this(), {x});
363void DiffVisitor::bvisit(
const Derivative &self)
365 apply(self.get_arg());
366 RCP<const Basic> ret = result_;
367 if (
eq(*ret, *zero)) {
370 multiset_basic t = self.get_symbols();
376 result_ = Derivative::create(self.get_arg(), t);
381 if (is_a<Derivative>(*ret)
382 &&
eq(*down_cast<const Derivative &>(*ret).get_arg(),
385 result_ = Derivative::create(self.get_arg(), t);
389 ret = diff(ret, rcp_static_cast<const Symbol>(p));
394static inline RCP<const Symbol> get_dummy(
const Basic &b,
std::string name)
400 }
while (has_symbol(b, *s));
404void DiffVisitor::bvisit(
const OneArgFunction &self)
406 result_ = fdiff(self, x, *
this);
409void DiffVisitor::bvisit(
const MultiArgFunction &self)
411 result_ = fdiff(self, x, *
this);
414void DiffVisitor::bvisit(
const LambertW &self)
418 apply(self.get_arg());
419 RCP<const Basic> lambertw_val =
lambertw(self.get_arg());
421 =
mul(
div(lambertw_val,
mul(self.get_arg(),
add(lambertw_val, one))),
425void DiffVisitor::bvisit(
const Add &self)
428 RCP<const Number> coef = zero, coef2;
430 for (
auto &p : self.get_dict()) {
432 RCP<const Basic> term = result_;
433 if (is_a<Integer>(*term)
434 && down_cast<const Integer &>(*term).is_zero()) {
436 }
else if (is_a_Number(*term)) {
437 iaddnum(outArg(coef),
438 mulnum(p.second, rcp_static_cast<const Number>(term)));
439 }
else if (is_a<Add>(*term)) {
440 for (
auto &q : (down_cast<const Add &>(*term)).get_dict())
441 Add::dict_add_term(d,
mulnum(q.second, p.second), q.first);
442 iaddnum(outArg(coef),
443 mulnum(p.second, down_cast<const Add &>(*term).get_coef()));
445 Add::as_coef_term(
mul(p.second, term), outArg(coef2), outArg(t));
446 Add::dict_add_term(d, coef2, t);
449 result_ = Add::from_dict(coef,
std::move(d));
452void DiffVisitor::bvisit(
const Mul &self)
454 RCP<const Number> overall_coef = zero;
455 umap_basic_num add_dict;
456 for (
auto &p : self.get_dict()) {
457 RCP<const Number> coef = self.get_coef();
458 apply(
pow(p.first, p.second));
459 RCP<const Basic>
factor = result_;
460 if (is_a<Integer>(*factor)
461 && down_cast<const Integer &>(*factor).is_zero())
463 map_basic_basic d = self.get_dict();
465 if (is_a_Number(*factor)) {
466 imulnum(outArg(coef), rcp_static_cast<const Number>(factor));
467 }
else if (is_a<Mul>(*factor)) {
468 RCP<const Mul> tmp = rcp_static_cast<const Mul>(factor);
469 imulnum(outArg(coef), tmp->get_coef());
470 for (
auto &q : tmp->get_dict()) {
471 Mul::dict_add_term_new(outArg(coef), d, q.second, q.first);
474 RCP<const Basic>
exp, t;
475 Mul::as_base_exp(factor, outArg(exp), outArg(t));
476 Mul::dict_add_term_new(outArg(coef), d, exp, t);
479 iaddnum(outArg(overall_coef), coef);
481 RCP<const Basic>
mul = Mul::from_dict(one,
std::move(d));
482 Add::coef_dict_add_term(outArg(overall_coef), add_dict, coef, mul);
485 result_ = Add::from_dict(overall_coef,
std::move(add_dict));
488void DiffVisitor::bvisit(
const Pow &self)
490 if (is_a_Number(*(self.get_exp()))) {
491 apply(self.get_base());
493 mul(self.get_exp(),
pow(self.get_base(),
sub(self.get_exp(), one))),
496 apply(
mul(self.get_exp(),
log(self.get_base())));
497 result_ =
mul(self.rcp_from_this(), result_);
501void DiffVisitor::bvisit(
const Sin &self)
503 apply(self.get_arg());
504 result_ =
mul(
cos(self.get_arg()), result_);
507void DiffVisitor::bvisit(
const Cos &self)
509 apply(self.get_arg());
510 result_ =
mul(
mul(minus_one,
sin(self.get_arg())), result_);
513void DiffVisitor::bvisit(
const Tan &self)
515 apply(self.get_arg());
516 RCP<const Integer> two =
integer(2);
517 result_ =
mul(
add(one,
pow(
tan(self.get_arg()), two)), result_);
520void DiffVisitor::bvisit(
const Cot &self)
522 apply(self.get_arg());
523 RCP<const Integer> two =
integer(2);
525 =
mul(
mul(
add(one,
pow(
cot(self.get_arg()), two)), minus_one), result_);
528void DiffVisitor::bvisit(
const Csc &self)
530 apply(self.get_arg());
531 result_ =
mul(
mul(
mul(
cot(self.get_arg()),
csc(self.get_arg())), minus_one),
535void DiffVisitor::bvisit(
const Sec &self)
537 apply(self.get_arg());
538 result_ =
mul(
mul(
tan(self.get_arg()),
sec(self.get_arg())), result_);
541void DiffVisitor::bvisit(
const ASin &self)
543 apply(self.get_arg());
547void DiffVisitor::bvisit(
const ACos &self)
549 apply(self.get_arg());
554void DiffVisitor::bvisit(
const ASec &self)
556 apply(self.get_arg());
563void DiffVisitor::bvisit(
const ACsc &self)
565 apply(self.get_arg());
567 div(minus_one,
mul(
pow(self.get_arg(), i2),
572void DiffVisitor::bvisit(
const ATan &self)
574 apply(self.get_arg());
575 result_ =
mul(
div(one,
add(one,
pow(self.get_arg(), i2))), result_);
578void DiffVisitor::bvisit(
const ACot &self)
580 apply(self.get_arg());
581 result_ =
mul(
div(minus_one,
add(one,
pow(self.get_arg(), i2))), result_);
584void DiffVisitor::bvisit(
const ATan2 &self)
586 apply(
div(self.get_num(), self.get_den()));
587 result_ =
mul(
div(
pow(self.get_den(), i2),
588 add(
pow(self.get_den(), i2),
pow(self.get_num(), i2))),
592void DiffVisitor::bvisit(
const Erf &self)
594 apply(self.get_arg());
601void DiffVisitor::bvisit(
const Erfc &self)
603 apply(self.get_arg());
610void DiffVisitor::bvisit(
const Gamma &self)
612 apply(self.get_arg());
613 result_ =
mul(
mul(self.rcp_from_this(),
polygamma(zero, self.get_arg())),
617void DiffVisitor::bvisit(
const LogGamma &self)
619 apply(self.get_arg());
620 result_ =
mul(
polygamma(zero, self.get_arg()), result_);
623void DiffVisitor::bvisit(
const UIntPoly &self)
625 result_ = diff_upoly<UIntPoly, map_uint_mpz>(self, *x);
628void DiffVisitor::bvisit(
const URatPoly &self)
630 result_ = diff_upoly<URatPoly, map_uint_mpq>(self, *x);
633#ifdef HAVE_SYMENGINE_PIRANHA
634void DiffVisitor::bvisit(
const UIntPolyPiranha &self)
636 result_ = diff_upoly<UIntPolyPiranha, map_uint_mpz>(self, *x);
638void DiffVisitor::bvisit(
const URatPolyPiranha &self)
640 result_ = diff_upoly<URatPolyPiranha, map_uint_mpq>(self, *x);
644#ifdef HAVE_SYMENGINE_FLINT
645void DiffVisitor::bvisit(
const UIntPolyFlint &self)
647 result_ = diff_upolyflint(self, *x);
650void DiffVisitor::bvisit(
const URatPolyFlint &self)
652 result_ = diff_upolyflint(self, *x);
655void DiffVisitor::bvisit(
const MIntPoly &self)
657 result_ = diff_mpoly(self, x);
660void DiffVisitor::bvisit(
const MExprPoly &self)
662 result_ = diff_mpoly(self, x);
665void DiffVisitor::bvisit(
const UExprPoly &self)
667 result_ = diff_upoly<UExprPoly, map_int_Expr>(self, *x);
670void DiffVisitor::bvisit(
const FunctionWrapper &self)
672 result_ = self.diff_impl(x);
675void DiffVisitor::bvisit(
const Beta &self)
677 RCP<const Basic> beta_arg0 = self.get_args()[0];
678 RCP<const Basic> beta_arg1 = self.get_args()[1];
680 RCP<const Basic> diff_beta_arg0 = result_;
682 RCP<const Basic> diff_beta_arg1 = result_;
683 result_ =
mul(self.rcp_from_this(),
687 add(diff_beta_arg0, diff_beta_arg1)))));
690void DiffVisitor::bvisit(
const Set &self)
692 throw SymEngineException(
"Derivative doesn't exist.");
695void DiffVisitor::bvisit(
const Tuple &self)
697 throw NotImplementedError(
"Derivative not implemented");
700void DiffVisitor::bvisit(
const IdentityMatrix &self)
702 throw NotImplementedError(
"Derivative not implemented");
705void DiffVisitor::bvisit(
const ZeroMatrix &self)
707 throw NotImplementedError(
"Derivative not implemented");
710void DiffVisitor::bvisit(
const MatrixSymbol &self)
712 throw NotImplementedError(
"Derivative not implemented");
715void DiffVisitor::bvisit(
const DiagonalMatrix &self)
717 throw NotImplementedError(
"Derivative not implemented");
720void DiffVisitor::bvisit(
const ImmutableDenseMatrix &self)
722 throw NotImplementedError(
"Derivative not implemented");
725void DiffVisitor::bvisit(
const MatrixAdd &self)
727 throw NotImplementedError(
"Derivative not implemented");
730void DiffVisitor::bvisit(
const HadamardProduct &self)
732 throw NotImplementedError(
"Derivative not implemented");
735void DiffVisitor::bvisit(
const MatrixMul &self)
737 throw NotImplementedError(
"Derivative not implemented");
740void DiffVisitor::bvisit(
const ConjugateMatrix &self)
742 throw NotImplementedError(
"Derivative not implemented");
745void DiffVisitor::bvisit(
const Transpose &self)
747 throw NotImplementedError(
"Derivative not implemented");
750void DiffVisitor::bvisit(
const Trace &self)
752 throw NotImplementedError(
"Derivative not implemented");
755void DiffVisitor::bvisit(
const Boolean &self)
757 throw SymEngineException(
"Derivative doesn't exist.");
760void DiffVisitor::bvisit(
const GaloisField &self)
763 if (self.get_var()->__eq__(*x)) {
764 d = self.get_poly().gf_diff();
765 result_ = GaloisField::from_dict(self.get_var(),
std::move(d));
767 result_ = GaloisField::from_dict(self.get_var(),
std::move(d));
771void DiffVisitor::bvisit(
const Piecewise &self)
773 PiecewiseVec v = self.get_vec();
781const RCP<const Basic> &DiffVisitor::apply(
const Basic &b)
783 apply(b.rcp_from_this());
787const RCP<const Basic> &DiffVisitor::apply(
const RCP<const Basic> &b)
793 auto it = visited.find(b);
794 if (it == visited.end()) {
796 insert(visited, b, result_);
798 result_ = it->second;
803RCP<const Basic> diff(
const RCP<const Basic> &arg,
const RCP<const Symbol> &x,
810RCP<const Basic> Basic::diff(
const RCP<const Symbol> &x,
bool cache)
const
812 return SymEngine::diff(this->rcp_from_this(), x, cache);
818RCP<const Basic> sdiff(
const RCP<const Basic> &arg,
const RCP<const Basic> &x,
821 if (is_a<Symbol>(*x)) {
822 return arg->diff(rcp_static_cast<const Symbol>(x), cache);
824 RCP<const Symbol> d = get_dummy(*arg,
"x");
825 return ssubs(
ssubs(arg, {{x, d}})->diff(d, cache), {{d, x}});
Main namespace for SymEngine package.
RCP< const Basic > sec(const RCP< const Basic > &arg)
Canonicalize Sec:
RCP< const Basic > polygamma(const RCP< const Basic > &n_, const RCP< const Basic > &x_)
Canonicalize PolyGamma.
RCP< const Basic > zeta(const RCP< const Basic > &s, const RCP< const Basic > &a)
Create a new Zeta instance:
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > coth(const RCP< const Basic > &arg)
Canonicalize Coth:
void hash_combine(hash_t &seed, const T &v)
RCP< const Basic > sech(const RCP< const Basic > &arg)
Canonicalize Sech:
RCP< const Basic > sub(const RCP< const Basic > &a, const RCP< const Basic > &b)
Substracts b from a.
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
RCP< const Basic > cot(const RCP< const Basic > &arg)
Canonicalize Cot:
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
void insert(T1 &m, const T2 &first, const T3 &second)
int factor(const Ptr< RCP< const Integer > > &f, const Integer &n, double B1)
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
RCP< const Basic > csc(const RCP< const Basic > &arg)
Canonicalize Csc:
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
RCP< const Basic > csch(const RCP< const Basic > &arg)
Canonicalize Csch:
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
RCP< const Basic > lambertw(const RCP< const Basic > &arg)
Create a new LambertW instance:
RCP< const Basic > ssubs(const RCP< const Basic > &x, const map_basic_basic &subs_dict, bool cache=true)
SymPy compatible subs.
RCP< const Basic > neg(const RCP< const Basic > &a)
Negation.