]> www.ginac.de Git - ginac.git/commitdiff
lst now provides (read-only) iterator types, the use of which makes iterating
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 19 May 2003 18:21:43 +0000 (18:21 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 19 May 2003 18:21:43 +0000 (18:21 +0000)
over the elements of a lst an operation of order O(N), instead of O(N^2) when
using nops()/op(); this should speed up subs()

16 files changed:
NEWS
configure.ac
doc/tutorial/ginac.texi
ginac/basic.cpp
ginac/clifford.cpp
ginac/container.pl
ginac/expairseq.cpp
ginac/idx.cpp
ginac/indexed.cpp
ginac/matrix.cpp
ginac/mul.cpp
ginac/ncmul.cpp
ginac/normal.cpp
ginac/power.cpp
ginac/symbol.cpp
ginac/symmetry.cpp

diff --git a/NEWS b/NEWS
index 34b333b65049a5de74236336722c4f82482e21b5..59ba650a1b4610730059d8db049d27b6032888ab 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
 This file records noteworthy changes.
 
+1.1.1 (<date>)
+* lst (and exprseq) provide iterators for read-only element access. For
+  sequential access this is one order faster than using op().
+
 1.1.0 (3 April 2003)
 * Removed deprecated macros is_ex_a, is_ex_exactly_a and friends for good.
 * The scalar_products mechanism allows the specification of an index dimension.
index 46d636ef4641c05a731f34372eb640c67160022d..763348d0827b4ef0f19e56e0f3cb4871d732bb59 100644 (file)
@@ -20,7 +20,7 @@ dnl (don't we all *love* M4?)...
 
 GINACLIB_MAJOR_VERSION=1
 GINACLIB_MINOR_VERSION=1
-GINACLIB_MICRO_VERSION=0
+GINACLIB_MICRO_VERSION=1
 GINACLIB_INTERFACE_AGE=0
 GINACLIB_BINARY_AGE=0
 GINACLIB_VERSION=$GINACLIB_MAJOR_VERSION.$GINACLIB_MINOR_VERSION.$GINACLIB_MICRO_VERSION
index 04cedf4392f8089f1703498421ac49c812bbb685..358ea9115ebb865ba5ef94603b3fbb03a729485c 100644 (file)
@@ -1304,6 +1304,51 @@ individual elements:
     ...
 @end example
 
+As with the standard @code{list<T>} container, accessing random elements of a
+@code{lst} is generally an operation of order @math{O(N)}. Faster read-only
+sequential access to the elements of a list is possible with the
+iterator types provided by the @code{lst} class:
+
+@example
+typedef ... lst::const_iterator;
+typedef ... lst::const_reverse_iterator;
+lst::const_iterator lst::begin() const;
+lst::const_iterator lst::end() const;
+lst::const_reverse_iterator lst::rbegin() const;
+lst::const_reverse_iterator lst::rend() const;
+@end example
+
+For example, to print the elements of a list individually you can use:
+
+@example
+    ...
+    // O(N)
+    for (lst::const_iterator i = l.begin(); i != l.end(); ++i)
+        cout << *i << endl;
+    ...
+@end example
+
+which is one order faster than
+
+@example
+    ...
+    // O(N^2)
+    for (size_t i = 0; i < l.nops(); ++i)
+        cout << l.op(i) << endl;
+    ...
+@end example
+
+These iterators also allow you to use some of the algorithms provided by
+the C++ standard library:
+
+@example
+    ...
+    // sum up the elements of the list (requires #include <numeric>)
+    ex sum = accumulate(l.begin(), l.end(), ex(0));
+    cout << sum << endl;  // prints '2+2*x+2*y'
+    ...
+@end example
+
 @code{lst} is one of the few GiNaC classes that allow in-place modifications
 (the only other one is @code{matrix}). You can modify single elements:
 
index 85294cac3a30fe32cc3f200307856e419e27a973..6fb3952ffa4ae720d21da7d8f125b8f7233cfbfb 100644 (file)
@@ -484,9 +484,9 @@ bool basic::match(const ex & pattern, lst & repl_lst) const
                // Wildcard matches anything, but check whether we already have found
                // a match for that wildcard first (if so, it the earlier match must
                // be the same expression)
-               for (size_t i=0; i<repl_lst.nops(); i++) {
-                       if (repl_lst.op(i).op(0).is_equal(pattern))
-                               return is_equal(ex_to<basic>(repl_lst.op(i).op(1)));
+               for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
+                       if (it->op(0).is_equal(pattern))
+                               return is_equal(ex_to<basic>(it->op(1)));
                }
                repl_lst.append(pattern == *this);
                return true;
@@ -526,16 +526,18 @@ ex basic::subs(const lst & ls, const lst & lr, unsigned options) const
 {
        GINAC_ASSERT(ls.nops() == lr.nops());
 
+       lst::const_iterator its, itr;
+
        if (options & subs_options::subs_no_pattern) {
-               for (size_t i=0; i<ls.nops(); i++) {
-                       if (is_equal(ex_to<basic>(ls.op(i))))
-                               return lr.op(i);
+               for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
+                       if (is_equal(ex_to<basic>(*its)))
+                               return *itr;
                }
        } else {
-               for (size_t i=0; i<ls.nops(); i++) {
+               for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
                        lst repl_lst;
-                       if (match(ex_to<basic>(ls.op(i)), repl_lst))
-                               return lr.op(i).subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards
+                       if (match(ex_to<basic>(*its), repl_lst))
+                               return itr->subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards
                }
        }
 
@@ -711,10 +713,13 @@ ex basic::subs(const ex & e, unsigned options) const
        if (!e.info(info_flags::list)) {
                throw(std::invalid_argument("basic::subs(ex): argument must be a list"));
        }
+
+       // Split list into two
        lst ls;
        lst lr;
-       for (size_t i=0; i<e.nops(); i++) {
-               ex r = e.op(i);
+       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"));
                }
index a8b87343ba838f7cdfca4568d941e863d266eec6..8ea924b17d17288792712bfa9c65ca446ad52729 100644 (file)
@@ -695,8 +695,9 @@ ex canonicalize_clifford(const ex & e)
        ex aux = e.to_rational(srl);
        for (size_t i=0; i<srl.nops(); i++) {
 
-               ex lhs = srl.op(i).lhs();
-               ex rhs = srl.op(i).rhs();
+               ex o = srl.op(i);
+               ex lhs = o.lhs();
+               ex rhs = o.rhs();
 
                if (is_exactly_a<ncmul>(rhs)
                 && rhs.return_type() == return_types::noncommutative
index 7dcd0be68fd6449f38c752bfc32fef5735fbbf8a..66bef262aa4027f88219994f817e8a270e67ca78 100755 (executable)
@@ -244,6 +244,10 @@ class ${CONTAINER} : public basic
 {
        GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic)
 
+public:
+       typedef ${STLT}::const_iterator const_iterator;
+       typedef ${STLT}::const_reverse_iterator const_reverse_iterator;
+
 public:
        ${CONTAINER}(${STLT} const & s, bool discardable = false);
        ${CONTAINER}(${STLT} * vp); // vp will be deleted
@@ -276,6 +280,13 @@ protected:
        virtual ex this${CONTAINER}(${STLT} const & v) const;
        virtual ex this${CONTAINER}(${STLT} * vp) const;
 
+       // non-virtual functions in this class
+public:
+       const_iterator begin() const {return seq.begin();}
+       const_iterator end() const {return seq.end();}
+       const_reverse_iterator rbegin() const {return seq.rbegin();}
+       const_reverse_iterator rend() const {return seq.rend();}
+
 protected:
        bool is_canonical() const;
        ${STLT} evalchildren(int level) const;
index c41c694b82e3c3ed10f5458e62782abf56e33391..041994af27892fc20f9669d177f450a0192c44c3 100644 (file)
@@ -379,9 +379,9 @@ found:              ;
                        for (size_t i=0; i<num; i++)
                                vp->push_back(split_ex_to_pair(ops[i]));
                        ex rest = thisexpairseq(vp, default_overall_coeff());
-                       for (size_t i=0; i<repl_lst.nops(); i++) {
-                               if (repl_lst.op(i).op(0).is_equal(global_wildcard))
-                                       return rest.is_equal(repl_lst.op(i).op(1));
+                       for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
+                               if (it->op(0).is_equal(global_wildcard))
+                                       return rest.is_equal(it->op(1));
                        }
                        repl_lst.append(global_wildcard == rest);
                        return true;
@@ -1564,8 +1564,8 @@ epvector * expairseq::subschildren(const lst &ls, const lst &lr, unsigned option
        // is a product or power. In this case we have to recombine the pairs
        // because the numeric coefficients may be part of the search pattern.
        bool complex_subs = false;
-       for (size_t i=0; i<ls.nops(); ++i) {
-               if (is_exactly_a<mul>(ls.op(i)) || is_exactly_a<power>(ls.op(i))) {
+       for (lst::const_iterator it = ls.begin(); it != ls.end(); ++it) {
+               if (is_exactly_a<mul>(*it) || is_exactly_a<power>(*it)) {
                        complex_subs = true;
                        break;
                }
index 55475568bb12b58e9f077f461b929892c46d96a3..35952871213136d76f20adfd033cdea757031ff4 100644 (file)
@@ -376,16 +376,17 @@ ex idx::subs(const lst & ls, const lst & lr, unsigned options) const
        GINAC_ASSERT(ls.nops() == lr.nops());
 
        // First look for index substitutions
-       for (size_t i=0; i<ls.nops(); i++) {
-               if (is_equal(ex_to<basic>(ls.op(i)))) {
+       lst::const_iterator its, itr;
+       for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
+               if (is_equal(ex_to<basic>(*its))) {
 
                        // Substitution index->index
-                       if (is_a<idx>(lr.op(i)))
-                               return lr.op(i);
+                       if (is_a<idx>(*itr))
+                               return *itr;
 
                        // Otherwise substitute value
                        idx *i_copy = static_cast<idx *>(duplicate());
-                       i_copy->value = lr.op(i);
+                       i_copy->value = *itr;
                        i_copy->clearflag(status_flags::hash_calculated);
                        return i_copy->setflag(status_flags::dynallocated);
                }
index 695768f69ddb825d0fed921873183d0a0fcc1742..de2e8c96d3de8c8b4fb8e1d3d9d90c6f199528f2 100644 (file)
@@ -1224,14 +1224,9 @@ void scalar_products::add(const ex & v1, const ex & v2, const ex & dim, const ex
 void scalar_products::add_vectors(const lst & l, const ex & dim)
 {
        // Add all possible pairs of products
-       size_t num = l.nops();
-       for (size_t i=0; i<num; i++) {
-               ex a = l.op(i);
-               for (size_t j=0; j<num; j++) {
-                       ex b = l.op(j);
-                       add(a, b, dim, a*b);
-               }
-       }
+       for (lst::const_iterator it1 = l.begin(); it1 != l.end(); ++it1)
+               for (lst::const_iterator it2 = l.begin(); it2 != l.end(); ++it2)
+                       add(*it1, *it2, *it1 * *it2);
 }
 
 void scalar_products::clear(void)
index df1b4c9178f62565c7d7fc03f21d9a1552917cfa..109304fe30416ea5861ab08d992847224cc1e174 100644 (file)
@@ -32,6 +32,7 @@
 #include "lst.h"
 #include "idx.h"
 #include "indexed.h"
+#include "add.h"
 #include "power.h"
 #include "symbol.h"
 #include "operators.h"
@@ -95,12 +96,13 @@ matrix::matrix(unsigned r, unsigned c, const lst & l)
 {
        m.resize(r*c, _ex0);
 
-       for (size_t i=0; i<l.nops(); i++) {
+       size_t i = 0;
+       for (lst::const_iterator it = l.begin(); it != l.end(); ++it, ++i) {
                size_t x = i % c;
                size_t y = i / c;
                if (y >= r)
                        break; // matrix smaller than list: throw away excessive elements
-               m[y*c+x] = l.op(i);
+               m[y*c+x] = *it;
        }
 }
 
@@ -880,6 +882,7 @@ ex matrix::charpoly(const symbol & lambda) const
        // trapped and we use Leverrier's algorithm which goes as row^3 for
        // every coefficient.  The expensive part is the matrix multiplication.
        if (numeric_flag) {
+
                matrix B(*this);
                ex c = B.trace();
                ex poly = power(lambda,row)-c*power(lambda,row-1);
@@ -887,20 +890,22 @@ ex matrix::charpoly(const symbol & lambda) const
                        for (unsigned j=0; j<row; ++j)
                                B.m[j*col+j] -= c;
                        B = this->mul(B);
-                       c = B.trace()/ex(i+1);
+                       c = B.trace() / ex(i+1);
                        poly -= c*power(lambda,row-i-1);
                }
                if (row%2)
                        return -poly;
                else
                        return poly;
-       }
+
+       } else {
        
-       matrix M(*this);
-       for (unsigned r=0; r<col; ++r)
-               M.m[r*col+r] -= lambda;
+               matrix M(*this);
+               for (unsigned r=0; r<col; ++r)
+                       M.m[r*col+r] -= lambda;
        
-       return M.determinant().collect(lambda);
+               return M.determinant().collect(lambda);
+       }
 }
 
 
@@ -1452,34 +1457,45 @@ int matrix::pivot(unsigned ro, unsigned co, bool symbolic)
 
 ex lst_to_matrix(const lst & l)
 {
+       lst::const_iterator itr, itc;
+
        // Find number of rows and columns
-       size_t rows = l.nops(), cols = 0, i, j;
-       for (i=0; i<rows; i++)
-               if (l.op(i).nops() > cols)
-                       cols = l.op(i).nops();
+       size_t rows = l.nops(), cols = 0;
+       for (itr = l.begin(); itr != l.end(); ++itr) {
+               if (!is_a<lst>(*itr))
+                       throw (std::invalid_argument("lst_to_matrix: argument must be a list of lists"));
+               if (itr->nops() > cols)
+                       cols = itr->nops();
+       }
 
        // Allocate and fill matrix
        matrix &M = *new matrix(rows, cols);
        M.setflag(status_flags::dynallocated);
-       for (i=0; i<rows; i++)
-               for (j=0; j<cols; j++)
-                       if (l.op(i).nops() > j)
-                               M(i, j) = l.op(i).op(j);
-                       else
-                               M(i, j) = _ex0;
+
+       unsigned i;
+       for (itr = l.begin(), i = 0; itr != l.end(); ++itr, ++i) {
+               unsigned j;
+               for (itc = ex_to<lst>(*itr).begin(), j = 0; itc != ex_to<lst>(*itr).end(); ++itc, ++j)
+                       M(i, j) = *itc;
+       }
+
        return M;
 }
 
 ex diag_matrix(const lst & l)
 {
+       lst::const_iterator it;
        size_t dim = l.nops();
 
-       matrix &m = *new matrix(dim, dim);
-       m.setflag(status_flags::dynallocated);
-       for (size_t i=0; i<dim; i++)
-               m(i, i) = l.op(i);
+       // Allocate and fill matrix
+       matrix &M = *new matrix(dim, dim);
+       M.setflag(status_flags::dynallocated);
 
-       return m;
+       unsigned i;
+       for (it = l.begin(), i = 0; it != l.end(); ++it, ++i)
+               M(i, i) = *it;
+
+       return M;
 }
 
 ex unit_matrix(unsigned r, unsigned c)
index 96521c7c0ec04680cbdd3945fd478a09c2b93a09..ede10a7c366ea1a978782ee3cb0b0058b3551aba 100644 (file)
@@ -566,21 +566,22 @@ ex mul::algebraic_subs_mul(const lst & ls, const lst & lr, unsigned options) con
        std::vector<bool> subsed(seq.size(), false);
        exvector subsresult(seq.size());
 
-       for (size_t i=0; i<ls.nops(); i++) {
+       lst::const_iterator its, itr;
+       for (its = ls.begin(), itr != lr.begin(); its != ls.end(); ++its, ++itr) {
 
-               if (is_exactly_a<mul>(ls.op(i))) {
+               if (is_exactly_a<mul>(*its)) {
 
                        int nummatches = std::numeric_limits<int>::max();
                        std::vector<bool> currsubsed(seq.size(), false);
                        bool succeed = true;
                        lst repls;
 
-                       for (size_t j=0; j<ls.op(i).nops(); j++) {
+                       for (size_t j=0; j<its->nops(); j++) {
                                bool found=false;
                                for (size_t k=0; k<nops(); k++) {
                                        if (currsubsed[k] || subsed[k])
                                                continue;
-                                       if (tryfactsubs(op(k), ls.op(i).op(j), nummatches, repls)) {
+                                       if (tryfactsubs(op(k), its->op(j), nummatches, repls)) {
                                                currsubsed[k] = true;
                                                found = true;
                                                break;
@@ -601,7 +602,7 @@ ex mul::algebraic_subs_mul(const lst & ls, const lst & lr, unsigned options) con
                                                subsresult[j] = op(j);
                                        else {
                                                foundfirstsubsedfactor = true;
-                                               subsresult[j] = op(j) * power(lr.op(i).subs(ex(repls), subs_options::subs_no_pattern) / ls.op(i).subs(ex(repls), subs_options::subs_no_pattern), nummatches);
+                                               subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches);
                                        }
                                        subsed[j] = true;
                                }
@@ -613,9 +614,9 @@ ex mul::algebraic_subs_mul(const lst & ls, const lst & lr, unsigned options) con
                        lst repls;
 
                        for (size_t j=0; j<this->nops(); j++) {
-                               if (!subsed[j] && tryfactsubs(op(j), ls.op(i), nummatches, repls)) {
+                               if (!subsed[j] && tryfactsubs(op(j), *its, nummatches, repls)) {
                                        subsed[j] = true;
-                                       subsresult[j] = op(j) * power(lr.op(i).subs(ex(repls), subs_options::subs_no_pattern) / ls.op(i).subs(ex(repls), subs_options::subs_no_pattern), nummatches);
+                                       subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches);
                                }
                        }
                }
index b0fbb93d722ff7afe75d6ea943dcdbfe3a2c6963..110afa0de980e2d96d6c09b11f6a70275ec78ae5 100644 (file)
@@ -269,7 +269,7 @@ void ncmul::append_factors(exvector & v, const ex & e) const
        if ((is_exactly_a<mul>(e)&&(e.return_type()!=return_types::commutative))||
                (is_exactly_a<ncmul>(e))) {
                for (size_t i=0; i<e.nops(); i++)
-                       append_factors(v,e.op(i));
+                       append_factors(v, e.op(i));
        } else 
                v.push_back(e);
 }
index 297a052b61ea6db2a6a2166af89626159f5d3f4a..fad5a9d4257176b52bb4977010484de1bfb635e0 100644 (file)
@@ -1689,9 +1689,10 @@ ex sqrfree_parfrac(const ex & a, const symbol & x)
 static ex replace_with_symbol(const ex &e, lst &sym_lst, lst &repl_lst)
 {
        // Expression already in repl_lst? Then return the assigned symbol
-       for (size_t i=0; i<repl_lst.nops(); i++)
-               if (repl_lst.op(i).is_equal(e))
-                       return sym_lst.op(i);
+       lst::const_iterator its, itr;
+       for (its = sym_lst.begin(), itr = repl_lst.begin(); itr != repl_lst.end(); ++its, ++itr)
+               if (itr->is_equal(e))
+                       return *its;
        
        // Otherwise create new symbol and add to list, taking care that the
        // replacement expression doesn't contain symbols from the sym_lst
@@ -1712,9 +1713,9 @@ static ex replace_with_symbol(const ex &e, lst &sym_lst, lst &repl_lst)
 static ex replace_with_symbol(const ex &e, lst &repl_lst)
 {
        // Expression already in repl_lst? Then return the assigned symbol
-       for (size_t i=0; i<repl_lst.nops(); i++)
-               if (repl_lst.op(i).op(1).is_equal(e))
-                       return repl_lst.op(i).op(0);
+       for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it)
+               if (it->op(1).is_equal(e))
+                       return it->op(0);
        
        // Otherwise create new symbol and add to list, taking care that the
        // replacement expression doesn't contain symbols from the sym_lst
index 07a52ebeefbde2d82266dd42eb05b04b817db1b1..2cae8a88f4a2e4c867a25c4775bbfc677e5dfbf6 100644 (file)
@@ -524,6 +524,7 @@ ex power::evalm(void) const
        return (new power(ebasis, eexponent))->setflag(status_flags::dynallocated);
 }
 
+// from mul.cpp
 extern bool tryfactsubs(const ex &, const ex &, int &, lst &);
 
 ex power::subs(const lst & ls, const lst & lr, unsigned options) const
@@ -538,11 +539,12 @@ ex power::subs(const lst & ls, const lst & lr, unsigned options) const
        if(!(options & subs_options::subs_algebraic))
                return basic::subs(ls, lr, options);
 
-       for (size_t i=0; i<ls.nops(); i++) {
+       lst::const_iterator its, itr;
+       for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
                int nummatches = std::numeric_limits<int>::max();
                lst repls;
-               if (tryfactsubs(*this, ls.op(i), nummatches, repls))
-                       return (ex_to<basic>((*this) * power(lr.op(i).subs(ex(repls), subs_options::subs_no_pattern) / ls.op(i).subs(ex(repls), subs_options::subs_no_pattern), nummatches))).basic::subs(ls, lr, options);
+               if (tryfactsubs(*this, *its, nummatches, repls))
+                       return (ex_to<basic>((*this) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches))).basic::subs(ls, lr, options);
        }
 
        ex result=basic::subs(ls, lr, options);
index 43e3684cee97d1b645bd643aae02700d260292a4..062a28909b3f5122c59ffe8b38ecc9c89ec3075f 100644 (file)
@@ -110,9 +110,9 @@ ex symbol::unarchive(const archive_node &n, lst &sym_lst)
        ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated);
 
        // If symbol is in sym_lst, return the existing symbol
-       for (size_t i=0; i<sym_lst.nops(); i++) {
-               if (is_a<symbol>(sym_lst.op(i)) && (ex_to<symbol>(sym_lst.op(i)).name == ex_to<symbol>(s).name))
-                       return sym_lst.op(i);
+       for (lst::const_iterator it = sym_lst.begin(); it != sym_lst.end(); ++it) {
+               if (is_a<symbol>(*it) && (ex_to<symbol>(*it).name == ex_to<symbol>(s).name))
+                       return *it;
        }
 
        // Otherwise add new symbol to list and return it
index 2058a27974fa4a155a7e553e84fc2af317113b47..7934d6734234c626fb3bcac6493a4bb46982aca0 100644 (file)
@@ -426,20 +426,14 @@ ex symmetrize_cyclic(const ex & e, exvector::const_iterator first, exvector::con
 /** Symmetrize expression over a list of objects (symbols, indices). */
 ex ex::symmetrize(const lst & l) const
 {
-       exvector v;
-       v.reserve(l.nops());
-       for (size_t i=0; i<l.nops(); i++)
-               v.push_back(l.op(i));
+       exvector v(l.begin(), l.end());
        return symm(*this, v.begin(), v.end(), false);
 }
 
 /** Antisymmetrize expression over a list of objects (symbols, indices). */
 ex ex::antisymmetrize(const lst & l) const
 {
-       exvector v;
-       v.reserve(l.nops());
-       for (size_t i=0; i<l.nops(); i++)
-               v.push_back(l.op(i));
+       exvector v(l.begin(), l.end());
        return symm(*this, v.begin(), v.end(), true);
 }
 
@@ -447,10 +441,7 @@ ex ex::antisymmetrize(const lst & l) const
  *  (symbols, indices). */
 ex ex::symmetrize_cyclic(const lst & l) const
 {
-       exvector v;
-       v.reserve(l.nops());
-       for (size_t i=0; i<l.nops(); i++)
-               v.push_back(l.op(i));
+       exvector v(l.begin(), l.end());
        return GiNaC::symmetrize_cyclic(*this, v.begin(), v.end());
 }