]> www.ginac.de Git - ginac.git/blobdiff - ginac/ex.cpp
Synced to HEAD
[ginac.git] / ginac / ex.cpp
index e3e54c132d2d8fb27348d56efc457e1fdf6b4ff8..4f0da0d631627db1a083d3a9e2cea321e9b581a3 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's light-weight expression handles. */
 
 /*
- *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2004 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
@@ -73,7 +73,7 @@ void ex::dbgprinttree() const
 ex ex::expand(unsigned options) const
 {
        if (options == 0 && (bp->flags & status_flags::expanded)) // The "expanded" flag only covers the standard options; someone might want to re-expand with different options
-               return *bp;
+               return *this;
        else
                return bp->expand(options);
 }
@@ -146,34 +146,43 @@ ex ex::subs(const lst & ls, const lst & lr, unsigned options) const
 ex ex::subs(const ex & e, unsigned options) const
 {
        if (e.info(info_flags::relation_equal)) {
+
+               // Argument is a relation: convert it to a map
                exmap m;
-               const ex & s = e.lhs();
-               m.insert(std::make_pair(s, e.rhs()));
+               const ex & s = e.op(0);
+               m.insert(std::make_pair(s, e.op(1)));
+
                if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
                        options |= subs_options::pattern_is_product;
+               else
+                       options |= subs_options::pattern_is_not_product;
+
                return bp->subs(m, options);
-       } else if (!e.info(info_flags::list))
-               throw(std::invalid_argument("basic::subs(ex): argument must be a list"));
 
-       // Convert the list to a map
-       exmap m;
-       GINAC_ASSERT(is_a<lst>(e));
-       for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
-               ex r = *it;
-               if (!r.info(info_flags::relation_equal))
-                       throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
-               const ex & s = r.lhs();
-               m.insert(std::make_pair(s, r.rhs()));
+       } else if (e.info(info_flags::list)) {
 
-               // Search for products and powers in the expressions to be substituted
-               // (for an optimization in expairseq::subs())
-               if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
-                       options |= subs_options::pattern_is_product;
-       }
-       if (!(options & subs_options::pattern_is_product))
-               options |= subs_options::pattern_is_not_product;
+               // Argument is a list: convert it to a map
+               exmap m;
+               GINAC_ASSERT(is_a<lst>(e));
+               for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
+                       ex r = *it;
+                       if (!r.info(info_flags::relation_equal))
+                               throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
+                       const ex & s = r.op(0);
+                       m.insert(std::make_pair(s, r.op(1)));
+
+                       // Search for products and powers in the expressions to be substituted
+                       // (for an optimization in expairseq::subs())
+                       if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
+                               options |= subs_options::pattern_is_product;
+               }
+               if (!(options & subs_options::pattern_is_product))
+                       options |= subs_options::pattern_is_not_product;
 
-       return bp->subs(m, options);
+               return bp->subs(m, options);
+
+       } else
+               throw(std::invalid_argument("ex::subs(ex): argument must be a relation_equal or a list"));
 }
 
 /** Traverse expression tree with given visitor, preorder traversal. */
@@ -239,7 +248,20 @@ void ex::makewriteable()
 {
        GINAC_ASSERT(bp->flags & status_flags::dynallocated);
        bp.makewritable();
-       GINAC_ASSERT(bp->refcount == 1);
+       GINAC_ASSERT(bp->get_refcount() == 1);
+}
+
+/** Share equal objects between expressions.
+ *  @see ex::compare(const ex &) */
+void ex::share(const ex & other) const
+{
+       if ((bp->flags | other.bp->flags) & status_flags::not_shareable)
+               return;
+
+       if (bp->get_refcount() <= other.bp->get_refcount())
+               bp = other.bp;
+       else
+               other.bp = bp;
 }
 
 /** Helper function for the ex-from-basic constructor. This is where GiNaC's
@@ -274,7 +296,7 @@ ptr<basic> ex::construct_from_basic(const basic & other)
                // it means that eval() hit case b) above. The original object is
                // no longer needed (it evaluated into something different), so we
                // delete it (because nobody else will).
-               if ((other.refcount==0) && (other.flags & status_flags::dynallocated))
+               if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated))
                        delete &other; // yes, you can apply delete to a const pointer
 
                // We can't return a basic& here because the tmpex is destroyed as
@@ -297,7 +319,7 @@ ptr<basic> ex::construct_from_basic(const basic & other)
                        // on the heap.
                        basic *bp = other.duplicate();
                        bp->setflag(status_flags::dynallocated);
-                       GINAC_ASSERT(bp->refcount == 0);
+                       GINAC_ASSERT(bp->get_refcount() == 0);
                        return bp;
                }
        }
@@ -307,59 +329,59 @@ basic & ex::construct_from_int(int i)
 {
        switch (i) {  // prefer flyweights over new objects
        case -12:
-               return const_cast<numeric &>(_num_12);
+               return *const_cast<numeric *>(_num_12_p);
        case -11:
-               return const_cast<numeric &>(_num_11);
+               return *const_cast<numeric *>(_num_11_p);
        case -10:
-               return const_cast<numeric &>(_num_10);
+               return *const_cast<numeric *>(_num_10_p);
        case -9:
-               return const_cast<numeric &>(_num_9);
+               return *const_cast<numeric *>(_num_9_p);
        case -8:
-               return const_cast<numeric &>(_num_8);
+               return *const_cast<numeric *>(_num_8_p);
        case -7:
-               return const_cast<numeric &>(_num_7);
+               return *const_cast<numeric *>(_num_7_p);
        case -6:
-               return const_cast<numeric &>(_num_6);
+               return *const_cast<numeric *>(_num_6_p);
        case -5:
-               return const_cast<numeric &>(_num_5);
+               return *const_cast<numeric *>(_num_5_p);
        case -4:
-               return const_cast<numeric &>(_num_4);
+               return *const_cast<numeric *>(_num_4_p);
        case -3:
-               return const_cast<numeric &>(_num_3);
+               return *const_cast<numeric *>(_num_3_p);
        case -2:
-               return const_cast<numeric &>(_num_2);
+               return *const_cast<numeric *>(_num_2_p);
        case -1:
-               return const_cast<numeric &>(_num_1);
+               return *const_cast<numeric *>(_num_1_p);
        case 0:
-               return const_cast<numeric &>(_num0);
+               return *const_cast<numeric *>(_num0_p);
        case 1:
-               return const_cast<numeric &>(_num1);
+               return *const_cast<numeric *>(_num1_p);
        case 2:
-               return const_cast<numeric &>(_num2);
+               return *const_cast<numeric *>(_num2_p);
        case 3:
-               return const_cast<numeric &>(_num3);
+               return *const_cast<numeric *>(_num3_p);
        case 4:
-               return const_cast<numeric &>(_num4);
+               return *const_cast<numeric *>(_num4_p);
        case 5:
-               return const_cast<numeric &>(_num5);
+               return *const_cast<numeric *>(_num5_p);
        case 6:
-               return const_cast<numeric &>(_num6);
+               return *const_cast<numeric *>(_num6_p);
        case 7:
-               return const_cast<numeric &>(_num7);
+               return *const_cast<numeric *>(_num7_p);
        case 8:
-               return const_cast<numeric &>(_num8);
+               return *const_cast<numeric *>(_num8_p);
        case 9:
-               return const_cast<numeric &>(_num9);
+               return *const_cast<numeric *>(_num9_p);
        case 10:
-               return const_cast<numeric &>(_num10);
+               return *const_cast<numeric *>(_num10_p);
        case 11:
-               return const_cast<numeric &>(_num11);
+               return *const_cast<numeric *>(_num11_p);
        case 12:
-               return const_cast<numeric &>(_num12);
+               return *const_cast<numeric *>(_num12_p);
        default:
                basic *bp = new numeric(i);
                bp->setflag(status_flags::dynallocated);
-               GINAC_ASSERT(bp->refcount == 0);
+               GINAC_ASSERT(bp->get_refcount() == 0);
                return *bp;
        }
 }
@@ -368,35 +390,35 @@ basic & ex::construct_from_uint(unsigned int i)
 {
        switch (i) {  // prefer flyweights over new objects
        case 0:
-               return const_cast<numeric &>(_num0);
+               return *const_cast<numeric *>(_num0_p);
        case 1:
-               return const_cast<numeric &>(_num1);
+               return *const_cast<numeric *>(_num1_p);
        case 2:
-               return const_cast<numeric &>(_num2);
+               return *const_cast<numeric *>(_num2_p);
        case 3:
-               return const_cast<numeric &>(_num3);
+               return *const_cast<numeric *>(_num3_p);
        case 4:
-               return const_cast<numeric &>(_num4);
+               return *const_cast<numeric *>(_num4_p);
        case 5:
-               return const_cast<numeric &>(_num5);
+               return *const_cast<numeric *>(_num5_p);
        case 6:
-               return const_cast<numeric &>(_num6);
+               return *const_cast<numeric *>(_num6_p);
        case 7:
-               return const_cast<numeric &>(_num7);
+               return *const_cast<numeric *>(_num7_p);
        case 8:
-               return const_cast<numeric &>(_num8);
+               return *const_cast<numeric *>(_num8_p);
        case 9:
-               return const_cast<numeric &>(_num9);
+               return *const_cast<numeric *>(_num9_p);
        case 10:
-               return const_cast<numeric &>(_num10);
+               return *const_cast<numeric *>(_num10_p);
        case 11:
-               return const_cast<numeric &>(_num11);
+               return *const_cast<numeric *>(_num11_p);
        case 12:
-               return const_cast<numeric &>(_num12);
+               return *const_cast<numeric *>(_num12_p);
        default:
                basic *bp = new numeric(i);
                bp->setflag(status_flags::dynallocated);
-               GINAC_ASSERT(bp->refcount == 0);
+               GINAC_ASSERT(bp->get_refcount() == 0);
                return *bp;
        }
 }
@@ -405,59 +427,59 @@ basic & ex::construct_from_long(long i)
 {
        switch (i) {  // prefer flyweights over new objects
        case -12:
-               return const_cast<numeric &>(_num_12);
+               return *const_cast<numeric *>(_num_12_p);
        case -11:
-               return const_cast<numeric &>(_num_11);
+               return *const_cast<numeric *>(_num_11_p);
        case -10:
-               return const_cast<numeric &>(_num_10);
+               return *const_cast<numeric *>(_num_10_p);
        case -9:
-               return const_cast<numeric &>(_num_9);
+               return *const_cast<numeric *>(_num_9_p);
        case -8:
-               return const_cast<numeric &>(_num_8);
+               return *const_cast<numeric *>(_num_8_p);
        case -7:
-               return const_cast<numeric &>(_num_7);
+               return *const_cast<numeric *>(_num_7_p);
        case -6:
-               return const_cast<numeric &>(_num_6);
+               return *const_cast<numeric *>(_num_6_p);
        case -5:
-               return const_cast<numeric &>(_num_5);
+               return *const_cast<numeric *>(_num_5_p);
        case -4:
-               return const_cast<numeric &>(_num_4);
+               return *const_cast<numeric *>(_num_4_p);
        case -3:
-               return const_cast<numeric &>(_num_3);
+               return *const_cast<numeric *>(_num_3_p);
        case -2:
-               return const_cast<numeric &>(_num_2);
+               return *const_cast<numeric *>(_num_2_p);
        case -1:
-               return const_cast<numeric &>(_num_1);
+               return *const_cast<numeric *>(_num_1_p);
        case 0:
-               return const_cast<numeric &>(_num0);
+               return *const_cast<numeric *>(_num0_p);
        case 1:
-               return const_cast<numeric &>(_num1);
+               return *const_cast<numeric *>(_num1_p);
        case 2:
-               return const_cast<numeric &>(_num2);
+               return *const_cast<numeric *>(_num2_p);
        case 3:
-               return const_cast<numeric &>(_num3);
+               return *const_cast<numeric *>(_num3_p);
        case 4:
-               return const_cast<numeric &>(_num4);
+               return *const_cast<numeric *>(_num4_p);
        case 5:
-               return const_cast<numeric &>(_num5);
+               return *const_cast<numeric *>(_num5_p);
        case 6:
-               return const_cast<numeric &>(_num6);
+               return *const_cast<numeric *>(_num6_p);
        case 7:
-               return const_cast<numeric &>(_num7);
+               return *const_cast<numeric *>(_num7_p);
        case 8:
-               return const_cast<numeric &>(_num8);
+               return *const_cast<numeric *>(_num8_p);
        case 9:
-               return const_cast<numeric &>(_num9);
+               return *const_cast<numeric *>(_num9_p);
        case 10:
-               return const_cast<numeric &>(_num10);
+               return *const_cast<numeric *>(_num10_p);
        case 11:
-               return const_cast<numeric &>(_num11);
+               return *const_cast<numeric *>(_num11_p);
        case 12:
-               return const_cast<numeric &>(_num12);
+               return *const_cast<numeric *>(_num12_p);
        default:
                basic *bp = new numeric(i);
                bp->setflag(status_flags::dynallocated);
-               GINAC_ASSERT(bp->refcount == 0);
+               GINAC_ASSERT(bp->get_refcount() == 0);
                return *bp;
        }
 }
@@ -466,35 +488,35 @@ basic & ex::construct_from_ulong(unsigned long i)
 {
        switch (i) {  // prefer flyweights over new objects
        case 0:
-               return const_cast<numeric &>(_num0);
+               return *const_cast<numeric *>(_num0_p);
        case 1:
-               return const_cast<numeric &>(_num1);
+               return *const_cast<numeric *>(_num1_p);
        case 2:
-               return const_cast<numeric &>(_num2);
+               return *const_cast<numeric *>(_num2_p);
        case 3:
-               return const_cast<numeric &>(_num3);
+               return *const_cast<numeric *>(_num3_p);
        case 4:
-               return const_cast<numeric &>(_num4);
+               return *const_cast<numeric *>(_num4_p);
        case 5:
-               return const_cast<numeric &>(_num5);
+               return *const_cast<numeric *>(_num5_p);
        case 6:
-               return const_cast<numeric &>(_num6);
+               return *const_cast<numeric *>(_num6_p);
        case 7:
-               return const_cast<numeric &>(_num7);
+               return *const_cast<numeric *>(_num7_p);
        case 8:
-               return const_cast<numeric &>(_num8);
+               return *const_cast<numeric *>(_num8_p);
        case 9:
-               return const_cast<numeric &>(_num9);
+               return *const_cast<numeric *>(_num9_p);
        case 10:
-               return const_cast<numeric &>(_num10);
+               return *const_cast<numeric *>(_num10_p);
        case 11:
-               return const_cast<numeric &>(_num11);
+               return *const_cast<numeric *>(_num11_p);
        case 12:
-               return const_cast<numeric &>(_num12);
+               return *const_cast<numeric *>(_num12_p);
        default:
                basic *bp = new numeric(i);
                bp->setflag(status_flags::dynallocated);
-               GINAC_ASSERT(bp->refcount == 0);
+               GINAC_ASSERT(bp->get_refcount() == 0);
                return *bp;
        }
 }
@@ -503,7 +525,7 @@ basic & ex::construct_from_double(double d)
 {
        basic *bp = new numeric(d);
        bp->setflag(status_flags::dynallocated);
-       GINAC_ASSERT(bp->refcount == 0);
+       GINAC_ASSERT(bp->get_refcount() == 0);
        return *bp;
 }