]> www.ginac.de Git - ginac.git/blobdiff - ginac/ex.cpp
- Banned exZERO(), exONE(), exMINUSHALF() and all this from the interface.
[ginac.git] / ginac / ex.cpp
index c30efddac37b449193263f329d367f7a915fdd78..6a7a0aa91bdf3b823bf48beda6cbd735948523a6 100644 (file)
@@ -1,7 +1,8 @@
 /** @file ex.cpp
  *
- *  Implementation of GiNaC's light-weight expression handles.
- *
+ *  Implementation of GiNaC's light-weight expression handles. */
+
+/*
  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
 #include "ncmul.h"
 #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);
-    ASSERT(exZERO().bp!=0);
-    ASSERT(exZERO().bp->flags & status_flags::dynallocated);
-    ASSERT(bp!=0);
+    GINAC_ASSERT(ex0().bp!=0);
+    GINAC_ASSERT(ex0().bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
     ++bp->refcount;
 }
 
 ex::~ex()
 {
     debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
-    ASSERT(bp!=0);
-    ASSERT(bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(bp->flags & status_flags::dynallocated);
     if (--bp->refcount == 0) {
         delete bp;
     }
@@ -58,18 +65,18 @@ ex::~ex()
 ex::ex(ex const & other) : bp(other.bp)
 {
     debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
-    ASSERT(bp!=0);
-    ASSERT((bp->flags) & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
     ++bp->refcount;
 }
 
 ex const & ex::operator=(ex const & other)
 {
     debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
-    ASSERT(bp!=0);
-    ASSERT(bp->flags & status_flags::dynallocated);
-    ASSERT(other.bp!=0);
-    ASSERT(other.bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(other.bp!=0);
+    GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
     ++other.bp->refcount;
     basic * tmpbp=other.bp;
     if (--bp->refcount==0) {
@@ -143,20 +150,89 @@ ex::ex(double const d)
 
 // public
 
+/** Swap the contents of two expressions. */
 void ex::swap(ex & other)
 {
     debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
 
-    ASSERT(bp!=0);
-    ASSERT(bp->flags & status_flags::dynallocated);
-    ASSERT(other.bp!=0);
-    ASSERT(other.bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(other.bp!=0);
+    GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
     
     basic * tmpbp=bp;
     bp=other.bp;
     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) {
@@ -190,37 +266,37 @@ bool ex::info(unsigned inf) const
 
 int ex::nops() const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->nops();
 }
 
 ex ex::expand(unsigned options) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->expand(options);
 }
 
 bool ex::has(ex const & other) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->has(other);
 }
 
 int ex::degree(symbol const & s) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->degree(s);
 }
 
 int ex::ldegree(symbol const & s) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->ldegree(s);
 }
 
 ex ex::coeff(symbol const & s, int const n) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->coeff(s,n);
 }
 
@@ -238,12 +314,12 @@ ex ex::numer(bool normalize) const
 
     // 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();
+    ex res = _ex1();
     for (int 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);
@@ -261,7 +337,7 @@ ex ex::denom(bool normalize) const
 
     // 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))
@@ -269,8 +345,8 @@ ex ex::denom(bool normalize) const
 
     // something^(int) * something^(int) * ...
     if (!is_ex_exactly_of_type(n, mul))
-        return exONE();
-    ex res = exONE();
+        return _ex1();
+    ex res = _ex1();
     for (int 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);
@@ -280,64 +356,64 @@ ex ex::denom(bool normalize) const
 
 ex ex::collect(symbol const & s) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->collect(s);
 }
 
 ex ex::eval(int level) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->eval(level);
 }
 
 ex ex::evalf(int level) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->evalf(level);
 }
 
 ex ex::subs(lst const & ls, lst const & lr) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->subs(ls,lr);
 }
 
 ex ex::subs(ex const & e) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->subs(e);
 }
 
 exvector ex::get_indices(void) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->get_indices();
 }
 
 ex ex::simplify_ncmul(exvector const & v) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->simplify_ncmul(v);
 }
 
 ex ex::operator[](ex const & index) const
 {
     debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR);
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return (*bp)[index];
 }
 
 ex ex::operator[](int const i) const
 {
     debugmsg("ex operator[int]",LOGLEVEL_OPERATOR);
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return (*bp)[i];
 }
 
 ex ex::op(int const i) const
 {
     debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->op(i);
 }
 
@@ -345,15 +421,15 @@ ex & ex::let_op(int const i)
 {
     debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
     makewriteable();
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->let_op(i);
 }
 
 #ifndef INLINE_EX_CONSTRUCTORS
 int ex::compare(ex const & other) const
 {
-    ASSERT(bp!=0);
-    ASSERT(other.bp!=0);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(other.bp!=0);
     if (bp==other.bp) {
         // special case: both expression point to same basic, trivially equal
         return 0; 
@@ -365,8 +441,8 @@ int ex::compare(ex const & other) const
 #ifndef INLINE_EX_CONSTRUCTORS
 bool ex::is_equal(ex const & other) const
 {
-    ASSERT(bp!=0);
-    ASSERT(other.bp!=0);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(other.bp!=0);
     if (bp==other.bp) {
         // special case: both expression point to same basic, trivially equal
         return true; 
@@ -377,19 +453,19 @@ bool ex::is_equal(ex const & other) const
 
 unsigned ex::return_type(void) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->return_type();
 }
 
 unsigned ex::return_type_tinfo(void) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->return_type_tinfo();
 }
 
 unsigned ex::gethash(void) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
     return bp->gethash();
 }
 
@@ -413,8 +489,8 @@ ex ex::exncmul(ex const & rh) const
 void ex::makewriteable()
 {
     debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
-    ASSERT(bp!=0);
-    ASSERT(bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(bp->flags & status_flags::dynallocated);
     if (bp->refcount > 1) {
         basic * bp2=bp->duplicate();
         ++bp2->refcount;
@@ -422,17 +498,17 @@ void ex::makewriteable()
         --bp->refcount;
         bp=bp2;
     }
-    ASSERT(bp->refcount == 1);
+    GINAC_ASSERT(bp->refcount == 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;
-        ASSERT(bp!=0);
-        ASSERT(bp->flags & status_flags::dynallocated);
+        GINAC_ASSERT(bp!=0);
+        GINAC_ASSERT(bp->flags & status_flags::dynallocated);
         ++bp->refcount;
         if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
             delete &const_cast<basic &>(other);
@@ -444,12 +520,12 @@ void ex::construct_from_basic(basic const & other)
             bp=other.duplicate();
             bp->setflag(status_flags::dynallocated);
         }
-        ASSERT(bp!=0);
+        GINAC_ASSERT(bp!=0);
         // bp->clearflag(status_flags::evaluated);
         ++bp->refcount;
     }
-    ASSERT(bp!=0);
-    ASSERT(bp->flags & status_flags::dynallocated);
+    GINAC_ASSERT(bp!=0);
+    GINAC_ASSERT(bp->flags & status_flags::dynallocated);
 }
 
 //////////
@@ -468,45 +544,9 @@ void ex::construct_from_basic(basic const & other)
 // 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