]> www.ginac.de Git - ginac.git/blobdiff - ginac/ex.cpp
- ex::numer() and ex::denom() now make use of the new normal()
[ginac.git] / ginac / ex.cpp
index 88395f988f832a3707e01fedacea2b1d511f3be4..6c51fe6e02b596686fd01d788cf8cbe89539239a 100644 (file)
 #include "ncmul.h"
 #include "numeric.h"
 #include "power.h"
+#include "relational.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
@@ -95,58 +96,45 @@ const ex & ex::operator=(const ex & other)
 // 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);
 }
-    
+
+#endif // ndef INLINE_EX_CONSTRUCTORS
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -250,33 +238,7 @@ void ex::dbgprinttree(void) const
 
 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
@@ -315,60 +277,6 @@ ex ex::coeff(const symbol & s, int n) 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);
@@ -387,6 +295,21 @@ ex ex::evalf(int level) const
     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);
@@ -425,6 +348,7 @@ ex ex::operator[](int i) const
     return (*bp)[i];
 }
 
+/** Return operand/member at position i. */
 ex ex::op(int i) const
 {
     debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION);
@@ -432,6 +356,7 @@ ex ex::op(int i) const
     return bp->op(i);
 }
 
+/** Return modifyable operand/member at position i. */
 ex & ex::let_op(int i)
 {
     debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION);
@@ -440,6 +365,22 @@ ex & ex::let_op(int i)
     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
 {
@@ -507,14 +448,14 @@ void ex::makewriteable()
     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)
 {
@@ -530,9 +471,9 @@ 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);
@@ -543,6 +484,143 @@ void ex::construct_from_basic(const basic & other)
     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);
+}
+    
 //////////
 // static member variables
 //////////
@@ -562,6 +640,6 @@ void ex::construct_from_basic(const basic & other)
 // none
 
 
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
 } // namespace GiNaC
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC