From cbec8852eaab9a2a578d082698d29432ed43134d Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Thu, 10 Jun 2004 02:17:13 +0000 Subject: [PATCH] map() doesn't allocate a new object unless necessary --- ginac/basic.cpp | 25 ++++++++++++++++++------- ginac/idx.cpp | 15 ++++++++++----- ginac/power.cpp | 9 ++++++++- ginac/relational.cpp | 9 ++++++++- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 038cd7b5..b9689851 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -307,12 +307,23 @@ ex basic::map(map_function & f) const if (num == 0) return *this; - basic *copy = duplicate(); - copy->setflag(status_flags::dynallocated); - copy->clearflag(status_flags::hash_calculated | status_flags::expanded); - for (size_t i=0; ilet_op(i) = f(copy->op(i)); - return *copy; + basic *copy = NULL; + for (size_t i=0; ilet_op(i) = n; + } + } + + if (copy) { + copy->setflag(status_flags::dynallocated); + copy->clearflag(status_flags::hash_calculated | status_flags::expanded); + return *copy; + } else + return *this; } /** Return degree of highest power in object s. */ @@ -781,7 +792,7 @@ unsigned basic::calchash() const struct expand_map_function : public map_function { unsigned options; expand_map_function(unsigned o) : options(o) {} - ex operator()(const ex & e) { return expand(e, options); } + ex operator()(const ex & e) { return e.expand(options); } }; /** Expand expression, i.e. multiply it out and return the result as a new diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 1aba28bf..c95c07c7 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -242,11 +242,16 @@ ex idx::op(size_t i) const ex idx::map(map_function & f) const { - idx *copy = duplicate(); - copy->setflag(status_flags::dynallocated); - copy->clearflag(status_flags::hash_calculated); - copy->value = f(value); - return *copy; + const ex &mapped_value = f(value); + if (are_ex_trivially_equal(value, mapped_value)) + return *this; + else { + idx *copy = duplicate(); + copy->setflag(status_flags::dynallocated); + copy->clearflag(status_flags::hash_calculated); + copy->value = mapped_value; + return *copy; + } } /** Returns order relation between two indices of the same type. The order diff --git a/ginac/power.cpp b/ginac/power.cpp index aa0b082a..309d529a 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -246,7 +246,14 @@ ex power::op(size_t i) const ex power::map(map_function & f) const { - return (new power(f(basis), f(exponent)))->setflag(status_flags::dynallocated); + const ex &mapped_basis = f(basis); + const ex &mapped_exponent = f(exponent); + + if (!are_ex_trivially_equal(basis, mapped_basis) + || !are_ex_trivially_equal(exponent, mapped_exponent)) + return (new power(mapped_basis, mapped_exponent))->setflag(status_flags::dynallocated); + else + return *this; } int power::degree(const ex & s) const diff --git a/ginac/relational.cpp b/ginac/relational.cpp index 87acde42..86e2c2e8 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -164,7 +164,14 @@ ex relational::op(size_t i) const ex relational::map(map_function & f) const { - return (new relational(f(lh), f(rh), o))->setflag(status_flags::dynallocated); + const ex &mapped_lh = f(lh); + const ex &mapped_rh = f(rh); + + if (!are_ex_trivially_equal(lh, mapped_lh) + || !are_ex_trivially_equal(rh, mapped_rh)) + return (new relational(mapped_lh, mapped_rh, o))->setflag(status_flags::dynallocated); + else + return *this; } ex relational::eval(int level) const -- 2.49.0