1 /** @file utils_multi_iterator.h
3 * Utilities for summing over multiple indices */
6 * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef GINAC_UTILS_MULTI_ITERATOR_H
24 #define GINAC_UTILS_MULTI_ITERATOR_H
35 * SFINAE test for distance
38 template <typename T> class has_distance {
40 typedef char yes_type[1];
41 typedef char no_type[2];
43 template <typename C> static yes_type & test( decltype(std::distance<C>) ) ;
44 template <typename C> static no_type & test(...);
47 enum { value = sizeof(test<T>(0)) == sizeof(yes_type) };
52 * For printing a multi-index:
53 * If the templates are used, where T is an iterator, printing the address where the iterator points to is not meaningful.
54 * However, we may print the difference to the starting point.
57 template<typename T> typename std::enable_if<has_distance<T>::value, typename std::iterator_traits<T>::difference_type>::type format_index_value(const T & a, const T & b) {
58 return std::distance(a,b);
63 * For all other cases we simply print the value.
66 template<typename T> typename std::enable_if<!has_distance<T>::value, T>::type format_index_value(const T & a, const T & b) {
72 * basic_multi_iterator is a base class.
74 * The base class itself does not do anything useful.
75 * A typical use of a class derived from basic_multi_iterator is
77 * multi_iterator_ordered<int> k(0,4,2);
79 * for( k.init(); !k.overflow(); k++) {
80 * std::cout << k << std::endl;
85 * multi_iterator_ordered(0,1)
86 * multi_iterator_ordered(0,2)
87 * multi_iterator_ordered(0,3)
88 * multi_iterator_ordered(1,2)
89 * multi_iterator_ordered(1,3)
90 * multi_iterator_ordered(2,3)
92 * Individual components of k can be accessed with k[i] or k(i).
94 * All classes derived from basic_multi_iterator follow the same syntax.
97 template<class T> class basic_multi_iterator {
101 basic_multi_iterator(void);
102 explicit basic_multi_iterator(T B, T N, size_t k);
103 explicit basic_multi_iterator(T B, T N, const std::vector<T> & vv);
106 virtual ~basic_multi_iterator();
110 size_t size(void) const;
111 bool overflow(void) const;
112 const std::vector<T> & get_vector(void) const;
116 T operator[](size_t i) const;
117 T & operator[](size_t i);
119 T operator()(size_t i) const;
120 T & operator()(size_t i);
125 virtual basic_multi_iterator<T> & init(void);
127 virtual basic_multi_iterator<T> & operator++ (int);
130 template <class TT> friend std::ostream & operator<< (std::ostream & os, const basic_multi_iterator<TT> & v);
132 // member variables :
143 * The class multi_iterator_ordered defines a multi_iterator
144 * \f$(i_1,i_2,...,i_k)\f$, such that
152 * It is assumed that \f$k>0\f$ and \f$ N-B \ge k \f$.
155 template<class T> class multi_iterator_ordered : public basic_multi_iterator<T> {
159 multi_iterator_ordered(void);
160 explicit multi_iterator_ordered(T B, T N, size_t k);
161 explicit multi_iterator_ordered(T B, T N, const std::vector<T> & vv);
163 // overriding virtual functions from base class
166 basic_multi_iterator<T> & init(void);
168 basic_multi_iterator<T> & operator++ (int);
171 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered<TT> & v);
177 * The class multi_iterator_ordered_eq defines a multi_iterator
178 * \f$(i_1,i_2,...,i_k)\f$, such that
186 * It is assumed that \f$k>0\f$.
189 template<class T> class multi_iterator_ordered_eq : public basic_multi_iterator<T> {
193 multi_iterator_ordered_eq(void);
194 explicit multi_iterator_ordered_eq(T B, T N, size_t k);
195 explicit multi_iterator_ordered_eq(T B, T N, const std::vector<T> & vv);
197 // overriding virtual functions from base class
200 basic_multi_iterator<T> & init(void);
202 basic_multi_iterator<T> & operator++ (int);
205 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq<TT> & v);
211 * The class multi_iterator_ordered_eq_indv defines a multi_iterator
212 * \f$(i_1,i_2,...,i_k)\f$, such that
222 template<class T> class multi_iterator_ordered_eq_indv : public basic_multi_iterator<T> {
226 multi_iterator_ordered_eq_indv(void);
227 explicit multi_iterator_ordered_eq_indv(T B, const std::vector<T> & Nv, size_t k);
228 explicit multi_iterator_ordered_eq_indv(T B, const std::vector<T> & Nv, const std::vector<T> & vv);
230 // overriding virtual functions from base class
233 basic_multi_iterator<T> & init(void);
235 basic_multi_iterator<T> & operator++ (int);
238 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq_indv<TT> & v);
240 // member variables :
247 * The class multi_iterator_counter defines a multi_iterator
248 * \f$(i_1,i_2,...,i_k)\f$, such that
254 template<class T> class multi_iterator_counter : public basic_multi_iterator<T> {
258 multi_iterator_counter(void);
259 explicit multi_iterator_counter(T B, T N, size_t k);
260 explicit multi_iterator_counter(T B, T N, const std::vector<T> & vv);
262 // overriding virtual functions from base class
265 basic_multi_iterator<T> & init(void);
267 basic_multi_iterator<T> & operator++ (int);
270 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_counter<TT> & v);
276 * The class multi_iterator_counter_indv defines a multi_iterator
277 * \f$(i_1,i_2,...,i_k)\f$, such that
283 template<class T> class multi_iterator_counter_indv : public basic_multi_iterator<T> {
287 multi_iterator_counter_indv(void);
288 explicit multi_iterator_counter_indv(T B, const std::vector<T> & Nv, size_t k);
289 explicit multi_iterator_counter_indv(T B, const std::vector<T> & Nv, const std::vector<T> & vv);
291 // overriding virtual functions from base class
294 basic_multi_iterator<T> & init(void);
296 basic_multi_iterator<T> & operator++ (int);
299 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_counter_indv<TT> & v);
301 // member variables :
308 * The class multi_iterator_permutation defines a multi_iterator
309 * \f$(i_1,i_2,...,i_k)\f$, for which
317 * In particular, if \f$N-B=k\f$, multi_iterator_permutation loops over all
318 * permutations of \f$k\f$ elements.
321 template<class T> class multi_iterator_permutation : public basic_multi_iterator<T> {
325 multi_iterator_permutation(void);
326 explicit multi_iterator_permutation(T B, T N, size_t k);
327 explicit multi_iterator_permutation(T B, T N, const std::vector<T> & vv);
329 // overriding virtual functions from base class
332 basic_multi_iterator<T> & init(void);
334 basic_multi_iterator<T> & operator++ (int);
336 // new functions in this class
337 int get_sign(void) const;
340 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_permutation<TT> & v);
346 * The class multi_iterator_shuffle defines a multi_iterator,
347 * which runs over all shuffles of a and b.
350 template<class T> class multi_iterator_shuffle : public basic_multi_iterator<T> {
354 multi_iterator_shuffle(void);
355 explicit multi_iterator_shuffle(const std::vector<T> & a, const std::vector<T> & b);
357 // overriding virtual functions from base class
360 basic_multi_iterator<T> & init(void);
362 basic_multi_iterator<T> & operator++ (int);
365 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle<TT> & v);
367 // member variables :
370 std::vector<size_t> v_internal;
371 std::vector<T> v_orig;
376 * The class multi_iterator_shuffle_prime defines a multi_iterator,
377 * which runs over all shuffles of a and b, excluding the first one (a,b).
380 template<class T> class multi_iterator_shuffle_prime : public multi_iterator_shuffle<T> {
384 multi_iterator_shuffle_prime(void);
385 explicit multi_iterator_shuffle_prime(const std::vector<T> & a, const std::vector<T> & b);
387 // overriding virtual functions from base class
390 basic_multi_iterator<T> & init(void);
393 template <class TT> friend std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle_prime<TT> & v);
396 // ----------------------------------------------------------------------------------------------------------------
402 * Default constructor
405 template<class T> inline basic_multi_iterator<T>::basic_multi_iterator(void) : N(), B(), v(), flag_overflow(false)
410 * Construct a multi_iterator with upper limit N, lower limit B and size k .
413 template<class T> inline basic_multi_iterator<T>::basic_multi_iterator(T BB, T NN, size_t k) : N(NN), B(BB), v(k), flag_overflow(false)
418 * Construct from a vector.
421 template<class T> inline basic_multi_iterator<T>::basic_multi_iterator(T BB, T NN, const std::vector<T> & vv) : N(NN), B(BB), v(vv), flag_overflow(false)
429 template<class T> inline basic_multi_iterator<T>::~basic_multi_iterator()
436 * Returns the size of a multi_iterator.
439 template<class T> inline size_t basic_multi_iterator<T>::size(void) const
446 * Initialize the multi-index to
448 * (n_1,n_2,n_3,...,n_k) = (B,B,...,B)
452 template<class T> inline basic_multi_iterator<T> & basic_multi_iterator<T>::init(void)
454 flag_overflow = false;
456 for ( size_t i=0; i<v.size(); i++) {
464 * Return the overflow flag.
467 template<class T> inline bool basic_multi_iterator<T>::overflow(void) const
469 return flag_overflow;
474 * Returns a reference to the vector v.
477 template<class T> inline const std::vector<T> & basic_multi_iterator<T>::get_vector(void) const
486 * Subscription via []
489 template<class T> inline T basic_multi_iterator<T>::operator[](size_t i) const
496 * Subscription via []
499 template<class T> inline T & basic_multi_iterator<T>::operator[](size_t i)
506 * Subscription via ()
509 template<class T> inline T basic_multi_iterator<T>::operator()(size_t i) const
516 * Subscription via ()
519 template<class T> inline T & basic_multi_iterator<T>::operator()(size_t i)
527 * No effect for basic_multi_iterator
530 template<class T> inline basic_multi_iterator<T> & basic_multi_iterator<T>::operator++ (int)
539 * Output operator. A multi_iterator prints out as
540 * basic_multi_iterator(\f$n_0,n_1,...\f$).
543 template<class T> inline std::ostream & operator<< (std::ostream & os, const basic_multi_iterator<T> & v)
545 os << "basic_multi_iterator(";
546 for ( size_t i=0; i<v.size(); i++) {
550 os << format_index_value(v.B,v(i));
562 * Default constructor
565 template<class T> inline multi_iterator_ordered<T>::multi_iterator_ordered(void) : basic_multi_iterator<T>()
570 * Construct a multi_iterator with upper limit N and size k .
573 template<class T> inline multi_iterator_ordered<T>::multi_iterator_ordered(T B, T N, size_t k) : basic_multi_iterator<T>(B,N,k)
578 * Construct from a vector.
581 template<class T> inline multi_iterator_ordered<T>::multi_iterator_ordered(T B, T N, const std::vector<T> & v) : basic_multi_iterator<T>(B,N,v)
588 * Initialize the multi-index to
590 * (n_1,n_2,n_3,...,n_k) = (B+0,B+1,B+2,...,B+k-1)
594 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered<T>::init(void)
596 this->flag_overflow = false;
599 for ( size_t i=0; i < this->v.size(); i++) {
608 * The postfix increment operator allows to
609 * write for a multi-index n++, which will
610 * update n to the next configuration.
612 * If n is in the last configuration and the
613 * increment operator ++ is applied to n,
614 * the overflow flag will be raised.
617 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered<T>::operator++ (int)
619 int k = this->size();
621 T Upper_limit = this->N;
625 if ( this->v[j] == Upper_limit ) {
636 if (this->v[j] == Upper_limit) this->flag_overflow=true;
640 for (int jj=j+1;jj<k;jj++) {
641 this->v[jj] = this->v[jj-1];
653 * Output operator. A multi_iterator_ordered prints out as
654 * multi_iterator_ordered(\f$n_0,n_1,...\f$).
657 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered<T> & v)
659 os << "multi_iterator_ordered(";
660 for ( size_t i=0; i<v.size(); i++) {
664 os << format_index_value(v.B,v(i));
676 * Default constructor
679 template<class T> inline multi_iterator_ordered_eq<T>::multi_iterator_ordered_eq(void) : basic_multi_iterator<T>()
684 * Construct a multi_iterator with upper limit N and size k .
687 template<class T> inline multi_iterator_ordered_eq<T>::multi_iterator_ordered_eq(T B, T N, size_t k) : basic_multi_iterator<T>(B,N,k)
692 * Construct from a vector.
695 template<class T> inline multi_iterator_ordered_eq<T>::multi_iterator_ordered_eq(T B, T N, const std::vector<T> & v) : basic_multi_iterator<T>(B,N,v)
702 * Initialize the multi-index to
704 * (n_1,n_2,...,n_k) = (B,B,...,B)
708 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered_eq<T>::init(void)
710 this->flag_overflow = false;
712 for ( size_t i=0; i < this->v.size(); i++) {
713 this->v[i] = this->B;
720 * The postfix increment operator allows to
721 * write for a multi-index n++, which will
722 * update n to the next configuration.
724 * If n is in the last configuration and the
725 * increment operator ++ is applied to n,
726 * the overflow flag will be raised.
729 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered_eq<T>::operator++ (int)
731 int k = this->size();
736 if ( this->v[j] == this->N ) {
746 if (this->v[j] == this->N) {
747 this->flag_overflow=true;
752 for (int jj=j+1;jj<k;jj++) {
753 this->v[jj] = this->v[jj-1];
764 * Output operator. A multi_iterator_ordered_eq prints out as
765 * multi_iterator_ordered_eq(\f$n_0,n_1,...\f$).
768 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq<T> & v)
770 os << "multi_iterator_ordered_eq(";
771 for ( size_t i=0; i<v.size(); i++) {
775 os << format_index_value(v.B,v(i));
788 * Default constructor
791 template<class T> inline multi_iterator_ordered_eq_indv<T>::multi_iterator_ordered_eq_indv(void) : basic_multi_iterator<T>(), Nv()
796 * Construct a multi_iterator with upper limit N and size k .
799 template<class T> inline multi_iterator_ordered_eq_indv<T>::multi_iterator_ordered_eq_indv(T B, const std::vector<T> & Nvv, size_t k) : basic_multi_iterator<T>(B,B,k), Nv(Nvv)
804 * Construct from a vector.
807 template<class T> inline multi_iterator_ordered_eq_indv<T>::multi_iterator_ordered_eq_indv(T B, const std::vector<T> & Nvv, const std::vector<T> & v) : basic_multi_iterator<T>(B,B,v), Nv(Nvv)
814 * Initialize the multi-index to
816 * (n_1,n_2,n_3,...,n_k) = (B,B,B,...,B)
820 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered_eq_indv<T>::init(void)
822 this->flag_overflow = false;
824 for ( size_t i=0; i < this->v.size(); i++) {
825 this->v[i] = this->B;
832 * The postfix increment operator allows to
833 * write for a multi-index n++, which will
834 * update n to the next configuration.
836 * If n is in the last configuration and the
837 * increment operator ++ is applied to n,
838 * the overflow flag will be raised.
841 template<class T> inline basic_multi_iterator<T> & multi_iterator_ordered_eq_indv<T>::operator++ (int)
843 int k = this->size();
848 if ( this->v[j] == Nv[j] ) {
858 if (this->v[j] == Nv[j]) {
859 this->flag_overflow=true;
864 for (int jj=j+1;jj<k;jj++) {
865 this->v[jj] = this->v[jj-1];
876 * Output operator. A multi_iterator_ordered_eq_indv prints out as
877 * multi_iterator_ordered_eq_indv(\f$n_0,n_1,...\f$).
880 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_ordered_eq_indv<T> & v)
882 os << "multi_iterator_ordered_eq_indv(";
883 for ( size_t i=0; i<v.size(); i++) {
887 os << format_index_value(v.B,v(i));
900 * Default constructor
903 template<class T> inline multi_iterator_counter<T>::multi_iterator_counter(void) : basic_multi_iterator<T>()
908 * Construct a multi_iterator with upper limit N and size k .
911 template<class T> inline multi_iterator_counter<T>::multi_iterator_counter(T B, T N, size_t k) : basic_multi_iterator<T>(B,N,k)
916 * Construct from a vector.
919 template<class T> inline multi_iterator_counter<T>::multi_iterator_counter(T B, T N, const std::vector<T> & v) : basic_multi_iterator<T>(B,N,v)
926 * Initialize the multi-index to
928 * (n_1,n_2,n_3,...,n_k) = (B,B,...,B)
932 template<class T> inline basic_multi_iterator<T> & multi_iterator_counter<T>::init(void)
934 this->flag_overflow = false;
936 for ( size_t i=0; i < this->v.size(); i++) {
937 this->v[i] = this->B;
944 * The postfix increment operator allows to
945 * write for a multi-index n++, which will
946 * update n to the next configuration.
948 * If n is in the last configuration and the
949 * increment operator ++ is applied to n,
950 * the overflow flag will be raised.
953 template<class T> inline basic_multi_iterator<T> & multi_iterator_counter<T>::operator++ (int)
955 int k = this->size();
960 if ( this->v[j] == this->N ) {
961 this->v[j] = this->B;
971 if (this->v[j] == this->N) {
972 this->v[j] = this->B;
973 this->flag_overflow=true;
984 * Output operator. A multi_iterator_counter prints out as
985 * multi_iterator_counter(\f$n_0,n_1,...\f$).
988 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_counter<T> & v)
990 os << "multi_iterator_counter(";
991 for ( size_t i=0; i<v.size(); i++) {
995 os << format_index_value(v.B,v(i));
1008 * Default constructor
1011 template<class T> inline multi_iterator_counter_indv<T>::multi_iterator_counter_indv(void) : basic_multi_iterator<T>(), Nv()
1016 * Construct a multi_iterator with upper limit N and size k .
1019 template<class T> inline multi_iterator_counter_indv<T>::multi_iterator_counter_indv(T B, const std::vector<T> & Nvv, size_t k) : basic_multi_iterator<T>(B,B,k), Nv(Nvv)
1024 * Construct from a vector.
1027 template<class T> inline multi_iterator_counter_indv<T>::multi_iterator_counter_indv(T B, const std::vector<T> & Nvv, const std::vector<T> & v) : basic_multi_iterator<T>(B,B,v), Nv(Nvv)
1034 * Initialize the multi-index to
1036 * (n_1,n_2,n_3,...,n_k) = (B,B,...,B)
1040 template<class T> inline basic_multi_iterator<T> & multi_iterator_counter_indv<T>::init(void)
1042 this->flag_overflow = false;
1044 for ( size_t i=0; i < this->v.size(); i++) {
1045 this->v[i] = this->B;
1052 * The postfix increment operator allows to
1053 * write for a multi-index n++, which will
1054 * update n to the next configuration.
1056 * If n is in the last configuration and the
1057 * increment operator ++ is applied to n,
1058 * the overflow flag will be raised.
1061 template<class T> inline basic_multi_iterator<T> & multi_iterator_counter_indv<T>::operator++ (int)
1063 int k = this->size();
1068 if ( this->v[j] == Nv[j] ) {
1069 this->v[j] = this->B;
1079 if (this->v[j] == Nv[j]) {
1080 this->v[j] = this->B;
1081 this->flag_overflow=true;
1092 * Output operator. A multi_iterator_counter_indv prints out as
1093 * multi_iterator_counter_indv(\f$n_0,n_1,...\f$).
1096 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_counter_indv<T> & v)
1098 os << "multi_iterator_counter_indv(";
1099 for ( size_t i=0; i<v.size(); i++) {
1103 os << format_index_value(v.B,v(i));
1116 * Default constructor
1119 template<class T> inline multi_iterator_permutation<T>::multi_iterator_permutation(void) : basic_multi_iterator<T>()
1124 * Construct a multi_iterator with upper limit N and size k .
1127 template<class T> inline multi_iterator_permutation<T>::multi_iterator_permutation(T B, T N, size_t k) : basic_multi_iterator<T>(B,N,k)
1132 * Construct from a vector.
1135 template<class T> inline multi_iterator_permutation<T>::multi_iterator_permutation(T B, T N, const std::vector<T> & v) : basic_multi_iterator<T>(B,N,v)
1142 * Initialize the multi-index to
1144 * (n_1,n_2,n_3,...,n_k) = (B+0,B+1,B+2,...,B+k-1)
1148 template<class T> inline basic_multi_iterator<T> & multi_iterator_permutation<T>::init(void)
1150 this->flag_overflow = false;
1153 for ( size_t i=0; i < this->v.size(); i++) {
1162 * The postfix increment operator allows to
1163 * write for a multi-index n++, which will
1164 * update n to the next configuration.
1166 * If n is in the last configuration and the
1167 * increment operator ++ is applied to n,
1168 * the overflow flag will be raised.
1171 template<class T> inline basic_multi_iterator<T> & multi_iterator_permutation<T>::operator++ (int)
1173 int k = this->size();
1177 bool flag_have_already = true;
1178 while ( flag_have_already ) {
1181 // update flag_have_already
1182 flag_have_already = false;
1183 for (int ii=0; ii<j; ii++) {
1184 if (this->v[j] == this->v[ii]) {
1185 flag_have_already = true;
1190 if ( this->v[j] == this->N ) {
1198 for (int l=j+1; l<k; l++) {
1199 this->v[l] = this->B;
1201 bool flag_have_already;
1203 flag_have_already = false;
1204 for (int ii=0; ii<l; ii++) {
1205 if (this->v[l] == this->v[ii]) {
1206 flag_have_already = true;
1209 if (flag_have_already) {
1213 while (flag_have_already);
1216 // check for overflow
1217 this->flag_overflow = true;
1219 for (int ii=0; ii<k; ii++) {
1220 if (this->v[ii] != it) {
1221 this->flag_overflow = false;
1231 * Returns the sign of the permutation, defined by
1233 * \left(-1\right)^{n_{inv}},
1235 * where \f$ n_{inv} \f$ is the number of inversions, e.g. the
1236 * number of pairs \f$ i < j \f$ for which
1242 template<class T> inline int multi_iterator_permutation<T>::get_sign() const
1245 int k = this->size();
1247 for ( int i=0; i<k; i++) {
1248 for ( int j=i+1; j<k; j++) {
1249 // works only for random-access iterators
1250 if ( this->v[i] > this->v[j] ) {
1264 * Output operator. A multi_iterator_permutation prints out as
1265 * multi_iterator_permutation(\f$n_0,n_1,...\f$).
1268 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_permutation<T> & v)
1270 os << "multi_iterator_permutation(";
1271 for ( size_t i=0; i<v.size(); i++) {
1275 os << format_index_value(v.B,v(i));
1287 * Default constructor
1290 template<class T> inline multi_iterator_shuffle<T>::multi_iterator_shuffle(void) : basic_multi_iterator<T>(), N_internal(), v_internal(), v_orig()
1295 * Construct from a vector.
1298 template<class T> inline multi_iterator_shuffle<T>::multi_iterator_shuffle(const std::vector<T> & a, const std::vector<T> & b) : basic_multi_iterator<T>(), N_internal(), v_internal(), v_orig()
1302 for (size_t i=0; i<a.size(); i++) {
1303 this->v.push_back( a[i] );
1304 this->v_orig.push_back( a[i] );
1305 this->v_internal.push_back( i );
1307 for (size_t i=0; i<b.size(); i++) {
1308 this->v.push_back( b[i] );
1309 this->v_orig.push_back( b[i] );
1311 this->N_internal = this->v.size();
1318 * Initialize the multi-index to the first shuffle.
1321 template<class T> inline basic_multi_iterator<T> & multi_iterator_shuffle<T>::init(void)
1323 this->flag_overflow = false;
1325 for ( size_t i=0; i < this->v_internal.size(); i++) {
1326 this->v_internal[i] = i;
1328 for ( size_t i=0; i < this->v.size(); i++) {
1329 this->v[i] = this->v_orig[i];
1336 * The postfix increment operator allows to
1337 * write for a multi-index n++, which will
1338 * update n to the next configuration.
1340 * If n is in the last configuration and the
1341 * increment operator ++ is applied to n,
1342 * the overflow flag will be raised.
1345 template<class T> inline basic_multi_iterator<T> & multi_iterator_shuffle<T>::operator++ (int)
1347 int k = this->v_internal.size();
1349 size_t Upper_limit = this->N_internal;
1352 this->v_internal[j]++;
1353 if ( this->v_internal[j] == Upper_limit ) {
1363 this->v_internal[j]++;
1364 if (this->v_internal[j] == Upper_limit) {
1365 this->flag_overflow=true;
1370 for (int jj=j+1;jj<k;jj++) {
1371 this->v_internal[jj] = this->v_internal[jj-1];
1372 this->v_internal[jj]++;
1377 if ( !(this->flag_overflow) ) {
1381 for (size_t j=0; j<k; j++) {
1382 for (size_t i=i_all; i < this->v_internal[j]; i++) {
1383 this->v[i_all] = this->v_orig[k+i_b];
1387 this->v[i_all] = this->v_orig[i_a];
1391 for (size_t i = this->v_internal[k-1]+1; i < this->v.size(); i++) {
1392 this->v[i_all] = this->v_orig[k+i_b];
1405 * Output operator. A multi_iterator_shuffle prints out as
1406 * multi_iterator_shuffle(\f$n_0,n_1,...\f$).
1409 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle<T> & v)
1411 os << "multi_iterator_shuffle(";
1412 for ( size_t i=0; i<v.size(); i++) {
1416 os << format_index_value(v.B,v(i));
1428 * Default constructor
1431 template<class T> inline multi_iterator_shuffle_prime<T>::multi_iterator_shuffle_prime(void) : multi_iterator_shuffle<T>()
1436 * Construct from a vector.
1439 template<class T> inline multi_iterator_shuffle_prime<T>::multi_iterator_shuffle_prime(const std::vector<T> & a, const std::vector<T> & b) : multi_iterator_shuffle<T>(a,b)
1446 * Initialize the multi-index to the first shuffle.
1449 template<class T> inline basic_multi_iterator<T> & multi_iterator_shuffle_prime<T>::init(void)
1451 this->flag_overflow = false;
1453 for ( size_t i=0; i < this->v_internal.size(); i++) {
1454 this->v_internal[i] = i;
1456 for ( size_t i=0; i < this->v.size(); i++) {
1457 this->v[i] = this->v_orig[i];
1469 * Output operator. A multi_iterator_shuffle_prime prints out as
1470 * multi_iterator_shuffle_prime(\f$n_0,n_1,...\f$).
1473 template<class T> inline std::ostream & operator<< (std::ostream & os, const multi_iterator_shuffle_prime<T> & v)
1475 os << "multi_iterator_shuffle_prime(";
1476 for ( size_t i=0; i<v.size(); i++) {
1480 os << format_index_value(v.B,v(i));
1486 } // namespace GiNaC
1488 #endif // ndef GINAC_UTILS_MULTI_ITERATOR_H