X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fbasic.cpp;h=5c3c147faf57d039fe57e94c9be0e2f92112d7bb;hp=e2a9320e9b098629017fff48aebfc35892292170;hb=857ca8ca24fbfe26d4c0c624aa6c3f2296c419f8;hpb=956eeb82c513a723e864edefa857133282cf692b diff --git a/ginac/basic.cpp b/ginac/basic.cpp index e2a9320e..5c3c147f 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -80,14 +80,7 @@ const basic & basic::operator=(const basic & other) // protected -#if 0 -void basic::copy(const basic & other) -{ - flags=other.flags & ~ status_flags::dynallocated; - hashvalue=other.hashvalue; - tinfo_key=other.tinfo_key; -} -#endif +// none (all inlined) ////////// // other constructors @@ -229,9 +222,9 @@ ex & basic::let_op(int i) ex basic::operator[](const ex & index) const { - if (is_exactly_of_type(*index.bp,numeric)) { + if (is_exactly_of_type(*index.bp,numeric)) return op(static_cast(*index.bp).to_int()); - } + throw(std::invalid_argument("non-numeric indices not supported by this type")); } @@ -240,6 +233,8 @@ ex basic::operator[](int i) const return op(i); } +/** Search ocurrences. An object 'has' an expression if it is the expression + * itself or one of the children 'has' it. */ bool basic::has(const ex & other) const { GINAC_ASSERT(other.bp!=0); @@ -252,47 +247,81 @@ bool basic::has(const ex & other) const return false; } +/** Return degree of highest power in symbol s. */ int basic::degree(const symbol & s) const { return 0; } +/** Return degree of lowest power in symbol s. */ int basic::ldegree(const symbol & s) const { return 0; } +/** Return coefficient of degree n in symbol s. */ ex basic::coeff(const symbol & s, int n) const { return n==0 ? *this : _ex0(); } +/** Sort expression in terms of powers of some symbol. + * @param s symbol to sort in. */ ex basic::collect(const symbol & s) const { ex x; - int ldeg=ldegree(s); - int deg=degree(s); + int ldeg = this->ldegree(s); + int deg = this->degree(s); for (int n=ldeg; n<=deg; n++) { - x += coeff(s,n)*power(s,n); + x += this->coeff(s,n)*power(s,n); } return x; } +/* Perform automatic symbolic evaluations on expression. */ ex basic::eval(int level) const { return this->hold(); } +/** Evaluate object numerically. */ ex basic::evalf(int level) const { return *this; } +/* Substitute a set of symbols. */ ex basic::subs(const lst & ls, const lst & lr) const { return *this; } +/** Default interface of nth derivative ex::diff(s, n). It should be called + * instead of ::derivative(s) for first derivatives and for nth derivatives it + * just recurses down. + * + * @param s symbol to differentiate in + * @param nth order of differentiation + * @see ex::diff */ +ex basic::diff(const symbol & s, unsigned nth) const +{ + // trivial: zeroth derivative + if (!nth) + return ex(*this); + + // evaluate unevalueted *this before differentiating + if (!(flags & status_flags::evaluated)) + return ex(*this).diff(s, nth); + + ex ndiff = derivative(s); + while (!ndiff.is_zero() && // stop differentiating zeros + nth>1) { + ndiff = ndiff.diff(s); + --nth; + } + return ndiff; +} + exvector basic::get_indices(void) const { return exvector(); // return an empty exvector @@ -305,6 +334,15 @@ ex basic::simplify_ncmul(const exvector & v) const // protected +/** Default implementation of ex::diff(). It simply throws an error message. + * + * @exception logic_error (differentiation not supported by this type) + * @see ex::diff */ +ex basic::derivative(const symbol & s) const +{ + throw(std::logic_error("differentiation not supported by this type")); +} + int basic::compare_same_type(const basic & other) const { return compare_pointers(this, &other); @@ -344,24 +382,27 @@ unsigned basic::calchash(void) const return v; } +/** Expand expression, i.e. multiply it out and return the result as a new + * expression. */ ex basic::expand(unsigned options) const { return this->setflag(status_flags::expanded); } + ////////// // non-virtual functions in this class ////////// // public +/** Substitute symbols in expression and return the result as a new expression. + * There are two valid types of replacement arguments: 1) a relational like + * symbol==ex and 2) a list of relationals lst(symbol1==ex1,symbol2==ex2,...), + * which is converted to subs(lst(symbol1,symbol2,...),lst(ex1,ex2,...)). + * In addition, an object of class idx can be used instead of a symbol. */ ex basic::subs(const ex & e) const { - // accept 2 types of replacement expressions: - // - symbol==ex - // - lst(symbol1==ex1,symbol2==ex2,...) - // convert to subs(lst(symbol1,symbol2,...),lst(ex1,ex2,...)) - // additionally, idx can be used instead of symbol if (e.info(info_flags::relation_equal)) { return subs(lst(e)); } @@ -438,6 +479,7 @@ int basic::compare(const basic & other) const return cmpval; } +/** Test for equality. */ bool basic::is_equal(const basic & other) const { unsigned hash_this = gethash(); @@ -457,6 +499,8 @@ bool basic::is_equal(const basic & other) const // protected +/** Stop further evaluation. + * @see basic::eval */ const basic & basic::hold(void) const { return setflag(status_flags::evaluated); @@ -475,8 +519,8 @@ void basic::ensure_if_modifiable(void) const // protected -unsigned basic::precedence=70; -unsigned basic::delta_indent=4; +unsigned basic::precedence = 70; +unsigned basic::delta_indent = 4; ////////// // global constants