* Implementation of GiNaC's light-weight expression handles. */
/*
- * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "numeric.h"
#include "power.h"
#include "debugmsg.h"
+#include "utils.h"
+#ifndef NO_GINAC_NAMESPACE
namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
#ifndef INLINE_EX_CONSTRUCTORS
-ex::ex() : bp(exZERO().bp)
+ex::ex() : bp(ex0().bp)
{
debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
- GINAC_ASSERT(exZERO().bp!=0);
- GINAC_ASSERT(exZERO().bp->flags & status_flags::dynallocated);
+ GINAC_ASSERT(ex0().bp!=0);
+ GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
GINAC_ASSERT(bp!=0);
++bp->refcount;
}
ex::ex(int const i)
{
debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
- construct_from_basic(numeric(i));
+ 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));
+ }
}
ex::ex(unsigned int const i)
// public
+/** Swap the contents of two expressions. */
void ex::swap(ex & other)
{
debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
other.bp=tmpbp;
}
+/** Output formatted to be useful as ginsh input. */
+void ex::print(ostream & os, unsigned upper_precedence) const
+{
+ debugmsg("ex print",LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ bp->print(os,upper_precedence);
+}
+
+void ex::printraw(ostream & os) const
+{
+ debugmsg("ex printraw",LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ os << "ex(";
+ bp->printraw(os);
+ os << ")";
+}
+
+void ex::printtree(ostream & os, unsigned indent) const
+{
+ debugmsg("ex printtree",LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ // os << "refcount=" << bp->refcount << " ";
+ bp->printtree(os,indent);
+}
+
+/** Print expression as a C++ statement. The output looks like
+ * "<type> <var_name> = <expression>;". The "type" parameter has an effect
+ * on how number literals are printed.
+ *
+ * @param os output stream
+ * @param type variable type (one of the csrc_types)
+ * @param var_name variable name to be printed */
+void ex::printcsrc(ostream & os, unsigned type, const char *var_name) const
+{
+ debugmsg("ex print csrc", LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ switch (type) {
+ case csrc_types::ctype_float:
+ os << "float ";
+ break;
+ case csrc_types::ctype_double:
+ os << "double ";
+ break;
+ case csrc_types::ctype_cl_N:
+ os << "cl_N ";
+ break;
+ }
+ os << var_name << " = ";
+ bp->printcsrc(os, type, 0);
+ os << ";\n";
+}
+
+/** Little wrapper arount print to be called within a debugger. */
+void ex::dbgprint(void) const
+{
+ debugmsg("ex dbgprint",LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ bp->dbgprint();
+}
+
+/** Little wrapper arount printtree to be called within a debugger. */
+void ex::dbgprinttree(void) const
+{
+ debugmsg("ex dbgprinttree",LOGLEVEL_PRINT);
+ GINAC_ASSERT(bp!=0);
+ bp->dbgprinttree();
+}
+
bool ex::info(unsigned inf) const
{
if (inf == info_flags::normal_form) {
// polynomial^(int) * polynomial^(int) * ... is in normal form
if (!is_ex_exactly_of_type(*this, mul))
return false;
- for (int i=0; i<nops(); i++) {
+ 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;
}
}
-int ex::nops() const
+unsigned ex::nops() const
{
GINAC_ASSERT(bp!=0);
return bp->nops();
// something^(-int)
if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
- return exONE();
+ return _ex1();
// something^(int) * something^(int) * ...
if (!is_ex_exactly_of_type(n, mul))
return n;
- ex res = exONE();
- for (int i=0; i<n.nops(); i++) {
+ 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);
}
// polynomial
if (n.info(info_flags::polynomial))
- return exONE();
+ return _ex1();
// something^(-int)
if (is_ex_exactly_of_type(n, power) && n.op(1).info(info_flags::negint))
// something^(int) * something^(int) * ...
if (!is_ex_exactly_of_type(n, mul))
- return exONE();
- ex res = exONE();
- for (int i=0; i<n.nops(); i++) {
+ 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);
}
void ex::construct_from_basic(basic const & other)
{
- if ( (other.flags & status_flags::evaluated)==0 ) {
+ if ((other.flags & status_flags::evaluated)==0) {
// cf. copy constructor
ex const & tmpex = other.eval(1); // evaluate only one (top) level
bp = tmpex.bp;
// global functions
//////////
-ex const & exZERO(void)
-{
- static ex * eZERO=new ex(numZERO());
- return *eZERO;
-}
-
-ex const & exONE(void)
-{
- static ex * eONE=new ex(numONE());
- return *eONE;
-}
-
-ex const & exTWO(void)
-{
- static ex * eTWO=new ex(numTWO());
- return *eTWO;
-}
-
-ex const & exTHREE(void)
-{
- static ex * eTHREE=new ex(numTHREE());
- return *eTHREE;
-}
-
-ex const & exMINUSONE(void)
-{
- static ex * eMINUSONE=new ex(numMINUSONE());
- return *eMINUSONE;
-}
-
-ex const & exHALF(void)
-{
- static ex * eHALF=new ex(ex(1)/ex(2));
- return *eHALF;
-}
+// none
-ex const & exMINUSHALF(void)
-{
- static ex * eMINUSHALF=new ex(numeric(-1,2));
- return *eMINUSHALF;
-}
+#ifndef NO_GINAC_NAMESPACE
} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE