/** @file utils_multi_iterator.h * * Utilities for summing over multiple indices */ /* * GiNaC Copyright (C) 1999-2021 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GINAC_UTILS_MULTI_ITERATOR_H #define GINAC_UTILS_MULTI_ITERATOR_H #include #include #include #include namespace GiNaC { /** * * SFINAE test for distance * */ template class has_distance { private: typedef char yes_type[1]; typedef char no_type[2]; template static yes_type & test( decltype(std::distance) ) ; template static no_type & test(...); public: enum { value = sizeof(test(0)) == sizeof(yes_type) }; }; /** * * For printing a multi-index: * If the templates are used, where T is an iterator, printing the address where the iterator points to is not meaningful. * However, we may print the difference to the starting point. * */ template typename std::enable_if::value, typename std::iterator_traits::difference_type>::type format_index_value(const T & a, const T & b) { return std::distance(a,b); } /** * * For all other cases we simply print the value. * */ template typename std::enable_if::value, T>::type format_index_value(const T & a, const T & b) { return b; } /** * * basic_multi_iterator is a base class. * * The base class itself does not do anything useful. * A typical use of a class derived from basic_multi_iterator is * * multi_iterator_ordered k(0,4,2); * * for( k.init(); !k.overflow(); k++) { * std::cout << k << std::endl; * } * * which prints out * * multi_iterator_ordered(0,1) * multi_iterator_ordered(0,2) * multi_iterator_ordered(0,3) * multi_iterator_ordered(1,2) * multi_iterator_ordered(1,3) * multi_iterator_ordered(2,3) * * Individual components of k can be accessed with k[i] or k(i). * * All classes derived from basic_multi_iterator follow the same syntax. * */ template class basic_multi_iterator { // ctors public : basic_multi_iterator(void); explicit basic_multi_iterator(T B, T N, size_t k); explicit basic_multi_iterator(T B, T N, const std::vector & vv); // dtor virtual ~basic_multi_iterator(); // functions public : size_t size(void) const; bool overflow(void) const; const std::vector & get_vector(void) const; // subscripting public : T operator[](size_t i) const; T & operator[](size_t i); T operator()(size_t i) const; T & operator()(size_t i); // virtual functions public : // initialization virtual basic_multi_iterator & init(void); // postfix increment virtual basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const basic_multi_iterator & v); // member variables : protected : T N; T B; std::vector v; bool flag_overflow; }; /** * * The class multi_iterator_ordered defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, such that * \f[ * B \le i_j < N * \f] * and * \f[ * i_j < i_{j+1}. * \f] * It is assumed that \f$k>0\f$ and \f$ N-B \ge k \f$. * */ template class multi_iterator_ordered : public basic_multi_iterator { // ctors public : multi_iterator_ordered(void); explicit multi_iterator_ordered(T B, T N, size_t k); explicit multi_iterator_ordered(T B, T N, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered & v); }; /** * * The class multi_iterator_ordered_eq defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, such that * \f[ * B \le i_j < N * \f] * and * \f[ * i_j \le i_{j+1}. * \f] * It is assumed that \f$k>0\f$. * */ template class multi_iterator_ordered_eq : public basic_multi_iterator { // ctors public : multi_iterator_ordered_eq(void); explicit multi_iterator_ordered_eq(T B, T N, size_t k); explicit multi_iterator_ordered_eq(T B, T N, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq & v); }; /** * * The class multi_iterator_ordered_eq_indv defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, such that * \f[ * B \le i_j < N_j * \f] * and * \f[ * i_j \le i_{j+1}. * \f] * */ template class multi_iterator_ordered_eq_indv : public basic_multi_iterator { // ctors public : multi_iterator_ordered_eq_indv(void); explicit multi_iterator_ordered_eq_indv(T B, const std::vector & Nv, size_t k); explicit multi_iterator_ordered_eq_indv(T B, const std::vector & Nv, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq_indv & v); // member variables : protected : std::vector Nv; }; /** * * The class multi_iterator_counter defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, such that * \f[ * B \le i_j < N * \f] * */ template class multi_iterator_counter : public basic_multi_iterator { // ctors public : multi_iterator_counter(void); explicit multi_iterator_counter(T B, T N, size_t k); explicit multi_iterator_counter(T B, T N, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_counter & v); }; /** * * The class multi_iterator_counter_indv defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, such that * \f[ * B \le i_j < N_j * \f] * */ template class multi_iterator_counter_indv : public basic_multi_iterator { // ctors public : multi_iterator_counter_indv(void); explicit multi_iterator_counter_indv(T B, const std::vector & Nv, size_t k); explicit multi_iterator_counter_indv(T B, const std::vector & Nv, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_counter_indv & v); // member variables : protected : std::vector Nv; }; /** * * The class multi_iterator_permutation defines a multi_iterator * \f$(i_1,i_2,...,i_k)\f$, for which * \f[ * B \le i_j < N * \f] * and * \f[ * i_i \neq i_j * \f] * In particular, if \f$N-B=k\f$, multi_iterator_permutation loops over all * permutations of \f$k\f$ elements. * */ template class multi_iterator_permutation : public basic_multi_iterator { // ctors public : multi_iterator_permutation(void); explicit multi_iterator_permutation(T B, T N, size_t k); explicit multi_iterator_permutation(T B, T N, const std::vector & vv); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // new functions in this class int get_sign(void) const; // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_permutation & v); }; /** * * The class multi_iterator_shuffle defines a multi_iterator, * which runs over all shuffles of a and b. * */ template class multi_iterator_shuffle : public basic_multi_iterator { // ctors public : multi_iterator_shuffle(void); explicit multi_iterator_shuffle(const std::vector & a, const std::vector & b); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // postfix increment basic_multi_iterator & operator++ (int); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle & v); // member variables : protected : size_t N_internal; std::vector v_internal; std::vector v_orig; }; /** * * The class multi_iterator_shuffle_prime defines a multi_iterator, * which runs over all shuffles of a and b, excluding the first one (a,b). * */ template class multi_iterator_shuffle_prime : public multi_iterator_shuffle { // ctors public : multi_iterator_shuffle_prime(void); explicit multi_iterator_shuffle_prime(const std::vector & a, const std::vector & b); // overriding virtual functions from base class public : // initialization basic_multi_iterator & init(void); // I/O operators template friend std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle_prime & v); }; // ---------------------------------------------------------------------------------------------------------------- // ctors /** * * Default constructor * */ template inline basic_multi_iterator::basic_multi_iterator(void) : N(), B(), v(), flag_overflow(false) {} /** * * Construct a multi_iterator with upper limit N, lower limit B and size k . * */ template inline basic_multi_iterator::basic_multi_iterator(T BB, T NN, size_t k) : N(NN), B(BB), v(k), flag_overflow(false) {} /** * * Construct from a vector. * */ template inline basic_multi_iterator::basic_multi_iterator(T BB, T NN, const std::vector & vv) : N(NN), B(BB), v(vv), flag_overflow(false) {} /** * * Destructor * */ template inline basic_multi_iterator::~basic_multi_iterator() {} // functions /** * * Returns the size of a multi_iterator. * */ template inline size_t basic_multi_iterator::size(void) const { return v.size(); } /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B,B,...,B) * \f] * */ template inline basic_multi_iterator & basic_multi_iterator::init(void) { flag_overflow = false; for ( size_t i=0; i inline bool basic_multi_iterator::overflow(void) const { return flag_overflow; } /** * * Returns a reference to the vector v. * */ template inline const std::vector & basic_multi_iterator::get_vector(void) const { return v; } // subscripting /** * * Subscription via [] * */ template inline T basic_multi_iterator::operator[](size_t i) const { return v[i]; } /** * * Subscription via [] * */ template inline T & basic_multi_iterator::operator[](size_t i) { return v[i]; } /** * * Subscription via () * */ template inline T basic_multi_iterator::operator()(size_t i) const { return v[i]; } /** * * Subscription via () * */ template inline T & basic_multi_iterator::operator()(size_t i) { return v[i]; } /** * * No effect for basic_multi_iterator * */ template inline basic_multi_iterator & basic_multi_iterator::operator++ (int) { return *this; } // I/O operators /** * * Output operator. A multi_iterator prints out as * basic_multi_iterator(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const basic_multi_iterator & v) { os << "basic_multi_iterator("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_ordered::multi_iterator_ordered(void) : basic_multi_iterator() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_ordered::multi_iterator_ordered(T B, T N, size_t k) : basic_multi_iterator(B,N,k) {} /** * * Construct from a vector. * */ template inline multi_iterator_ordered::multi_iterator_ordered(T B, T N, const std::vector & v) : basic_multi_iterator(B,N,v) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B+0,B+1,B+2,...,B+k-1) * \f] * */ template inline basic_multi_iterator & multi_iterator_ordered::init(void) { this->flag_overflow = false; T it = this->B; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = it; it++; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_ordered::operator++ (int) { int k = this->size(); int j = k - 1; T Upper_limit = this->N; while ( j>0 ) { this->v[j]++; if ( this->v[j] == Upper_limit ) { j--; Upper_limit--; } else { break; } } if (j==0) { this->v[j]++; if (this->v[j] == Upper_limit) this->flag_overflow=true; } if ( j>= 0) { for (int jj=j+1;jjv[jj] = this->v[jj-1]; this->v[jj]++; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_ordered prints out as * multi_iterator_ordered(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered & v) { os << "multi_iterator_ordered("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_ordered_eq::multi_iterator_ordered_eq(void) : basic_multi_iterator() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_ordered_eq::multi_iterator_ordered_eq(T B, T N, size_t k) : basic_multi_iterator(B,N,k) {} /** * * Construct from a vector. * */ template inline multi_iterator_ordered_eq::multi_iterator_ordered_eq(T B, T N, const std::vector & v) : basic_multi_iterator(B,N,v) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,...,n_k) = (B,B,...,B) * \f] * */ template inline basic_multi_iterator & multi_iterator_ordered_eq::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->B; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_ordered_eq::operator++ (int) { int k = this->size(); int j = k - 1; while ( j>0 ) { this->v[j]++; if ( this->v[j] == this->N ) { j--; } else { break; } } if (j==0) { this->v[j]++; if (this->v[j] == this->N) { this->flag_overflow=true; } } if ( j>= 0) { for (int jj=j+1;jjv[jj] = this->v[jj-1]; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_ordered_eq prints out as * multi_iterator_ordered_eq(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq & v) { os << "multi_iterator_ordered_eq("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_ordered_eq_indv::multi_iterator_ordered_eq_indv(void) : basic_multi_iterator(), Nv() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_ordered_eq_indv::multi_iterator_ordered_eq_indv(T B, const std::vector & Nvv, size_t k) : basic_multi_iterator(B,B,k), Nv(Nvv) {} /** * * Construct from a vector. * */ template inline multi_iterator_ordered_eq_indv::multi_iterator_ordered_eq_indv(T B, const std::vector & Nvv, const std::vector & v) : basic_multi_iterator(B,B,v), Nv(Nvv) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B,B,B,...,B) * \f] * */ template inline basic_multi_iterator & multi_iterator_ordered_eq_indv::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->B; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_ordered_eq_indv::operator++ (int) { int k = this->size(); int j = k - 1; while ( j>0 ) { this->v[j]++; if ( this->v[j] == Nv[j] ) { j--; } else { break; } } if (j==0) { this->v[j]++; if (this->v[j] == Nv[j]) { this->flag_overflow=true; } } if ( j>= 0) { for (int jj=j+1;jjv[jj] = this->v[jj-1]; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_ordered_eq_indv prints out as * multi_iterator_ordered_eq_indv(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq_indv & v) { os << "multi_iterator_ordered_eq_indv("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_counter::multi_iterator_counter(void) : basic_multi_iterator() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_counter::multi_iterator_counter(T B, T N, size_t k) : basic_multi_iterator(B,N,k) {} /** * * Construct from a vector. * */ template inline multi_iterator_counter::multi_iterator_counter(T B, T N, const std::vector & v) : basic_multi_iterator(B,N,v) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B,B,...,B) * \f] * */ template inline basic_multi_iterator & multi_iterator_counter::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->B; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_counter::operator++ (int) { int k = this->size(); int j = k - 1; while ( j>0 ) { this->v[j]++; if ( this->v[j] == this->N ) { this->v[j] = this->B; j--; } else { break; } } if (j==0) { this->v[j]++; if (this->v[j] == this->N) { this->v[j] = this->B; this->flag_overflow=true; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_counter prints out as * multi_iterator_counter(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_counter & v) { os << "multi_iterator_counter("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_counter_indv::multi_iterator_counter_indv(void) : basic_multi_iterator(), Nv() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_counter_indv::multi_iterator_counter_indv(T B, const std::vector & Nvv, size_t k) : basic_multi_iterator(B,B,k), Nv(Nvv) {} /** * * Construct from a vector. * */ template inline multi_iterator_counter_indv::multi_iterator_counter_indv(T B, const std::vector & Nvv, const std::vector & v) : basic_multi_iterator(B,B,v), Nv(Nvv) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B,B,...,B) * \f] * */ template inline basic_multi_iterator & multi_iterator_counter_indv::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->B; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_counter_indv::operator++ (int) { int k = this->size(); int j = k - 1; while ( j>0 ) { this->v[j]++; if ( this->v[j] == Nv[j] ) { this->v[j] = this->B; j--; } else { break; } } if (j==0) { this->v[j]++; if (this->v[j] == Nv[j]) { this->v[j] = this->B; this->flag_overflow=true; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_counter_indv prints out as * multi_iterator_counter_indv(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_counter_indv & v) { os << "multi_iterator_counter_indv("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_permutation::multi_iterator_permutation(void) : basic_multi_iterator() {} /** * * Construct a multi_iterator with upper limit N and size k . * */ template inline multi_iterator_permutation::multi_iterator_permutation(T B, T N, size_t k) : basic_multi_iterator(B,N,k) {} /** * * Construct from a vector. * */ template inline multi_iterator_permutation::multi_iterator_permutation(T B, T N, const std::vector & v) : basic_multi_iterator(B,N,v) {} // functions /** * * Initialize the multi-index to * \f[ * (n_1,n_2,n_3,...,n_k) = (B+0,B+1,B+2,...,B+k-1) * \f] * */ template inline basic_multi_iterator & multi_iterator_permutation::init(void) { this->flag_overflow = false; T it = this->B; for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = it; it++; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_permutation::operator++ (int) { int k = this->size(); int j = k - 1; while ( j>=0 ) { bool flag_have_already = true; while ( flag_have_already ) { this->v[j]++; // update flag_have_already flag_have_already = false; for (int ii=0; iiv[j] == this->v[ii]) { flag_have_already = true; } } } if ( this->v[j] == this->N ) { j--; } else { break; } } for (int l=j+1; lv[l] = this->B; bool flag_have_already; do { flag_have_already = false; for (int ii=0; iiv[l] == this->v[ii]) { flag_have_already = true; } } if (flag_have_already) { this->v[l]++; } } while (flag_have_already); } // check for overflow this->flag_overflow = true; T it = this->B; for (int ii=0; iiv[ii] != it) { this->flag_overflow = false; } it++; } return *this; } /** * * Returns the sign of the permutation, defined by * \f[ * \left(-1\right)^{n_{inv}}, * \f] * where \f$ n_{inv} \f$ is the number of inversions, e.g. the * number of pairs \f$ i < j \f$ for which * \f[ * n_i > n_j. * \f] * */ template inline int multi_iterator_permutation::get_sign() const { int sign = 1; int k = this->size(); for ( int i=0; iv[i] > this->v[j] ) { sign = -sign; } } } return sign; } // I/O operators /** * * Output operator. A multi_iterator_permutation prints out as * multi_iterator_permutation(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_permutation & v) { os << "multi_iterator_permutation("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_shuffle::multi_iterator_shuffle(void) : basic_multi_iterator(), N_internal(), v_internal(), v_orig() {} /** * * Construct from a vector. * */ template inline multi_iterator_shuffle::multi_iterator_shuffle(const std::vector & a, const std::vector & b) : basic_multi_iterator(), N_internal(), v_internal(), v_orig() { this->B = a[0]; for (size_t i=0; iv.push_back( a[i] ); this->v_orig.push_back( a[i] ); this->v_internal.push_back( i ); } for (size_t i=0; iv.push_back( b[i] ); this->v_orig.push_back( b[i] ); } this->N_internal = this->v.size(); } // functions /** * * Initialize the multi-index to the first shuffle. * */ template inline basic_multi_iterator & multi_iterator_shuffle::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v_internal.size(); i++) { this->v_internal[i] = i; } for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->v_orig[i]; } return *this; } /** * * The postfix increment operator allows to * write for a multi-index n++, which will * update n to the next configuration. * * If n is in the last configuration and the * increment operator ++ is applied to n, * the overflow flag will be raised. * */ template inline basic_multi_iterator & multi_iterator_shuffle::operator++ (int) { int k = this->v_internal.size(); int j = k - 1; size_t Upper_limit = this->N_internal; while ( j>0 ) { this->v_internal[j]++; if ( this->v_internal[j] == Upper_limit ) { j--; Upper_limit--; } else { break; } } if (j==0) { this->v_internal[j]++; if (this->v_internal[j] == Upper_limit) { this->flag_overflow=true; } } if ( j>= 0) { for (int jj=j+1;jjv_internal[jj] = this->v_internal[jj-1]; this->v_internal[jj]++; } } // update v if ( !(this->flag_overflow) ) { size_t i_a = 0; size_t i_b = 0; size_t i_all = 0; for (size_t j=0; jv_internal[j]; i++) { this->v[i_all] = this->v_orig[k+i_b]; i_b++; i_all++; } this->v[i_all] = this->v_orig[i_a]; i_a++; i_all++; } for (size_t i = this->v_internal[k-1]+1; i < this->v.size(); i++) { this->v[i_all] = this->v_orig[k+i_b]; i_b++; i_all++; } } return *this; } // I/O operators /** * * Output operator. A multi_iterator_shuffle prints out as * multi_iterator_shuffle(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle & v) { os << "multi_iterator_shuffle("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } // ctors /** * * Default constructor * */ template inline multi_iterator_shuffle_prime::multi_iterator_shuffle_prime(void) : multi_iterator_shuffle() {} /** * * Construct from a vector. * */ template inline multi_iterator_shuffle_prime::multi_iterator_shuffle_prime(const std::vector & a, const std::vector & b) : multi_iterator_shuffle(a,b) {} // functions /** * * Initialize the multi-index to the first shuffle. * */ template inline basic_multi_iterator & multi_iterator_shuffle_prime::init(void) { this->flag_overflow = false; for ( size_t i=0; i < this->v_internal.size(); i++) { this->v_internal[i] = i; } for ( size_t i=0; i < this->v.size(); i++) { this->v[i] = this->v_orig[i]; } (*this)++; return *this; } // I/O operators /** * * Output operator. A multi_iterator_shuffle_prime prints out as * multi_iterator_shuffle_prime(\f$n_0,n_1,...\f$). * */ template inline std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle_prime & v) { os << "multi_iterator_shuffle_prime("; for ( size_t i=0; i0) { os << ","; } os << format_index_value(v.B,v(i)); } return os << ")"; } } // namespace GiNaC #endif // ndef GINAC_UTILS_MULTI_ITERATOR_H