X-Git-Url: https://ginac.de/ginac.git//ginac.git?a=blobdiff_plain;ds=inline;f=ginac%2Fbasic.cpp;h=5da77cc6e95b3ef523cb69621ee80a8296740e7a;hb=aae2dae47827f2b0102b7557bddc22e8555d490b;hp=b632a6e3f08064bf6af3305958b4fa4baa8bd6e3;hpb=0a1b35cf1e59c9e3aae33de8febaa1c8f4bbe630;p=ginac.git diff --git a/ginac/basic.cpp b/ginac/basic.cpp index b632a6e3..5da77cc6 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -35,9 +35,9 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_GINAC_NAMESPACE +#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_GINAC_NAMESPACE +#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void) @@ -61,14 +61,14 @@ basic::~basic() GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); } -basic::basic(basic const & other) : flags(0), refcount(0), tinfo_key(TINFO_BASIC) +basic::basic(const basic & other) : flags(0), refcount(0), tinfo_key(TINFO_BASIC) { debugmsg("basic copy constructor", LOGLEVEL_CONSTRUCT); copy(other); } #endif -basic const & basic::operator=(basic const & other) +const basic & basic::operator=(const basic & other) { debugmsg("basic operator=", LOGLEVEL_ASSIGNMENT); if (this != &other) { @@ -80,14 +80,7 @@ basic const & basic::operator=(basic const & other) // protected -#if 0 -void basic::copy(basic const & other) -{ - flags=other.flags & ~ status_flags::dynallocated; - hashvalue=other.hashvalue; - tinfo_key=other.tinfo_key; -} -#endif +// none (all inlined) ////////// // other constructors @@ -201,40 +194,48 @@ basic * basic::duplicate() const return new basic(*this); } +/** Information about the object. + * + * @see class info_flags */ bool basic::info(unsigned inf) const { return false; // all possible properties are false for basic objects } +/** Number of operands/members. */ unsigned basic::nops() const { return 0; } -ex basic::op(int const i) const +/** Return operand/member at position i. */ +ex basic::op(int i) const { return (const_cast(this))->let_op(i); } -ex & basic::let_op(int const i) +/** Return modifyable operand/member at position i. */ +ex & basic::let_op(int i) { throw(std::out_of_range("op() out of range")); } -ex basic::operator[](ex const & index) const +ex basic::operator[](const ex & index) const { - if (is_exactly_of_type(*index.bp,numeric)) { - return op(static_cast(*index.bp).to_int()); - } + 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")); } -ex basic::operator[](int const i) const +ex basic::operator[](int i) const { return op(i); } -bool basic::has(ex const & other) const +/** 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); if (is_equal(*other.bp)) return true; @@ -246,65 +247,113 @@ bool basic::has(ex const & other) const return false; } -int basic::degree(symbol const & s) const +/** Return degree of highest power in symbol s. */ +int basic::degree(const symbol & s) const { return 0; } -int basic::ldegree(symbol const & s) const +/** Return degree of lowest power in symbol s. */ +int basic::ldegree(const symbol & s) const { return 0; } -ex basic::coeff(symbol const & s, int const n) const +/** Return coefficient of degree n in symbol s. */ +ex basic::coeff(const symbol & s, int n) const { return n==0 ? *this : _ex0(); } -ex basic::collect(symbol const & s) const +/** 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; } -ex basic::subs(lst const & ls, lst const & lr) const +/* 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 } -ex basic::simplify_ncmul(exvector const & v) const +ex basic::simplify_ncmul(const exvector & v) const { return simplified_ncmul(v); } // protected -int basic::compare_same_type(basic const & other) const +/** 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")); +} + +/** Returns order relation between two objects of same type. Needs to be + * implemented by each class. */ +int basic::compare_same_type(const basic & other) const { return compare_pointers(this, &other); } -bool basic::is_equal_same_type(basic const & other) const +/** Returns true if two objects of same type are equal. Normally needs + * not be reimplemented as long as it wasn't overwritten by some parent + * class, since it just calls complare_same_type(). */ +bool basic::is_equal_same_type(const basic & other) const { return compare_same_type(other)==0; } @@ -324,7 +373,7 @@ unsigned basic::calchash(void) const unsigned v=golden_ratio_hash(tinfo()); for (unsigned i=0; i(this))->let_op(i).gethash(); + v ^= (const_cast(this))->op(i).gethash(); } v = v & 0x7FFFFFFFU; @@ -338,24 +387,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 -ex basic::subs(ex const & e) const +/** 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)); } @@ -382,7 +434,7 @@ ex basic::subs(ex const & e) const /** Compare objects to establish canonical order. * All compare functions return: -1 for *this less than other, 0 equal, * 1 greater. */ -int basic::compare(basic const & other) const +int basic::compare(const basic & other) const { unsigned hash_this = gethash(); unsigned hash_other = other.gethash(); @@ -432,7 +484,8 @@ int basic::compare(basic const & other) const return cmpval; } -bool basic::is_equal(basic const & other) const +/** Test for equality. */ +bool basic::is_equal(const basic & other) const { unsigned hash_this = gethash(); unsigned hash_other = other.gethash(); @@ -451,7 +504,9 @@ bool basic::is_equal(basic const & other) const // protected -basic const & basic::hold(void) const +/** Stop further evaluation. + * @see basic::eval */ +const basic & basic::hold(void) const { return setflag(status_flags::evaluated); } @@ -469,15 +524,15 @@ 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 ////////// const basic some_basic; -type_info const & typeid_basic=typeid(some_basic); +const type_info & typeid_basic=typeid(some_basic); ////////// // global variables @@ -485,6 +540,6 @@ type_info const & typeid_basic=typeid(some_basic); int max_recursion_level=1024; -#ifndef NO_GINAC_NAMESPACE +#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_GINAC_NAMESPACE +#endif // ndef NO_NAMESPACE_GINAC