3 * Implementation of symbolic differentiation in all of GiNaC's classes. */
9 /** Default implementation of ex::diff(). It prints and error message and returns a fail object.
11 ex basic::diff(symbol const & s) const
13 throw(std::logic_error("differentiation not supported by this type"));
17 /** Implementation of ex::diff() for a numeric. It always returns 0.
20 ex numeric::diff(symbol const & s) const
26 /** Implementation of ex::diff() for single differentiation of a symbol.
30 ex symbol::diff(symbol const & s) const
32 if (compare_same_type(s)) {
39 /** Implementation of ex::diff() for a constant. It always returns 0.
42 ex constant::diff(symbol const & s) const
47 /** Implementation of ex::diff() for multiple differentiation of a symbol.
48 * It returns the symbol, 1 or 0.
50 * @param nth order of differentiation
52 ex symbol::diff(symbol const & s, unsigned nth) const
54 if (compare_same_type(s)) {
71 /** Implementation of ex::diff() for an indexed object. It always returns 0.
73 ex indexed::diff(symbol const & s) const
79 /** Implementation of ex::diff() for an expairseq. It differentiates all elements of the sequence.
81 ex expairseq::diff(symbol const & s) const
83 return thisexpairseq(diffchildren(s),overall_coeff);
87 /** Implementation of ex::diff() for a sum. It differentiates each term.
89 ex add::diff(symbol const & s) const
91 // D(a+b+c)=D(a)+D(b)+D(c)
92 return (new add(diffchildren(s)))->setflag(status_flags::dynallocated);
96 /** Implementation of ex::diff() for a product. It applies the product rule.
98 ex mul::diff(symbol const & s) const
101 new_seq.reserve(seq.size());
103 // D(a*b*c)=D(a)*b*c+a*D(b)*c+a*b*D(c)
104 for (unsigned i=0; i!=seq.size(); i++) {
105 epvector sub_seq=seq;
106 sub_seq[i] = split_ex_to_pair(sub_seq[i].coeff*
107 power(sub_seq[i].rest,sub_seq[i].coeff-1)*
108 sub_seq[i].rest.diff(s));
109 new_seq.push_back((new mul(sub_seq,overall_coeff))->setflag(status_flags::dynallocated));
111 return (new add(new_seq))->setflag(status_flags::dynallocated);
115 /** Implementation of ex::diff() for a non-commutative product. It always returns 0.
117 ex ncmul::diff(symbol const & s) const
123 /** Implementation of ex::diff() for a power.
125 ex power::diff(symbol const & s) const
127 if (exponent.info(info_flags::real)) {
128 // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below)
129 return mul(mul(exponent, power(basis, exponent - exONE())), basis.diff(s));
131 // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b)
132 return mul(power(basis, exponent),
133 add(mul(exponent.diff(s), log(basis)),
134 mul(mul(exponent, basis.diff(s)), power(basis, -1))));
139 /** Implementation of ex::diff() for functions. It applies the chain rule,
140 * except for the Order term function.
142 ex function::diff(symbol const & s) const
146 if (serial == function_index_Order) {
148 // Order Term function only differentiates the argument
149 return Order(seq[0].diff(s));
154 for (unsigned i=0; i!=seq.size(); i++) {
155 new_seq.push_back(mul(pdiff(i), seq[i].diff(s)));
162 /** Implementation of ex::diff() for a power-series. It treats the series as a polynomial.
164 ex series::diff(symbol const & s) const
168 epvector::const_iterator it = seq.begin(), itend = seq.end();
170 //!! coeff might depend on var
171 while (it != itend) {
172 if (is_order_function(it->rest)) {
173 new_seq.push_back(expair(it->rest, it->coeff - 1));
175 ex c = it->rest * it->coeff;
177 new_seq.push_back(expair(c, it->coeff - 1));
181 return series(var, point, new_seq);
188 /** Compute partial derivative of an expression.
190 * @param s symbol by which the expression is derived
191 * @param nth order of derivative (default 1)
192 * @return partial derivative as a new expression */
194 ex ex::diff(symbol const & s, unsigned nth) const
202 ex ndiff = bp->diff(s);
204 ndiff = ndiff.diff(s);