*/
#include <iostream>
+#include <stdexcept>
#include "ex.h"
#include "add.h"
#include "ncmul.h"
#include "numeric.h"
#include "power.h"
+#include "relational.h"
+#include "input_lexer.h"
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
// public
#ifndef INLINE_EX_CONSTRUCTORS
+
ex::ex(const basic & other)
{
debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
construct_from_basic(other);
}
-#endif
ex::ex(int i)
{
debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
- switch (i) { // some tiny efficiency-hack (FIXME: is this ok?)
- case -1:
- bp = _ex_1().bp;
- ++bp->refcount;
- break;
- case 0:
- bp = _ex0().bp;
- ++bp->refcount;
- break;
- case 1:
- bp = _ex1().bp;
- ++bp->refcount;
- break;
- default:
- construct_from_basic(numeric(i));
- }
+ construct_from_int(i);
}
ex::ex(unsigned int i)
{
debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
- construct_from_basic(numeric(i));
+ construct_from_uint(i);
}
ex::ex(long i)
{
debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
- construct_from_basic(numeric(i));
+ construct_from_long(i);
}
ex::ex(unsigned long i)
{
debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
- construct_from_basic(numeric(i));
+ construct_from_ulong(i);
}
ex::ex(double const d)
{
debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
- construct_from_basic(numeric(d));
+ construct_from_double(d);
}
-
+
+ex::ex(const string &s, const ex &l)
+{
+ debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT);
+ construct_from_string_and_lst(s, l);
+}
+
+#endif // ndef INLINE_EX_CONSTRUCTORS
+
//////////
// functions overriding virtual functions from bases classes
//////////
bool ex::info(unsigned inf) const
{
- if (inf == info_flags::normal_form) {
-
- // Polynomials are in normal form
- if (info(info_flags::polynomial))
- return true;
-
- // polynomial^(-int) is in normal form
- if (is_ex_exactly_of_type(*this, power))
- return op(1).info(info_flags::negint);
-
- // polynomial^(int) * polynomial^(int) * ... is in normal form
- if (!is_ex_exactly_of_type(*this, mul))
- return false;
- for (unsigned i=0; i<nops(); i++) {
- if (is_ex_exactly_of_type(op(i), power)) {
- if (!op(i).op(1).info(info_flags::integer))
- return false;
- if (!op(i).op(0).info(info_flags::polynomial))
- return false;
- } else
- if (!op(i).info(info_flags::polynomial))
- return false;
- }
- return true;
- } else {
- return bp->info(inf);
- }
+ return bp->info(inf);
}
unsigned ex::nops() const
ex ex::expand(unsigned options) const
{
GINAC_ASSERT(bp!=0);
- return bp->expand(options);
+ if (bp->flags & status_flags::expanded)
+ return *bp;
+ else
+ return bp->expand(options);
}
bool ex::has(const ex & other) const
return bp->coeff(s,n);
}
-ex ex::numer(bool normalize) const
-{
- ex n;
- if (normalize && !info(info_flags::normal_form))
- n = normal();
- else
- n = *this;
-
- // polynomial
- if (n.info(info_flags::polynomial))
- return n;
-
- // something^(-int)
- if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
- return _ex1();
-
- // something^(int) * something^(int) * ...
- if (!is_ex_exactly_of_type(n, mul))
- return n;
- ex res = _ex1();
- for (unsigned i=0; i<n.nops(); i++) {
- if (!is_ex_exactly_of_type(n.op(i), power) || !n.op(i).op(1).info(info_flags::negint))
- res *= n.op(i);
- }
- return res;
-}
-
-ex ex::denom(bool normalize) const
-{
- ex n;
- if (normalize && !info(info_flags::normal_form))
- n = normal();
- else
- n = *this;
-
- // polynomial
- if (n.info(info_flags::polynomial))
- return _ex1();
-
- // something^(-int)
- if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
- return power(n.op(0), -(n.op(1)));
-
- // something^(int) * something^(int) * ...
- if (!is_ex_exactly_of_type(n, mul))
- return _ex1();
- ex res = _ex1();
- for (unsigned i=0; i<n.nops(); i++) {
- if (is_ex_exactly_of_type(n.op(i), power) && n.op(i).op(1).info(info_flags::negint))
- res *= power(n.op(i), -1);
- }
- return res;
-}
-
ex ex::collect(const symbol & s) const
{
GINAC_ASSERT(bp!=0);
return bp->evalf(level);
}
+/** Compute partial derivative of an expression.
+ *
+ * @param s symbol by which the expression is derived
+ * @param nth order of derivative (default 1)
+ * @return partial derivative as a new expression */
+ex ex::diff(const symbol & s, unsigned nth) const
+{
+ GINAC_ASSERT(bp!=0);
+
+ if (!nth)
+ return *this;
+ else
+ return bp->diff(s, nth);
+}
+
ex ex::subs(const lst & ls, const lst & lr) const
{
GINAC_ASSERT(bp!=0);
return (*bp)[i];
}
+/** Return operand/member at position i. */
ex ex::op(int i) const
{
debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
return bp->op(i);
}
+/** Return modifyable operand/member at position i. */
ex & ex::let_op(int i)
{
debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
return bp->let_op(i);
}
+/** Left hand side of relational expression. */
+ex ex::lhs(void) const
+{
+ debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION);
+ GINAC_ASSERT(is_ex_of_type(*this,relational));
+ return (*static_cast<relational *>(bp)).lhs();
+}
+
+/** Right hand side of relational expression. */
+ex ex::rhs(void) const
+{
+ debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION);
+ GINAC_ASSERT(is_ex_of_type(*this,relational));
+ return (*static_cast<relational *>(bp)).rhs();
+}
+
#ifndef INLINE_EX_CONSTRUCTORS
int ex::compare(const ex & other) const
{
GINAC_ASSERT(bp!=0);
GINAC_ASSERT(bp->flags & status_flags::dynallocated);
if (bp->refcount > 1) {
- basic * bp2=bp->duplicate();
+ basic * bp2 = bp->duplicate();
++bp2->refcount;
bp2->setflag(status_flags::dynallocated);
--bp->refcount;
- bp=bp2;
+ bp = bp2;
}
GINAC_ASSERT(bp->refcount == 1);
-}
+}
void ex::construct_from_basic(const basic & other)
{
}
} else {
if (other.flags & status_flags::dynallocated) {
- bp=&const_cast<basic &>(other);
+ bp = &const_cast<basic &>(other);
} else {
- bp=other.duplicate();
+ bp = other.duplicate();
bp->setflag(status_flags::dynallocated);
}
GINAC_ASSERT(bp!=0);
GINAC_ASSERT(bp->flags & status_flags::dynallocated);
}
+void ex::construct_from_int(int i)
+{
+ switch (i) { // some tiny efficiency-hack
+ case -2:
+ bp = _ex_2().bp;
+ ++bp->refcount;
+ break;
+ case -1:
+ bp = _ex_1().bp;
+ ++bp->refcount;
+ break;
+ case 0:
+ bp = _ex0().bp;
+ ++bp->refcount;
+ break;
+ case 1:
+ bp = _ex1().bp;
+ ++bp->refcount;
+ break;
+ case 2:
+ bp = _ex2().bp;
+ ++bp->refcount;
+ break;
+ default:
+ bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ ++bp->refcount;
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ GINAC_ASSERT(bp->refcount=1);
+ }
+}
+
+void ex::construct_from_uint(unsigned int i)
+{
+ switch (i) { // some tiny efficiency-hack
+ case -2:
+ bp = _ex_2().bp;
+ ++bp->refcount;
+ break;
+ case -1:
+ bp = _ex_1().bp;
+ ++bp->refcount;
+ break;
+ case 0:
+ bp = _ex0().bp;
+ ++bp->refcount;
+ break;
+ case 1:
+ bp = _ex1().bp;
+ ++bp->refcount;
+ break;
+ case 2:
+ bp = _ex2().bp;
+ ++bp->refcount;
+ break;
+ default:
+ bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ ++bp->refcount;
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ GINAC_ASSERT(bp->refcount=1);
+ }
+}
+
+void ex::construct_from_long(long i)
+{
+ switch (i) { // some tiny efficiency-hack
+ case -2:
+ bp = _ex_2().bp;
+ ++bp->refcount;
+ break;
+ case -1:
+ bp = _ex_1().bp;
+ ++bp->refcount;
+ break;
+ case 0:
+ bp = _ex0().bp;
+ ++bp->refcount;
+ break;
+ case 1:
+ bp = _ex1().bp;
+ ++bp->refcount;
+ break;
+ case 2:
+ bp = _ex2().bp;
+ ++bp->refcount;
+ break;
+ default:
+ bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ ++bp->refcount;
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ GINAC_ASSERT(bp->refcount=1);
+ }
+}
+
+void ex::construct_from_ulong(unsigned long i)
+{
+ switch (i) { // some tiny efficiency-hack
+ case -2:
+ bp = _ex_2().bp;
+ ++bp->refcount;
+ break;
+ case -1:
+ bp = _ex_1().bp;
+ ++bp->refcount;
+ break;
+ case 0:
+ bp = _ex0().bp;
+ ++bp->refcount;
+ break;
+ case 1:
+ bp = _ex1().bp;
+ ++bp->refcount;
+ break;
+ case 2:
+ bp = _ex2().bp;
+ ++bp->refcount;
+ break;
+ default:
+ bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ ++bp->refcount;
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ GINAC_ASSERT(bp->refcount=1);
+ }
+}
+
+void ex::construct_from_double(double d)
+{
+ bp = new numeric(d);
+ bp->setflag(status_flags::dynallocated);
+ ++bp->refcount;
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ GINAC_ASSERT(bp->refcount=1);
+}
+
+void ex::construct_from_string_and_lst(const string &s, const ex &l)
+{
+ set_lexer_string(s);
+ set_lexer_symbols(l);
+ ginac_yyrestart(NULL);
+ if (ginac_yyparse())
+ throw (std::runtime_error(get_parser_error()));
+ else {
+ bp = parsed_ex.bp;
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ ++bp->refcount;
+ }
+}
+
//////////
// static member variables
//////////
// none
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC