+ GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+ bp.makewritable();
+ 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
+ * automatic evaluator and memory management are implemented.
+ * @see ex::ex(const basic &) */
+ptr<basic> ex::construct_from_basic(const basic & other)
+{
+ if (!(other.flags & status_flags::evaluated)) {
+
+ // The object is not yet evaluated, so call eval() to evaluate
+ // the top level. This will return either
+ // a) the original object with status_flags::evaluated set (when the
+ // eval() implementation calls hold())
+ // or
+ // b) a different expression.
+ //
+ // eval() returns an ex, not a basic&, so this will go through
+ // construct_from_basic() a second time. In case a) we end up in
+ // the "else" branch below. In case b) we end up here again and
+ // apply eval() once more. The recursion stops when eval() calls
+ // hold() or returns an object that already has its "evaluated"
+ // flag set, such as a symbol or a numeric.
+ const ex & tmpex = other.eval(1);
+
+ // Eventually, the eval() recursion goes through the "else" branch
+ // below, which assures that the object pointed to by tmpex.bp is
+ // allocated on the heap (either it was already on the heap or it
+ // is a heap-allocated duplicate of another object).
+ GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated);
+
+ // If the original object is not referenced but heap-allocated,
+ // 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.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
+ // soon as we leave the function, which would deallocate the
+ // evaluated object.
+ return tmpex.bp;
+
+ } else {
+
+ // The easy case: making an "ex" out of an evaluated object.
+ if (other.flags & status_flags::dynallocated) {
+
+ // The object is already heap-allocated, so we can just make
+ // another reference to it.
+ return ptr<basic>(const_cast<basic &>(other));
+
+ } else {
+
+ // The object is not heap-allocated, so we create a duplicate
+ // on the heap.
+ basic *bp = other.duplicate();
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return bp;
+ }
+ }
+}
+
+basic & ex::construct_from_int(int i)
+{
+ switch (i) { // prefer flyweights over new objects
+ case -12:
+ return *const_cast<numeric *>(_num_12_p);
+ case -11:
+ return *const_cast<numeric *>(_num_11_p);
+ case -10:
+ return *const_cast<numeric *>(_num_10_p);
+ case -9:
+ return *const_cast<numeric *>(_num_9_p);
+ case -8:
+ return *const_cast<numeric *>(_num_8_p);
+ case -7:
+ return *const_cast<numeric *>(_num_7_p);
+ case -6:
+ return *const_cast<numeric *>(_num_6_p);
+ case -5:
+ return *const_cast<numeric *>(_num_5_p);
+ case -4:
+ return *const_cast<numeric *>(_num_4_p);
+ case -3:
+ return *const_cast<numeric *>(_num_3_p);
+ case -2:
+ return *const_cast<numeric *>(_num_2_p);
+ case -1:
+ return *const_cast<numeric *>(_num_1_p);
+ case 0:
+ return *const_cast<numeric *>(_num0_p);
+ case 1:
+ return *const_cast<numeric *>(_num1_p);
+ case 2:
+ return *const_cast<numeric *>(_num2_p);
+ case 3:
+ return *const_cast<numeric *>(_num3_p);
+ case 4:
+ return *const_cast<numeric *>(_num4_p);
+ case 5:
+ return *const_cast<numeric *>(_num5_p);
+ case 6:
+ return *const_cast<numeric *>(_num6_p);
+ case 7:
+ return *const_cast<numeric *>(_num7_p);
+ case 8:
+ return *const_cast<numeric *>(_num8_p);
+ case 9:
+ return *const_cast<numeric *>(_num9_p);
+ case 10:
+ return *const_cast<numeric *>(_num10_p);
+ case 11:
+ return *const_cast<numeric *>(_num11_p);
+ case 12:
+ return *const_cast<numeric *>(_num12_p);
+ default:
+ basic *bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return *bp;
+ }
+}
+
+basic & ex::construct_from_uint(unsigned int i)
+{
+ switch (i) { // prefer flyweights over new objects
+ case 0:
+ return *const_cast<numeric *>(_num0_p);
+ case 1:
+ return *const_cast<numeric *>(_num1_p);
+ case 2:
+ return *const_cast<numeric *>(_num2_p);
+ case 3:
+ return *const_cast<numeric *>(_num3_p);
+ case 4:
+ return *const_cast<numeric *>(_num4_p);
+ case 5:
+ return *const_cast<numeric *>(_num5_p);
+ case 6:
+ return *const_cast<numeric *>(_num6_p);
+ case 7:
+ return *const_cast<numeric *>(_num7_p);
+ case 8:
+ return *const_cast<numeric *>(_num8_p);
+ case 9:
+ return *const_cast<numeric *>(_num9_p);
+ case 10:
+ return *const_cast<numeric *>(_num10_p);
+ case 11:
+ return *const_cast<numeric *>(_num11_p);
+ case 12:
+ return *const_cast<numeric *>(_num12_p);
+ default:
+ basic *bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return *bp;
+ }
+}
+
+basic & ex::construct_from_long(long i)
+{
+ switch (i) { // prefer flyweights over new objects
+ case -12:
+ return *const_cast<numeric *>(_num_12_p);
+ case -11:
+ return *const_cast<numeric *>(_num_11_p);
+ case -10:
+ return *const_cast<numeric *>(_num_10_p);
+ case -9:
+ return *const_cast<numeric *>(_num_9_p);
+ case -8:
+ return *const_cast<numeric *>(_num_8_p);
+ case -7:
+ return *const_cast<numeric *>(_num_7_p);
+ case -6:
+ return *const_cast<numeric *>(_num_6_p);
+ case -5:
+ return *const_cast<numeric *>(_num_5_p);
+ case -4:
+ return *const_cast<numeric *>(_num_4_p);
+ case -3:
+ return *const_cast<numeric *>(_num_3_p);
+ case -2:
+ return *const_cast<numeric *>(_num_2_p);
+ case -1:
+ return *const_cast<numeric *>(_num_1_p);
+ case 0:
+ return *const_cast<numeric *>(_num0_p);
+ case 1:
+ return *const_cast<numeric *>(_num1_p);
+ case 2:
+ return *const_cast<numeric *>(_num2_p);
+ case 3:
+ return *const_cast<numeric *>(_num3_p);
+ case 4:
+ return *const_cast<numeric *>(_num4_p);
+ case 5:
+ return *const_cast<numeric *>(_num5_p);
+ case 6:
+ return *const_cast<numeric *>(_num6_p);
+ case 7:
+ return *const_cast<numeric *>(_num7_p);
+ case 8:
+ return *const_cast<numeric *>(_num8_p);
+ case 9:
+ return *const_cast<numeric *>(_num9_p);
+ case 10:
+ return *const_cast<numeric *>(_num10_p);
+ case 11:
+ return *const_cast<numeric *>(_num11_p);
+ case 12:
+ return *const_cast<numeric *>(_num12_p);
+ default:
+ basic *bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return *bp;
+ }
+}
+
+basic & ex::construct_from_ulong(unsigned long i)
+{
+ switch (i) { // prefer flyweights over new objects
+ case 0:
+ return *const_cast<numeric *>(_num0_p);
+ case 1:
+ return *const_cast<numeric *>(_num1_p);
+ case 2:
+ return *const_cast<numeric *>(_num2_p);
+ case 3:
+ return *const_cast<numeric *>(_num3_p);
+ case 4:
+ return *const_cast<numeric *>(_num4_p);
+ case 5:
+ return *const_cast<numeric *>(_num5_p);
+ case 6:
+ return *const_cast<numeric *>(_num6_p);
+ case 7:
+ return *const_cast<numeric *>(_num7_p);
+ case 8:
+ return *const_cast<numeric *>(_num8_p);
+ case 9:
+ return *const_cast<numeric *>(_num9_p);
+ case 10:
+ return *const_cast<numeric *>(_num10_p);
+ case 11:
+ return *const_cast<numeric *>(_num11_p);
+ case 12:
+ return *const_cast<numeric *>(_num12_p);
+ default:
+ basic *bp = new numeric(i);
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return *bp;
+ }
+}
+
+basic & ex::construct_from_double(double d)
+{
+ basic *bp = new numeric(d);
+ bp->setflag(status_flags::dynallocated);
+ GINAC_ASSERT(bp->get_refcount() == 0);
+ return *bp;