/* $Id$ */ // Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CoinSort_H #define CoinSort_H #include #include #include #include "CoinDistance.hpp" // Uncomment the next three lines to get thorough initialisation of memory. // #ifndef ZEROFAULT // #define ZEROFAULT // #endif #ifdef COIN_FAST_CODE #ifndef COIN_USE_EKK_SORT #define COIN_USE_EKK_SORT #endif #endif //############################################################################# /** An ordered pair. It's the same as std::pair, just this way it'll have the same look as the triple sorting. */ template < class S, class T > struct CoinPair { public: /// First member of pair S first; /// Second member of pair T second; public: /// Construct from ordered pair CoinPair(const S &s, const T &t) : first(s) , second(t) { } }; //############################################################################# /**@name Comparisons on first element of two ordered pairs */ //@{ /** Function operator. Returns true if t1.first < t2.first (i.e., increasing). */ template < class S, class T > class CoinFirstLess_2 { public: /// Compare function inline bool operator()(const CoinPair< S, T > &t1, const CoinPair< S, T > &t2) const { return t1.first < t2.first; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if t1.first > t2.first (i.e, decreasing). */ template < class S, class T > class CoinFirstGreater_2 { public: /// Compare function inline bool operator()(const CoinPair< S, T > &t1, const CoinPair< S, T > &t2) const { return t1.first > t2.first; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ template < class S, class T > class CoinFirstAbsLess_2 { public: /// Compare function inline bool operator()(const CoinPair< S, T > &t1, const CoinPair< S, T > &t2) const { const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; return t1Abs < t2Abs; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ template < class S, class T > class CoinFirstAbsGreater_2 { public: /// Compare function inline bool operator()(CoinPair< S, T > t1, CoinPair< S, T > t2) const { const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; return t1Abs > t2Abs; } }; //----------------------------------------------------------------------------- /** Function operator. Compare based on the entries of an external vector, i.e., returns true if vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to use this comparison operator .first must be a data type automatically convertible to int. */ template < class S, class T, class V > class CoinExternalVectorFirstLess_2 { private: CoinExternalVectorFirstLess_2(); private: const V *vec_; public: inline bool operator()(const CoinPair< S, T > &t1, const CoinPair< S, T > &t2) const { return vec_[t1.first] < vec_[t2.first]; } CoinExternalVectorFirstLess_2(const V *v) : vec_(v) { } }; //----------------------------------------------------------------------------- /** Function operator. Compare based on the entries of an external vector, i.e., returns true if vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to use this comparison operator .first must be a data type automatically convertible to int. */ template < class S, class T, class V > class CoinExternalVectorFirstGreater_2 { private: CoinExternalVectorFirstGreater_2(); private: const V *vec_; public: inline bool operator()(const CoinPair< S, T > &t1, const CoinPair< S, T > &t2) const { return vec_[t1.first] > vec_[t2.first]; } CoinExternalVectorFirstGreater_2(const V *v) : vec_(v) { } }; //@} //############################################################################# /** Sort a pair of containers.
Iter_S - iterator for first container
Iter_T - iterator for 2nd container
CoinCompare2 - class comparing CoinPairs
*/ #ifdef COIN_SORT_ARBITRARY_CONTAINERS template < class Iter_S, class Iter_T, class CoinCompare2 > void CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst, const CoinCompare2 &pc) { typedef typename std::iterator_traits< Iter_S >::value_type S; typedef typename std::iterator_traits< Iter_T >::value_type T; const size_t len = coinDistance(sfirst, slast); if (len <= 1) return; typedef CoinPair< S, T > ST_pair; ST_pair *x = static_cast< ST_pair * >(::operator new(len * sizeof(ST_pair))); #ifdef ZEROFAULT memset(x, 0, (len * sizeof(ST_pair))); #endif int i = 0; Iter_S scurrent = sfirst; Iter_T tcurrent = tfirst; while (scurrent != slast) { new (x + i++) ST_pair(*scurrent++, *tcurrent++); } std::sort(x.begin(), x.end(), pc); scurrent = sfirst; tcurrent = tfirst; for (i = 0; i < len; ++i) { *scurrent++ = x[i].first; *tcurrent++ = x[i].second; } ::operator delete(x); } //----------------------------------------------------------------------------- template < class Iter_S, class Iter_T > void CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst) { typedef typename std::iterator_traits< Iter_S >::value_type S; typedef typename std::iterator_traits< Iter_T >::value_type T; CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); } #else //======================================================================= template < class S, class T, class CoinCompare2 > void CoinSort_2(S *sfirst, S *slast, T *tfirst, const CoinCompare2 &pc) { const size_t len = coinDistance(sfirst, slast); if (len <= 1) return; typedef CoinPair< S, T > ST_pair; ST_pair *x = static_cast< ST_pair * >(::operator new(len * sizeof(ST_pair))); #ifdef ZEROFAULT // Can show RUI errors on some systems due to copy of ST_pair with gaps. // E.g., has 4 byte alignment gap on Solaris/SUNWspro. memset(x, 0, (len * sizeof(ST_pair))); #endif size_t i = 0; S *scurrent = sfirst; T *tcurrent = tfirst; while (scurrent != slast) { new (x + i++) ST_pair(*scurrent++, *tcurrent++); } std::sort(x, x + len, pc); scurrent = sfirst; tcurrent = tfirst; for (i = 0; i < len; ++i) { *scurrent++ = x[i].first; *tcurrent++ = x[i].second; } ::operator delete(x); } template < class S, class T > void // This Always uses std::sort CoinSort_2Std(S *sfirst, S *slast, T *tfirst) { CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); } #ifndef COIN_USE_EKK_SORT //----------------------------------------------------------------------------- template < class S, class T > void CoinSort_2(S *sfirst, S *slast, T *tfirst) { CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); } #else //----------------------------------------------------------------------------- extern int boundary_sort; extern int boundary_sort2; extern int boundary_sort3; /// Sort without new and delete template < class S, class T > void CoinSort_2(S *key, S *lastKey, T *array2) { const size_t number = coinDistance(key, lastKey); if (number <= 1) { return; } else if (number > 10000) { CoinSort_2Std(key, lastKey, array2); return; } #if 0 if (number==boundary_sort3) { printf("before sort %d entries\n",number); for (int j=0;j(number); int sp; S *v = key; S *m, t; S *ls[32], *rs[32]; S *l, *r, c; T it; int j; /*check already sorted */ S last = key[0]; for (j = 1; j < n; j++) { if (key[j] >= last) { last = key[j]; } else { break; } /* endif */ } /* endfor */ if (j == n) { return; } /* endif */ sp = 0; ls[sp] = v; rs[sp] = v + (n - 1); while (sp >= 0) { if (rs[sp] - ls[sp] > minsize) { l = ls[sp]; r = rs[sp]; m = l + (r - l) / 2; if (*l > *m) { t = *l; *l = *m; *m = t; it = array2[l - v]; array2[l - v] = array2[m - v]; array2[m - v] = it; } if (*m > *r) { t = *m; *m = *r; *r = t; it = array2[m - v]; array2[m - v] = array2[r - v]; array2[r - v] = it; if (*l > *m) { t = *l; *l = *m; *m = t; it = array2[l - v]; array2[l - v] = array2[m - v]; array2[m - v] = it; } } c = *m; while (r - l > 1) { while (*(++l) < c) ; while (*(--r) > c) ; t = *l; *l = *r; *r = t; it = array2[l - v]; array2[l - v] = array2[r - v]; array2[r - v] = it; } l = r - 1; if (l < m) { ls[sp + 1] = ls[sp]; rs[sp + 1] = l; ls[sp] = r; } else { ls[sp + 1] = r; rs[sp + 1] = rs[sp]; rs[sp] = l; } sp++; } else sp--; } for (l = v, m = v + (n - 1); l < m; l++) { if (*l > *(l + 1)) { c = *(l + 1); it = array2[(l - v) + 1]; for (r = l; r >= v && *r > c; r--) { *(r + 1) = *r; array2[(r - v) + 1] = array2[(r - v)]; } *(r + 1) = c; array2[(r - v) + 1] = it; } } #if 0 if (number==boundary_sort3) { printf("after sort %d entries\n",number); for (int j=0;j void CoinShortSort_2(S *key, S *lastKey, T *array2) { const size_t number = coinDistance(key, lastKey); if (number <= 2) { if (number == 2 && key[0] > key[1]) { S tempS = key[0]; T tempT = array2[0]; key[0] = key[1]; array2[0] = array2[1]; key[1] = tempS; array2[1] = tempT; } return; } else if (number > 10000) { CoinSort_2Std(key, lastKey, array2); return; } int minsize = 10; size_t n = number; int sp; S *v = key; S *m, t; S *ls[32], *rs[32]; S *l, *r, c; T it; size_t j; /*check already sorted */ S last = key[0]; for (j = 1; j < n; j++) { if (key[j] >= last) { last = key[j]; } else { break; } /* endif */ } /* endfor */ if (j == n) { return; } /* endif */ sp = 0; ls[sp] = v; rs[sp] = v + (n - 1); while (sp >= 0) { if (rs[sp] - ls[sp] > minsize) { l = ls[sp]; r = rs[sp]; m = l + (r - l) / 2; if (*l > *m) { t = *l; *l = *m; *m = t; it = array2[l - v]; array2[l - v] = array2[m - v]; array2[m - v] = it; } if (*m > *r) { t = *m; *m = *r; *r = t; it = array2[m - v]; array2[m - v] = array2[r - v]; array2[r - v] = it; if (*l > *m) { t = *l; *l = *m; *m = t; it = array2[l - v]; array2[l - v] = array2[m - v]; array2[m - v] = it; } } c = *m; while (r - l > 1) { while (*(++l) < c) ; while (*(--r) > c) ; t = *l; *l = *r; *r = t; it = array2[l - v]; array2[l - v] = array2[r - v]; array2[r - v] = it; } l = r - 1; if (l < m) { ls[sp + 1] = ls[sp]; rs[sp + 1] = l; ls[sp] = r; } else { ls[sp + 1] = r; rs[sp + 1] = rs[sp]; rs[sp] = l; } sp++; } else sp--; } for (l = v, m = v + (n - 1); l < m; l++) { if (*l > *(l + 1)) { c = *(l + 1); it = array2[(l - v) + 1]; for (r = l; r >= v && *r > c; r--) { *(r + 1) = *r; array2[(r - v) + 1] = array2[(r - v)]; } *(r + 1) = c; array2[(r - v) + 1] = it; } } } //############################################################################# //############################################################################# /**@name Ordered Triple Struct */ template < class S, class T, class U > class CoinTriple { public: /// First member of triple S first; /// Second member of triple T second; /// Third member of triple U third; public: /// Construct from ordered triple CoinTriple(const S &s, const T &t, const U &u) : first(s) , second(t) , third(u) { } }; //############################################################################# /**@name Comparisons on first element of two ordered triples */ //@{ /** Function operator. Returns true if t1.first < t2.first (i.e., increasing). */ template < class S, class T, class U > class CoinFirstLess_3 { public: /// Compare function inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { return t1.first < t2.first; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if t1.first > t2.first (i.e, decreasing). */ template < class S, class T, class U > class CoinFirstGreater_3 { public: /// Compare function inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { return t1.first > t2.first; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ template < class S, class T, class U > class CoinFirstAbsLess_3 { public: /// Compare function inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; return t1Abs < t2Abs; } }; //----------------------------------------------------------------------------- /** Function operator. Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ template < class S, class T, class U > class CoinFirstAbsGreater_3 { public: /// Compare function inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; return t1Abs > t2Abs; } }; //----------------------------------------------------------------------------- /** Function operator. Compare based on the entries of an external vector, i.e., returns true if vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to use this comparison operator .first must be a data type automatically convertible to int. */ template < class S, class T, class U, class V > class CoinExternalVectorFirstLess_3 { private: CoinExternalVectorFirstLess_3(); private: const V *vec_; public: inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { return vec_[t1.first] < vec_[t2.first]; } CoinExternalVectorFirstLess_3(const V *v) : vec_(v) { } }; //----------------------------------------------------------------------------- /** Function operator. Compare based on the entries of an external vector, i.e., returns true if vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to use this comparison operator .first must be a data type automatically convertible to int. */ template < class S, class T, class U, class V > class CoinExternalVectorFirstGreater_3 { private: CoinExternalVectorFirstGreater_3(); private: const V *vec_; public: inline bool operator()(const CoinTriple< S, T, U > &t1, const CoinTriple< S, T, U > &t2) const { return vec_[t1.first] > vec_[t2.first]; } CoinExternalVectorFirstGreater_3(const V *v) : vec_(v) { } }; //@} //############################################################################# /**@name Typedefs for sorting the entries of a packed vector based on an external vector. */ //@{ /// Sort packed vector in increasing order of the external vector typedef CoinExternalVectorFirstLess_3< int, int, double, double > CoinIncrSolutionOrdered; /// Sort packed vector in decreasing order of the external vector typedef CoinExternalVectorFirstGreater_3< int, int, double, double > CoinDecrSolutionOrdered; //@} //############################################################################# /** Sort a triple of containers.
Iter_S - iterator for first container
Iter_T - iterator for 2nd container
Iter_U - iterator for 3rd container
CoinCompare3 - class comparing CoinTriples
*/ #ifdef COIN_SORT_ARBITRARY_CONTAINERS template < class Iter_S, class Iter_T, class Iter_U, class CoinCompare3 > void CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst, const CoinCompare3 &tc) { typedef typename std::iterator_traits< Iter_S >::value_type S; typedef typename std::iterator_traits< Iter_T >::value_type T; typedef typename std::iterator_traits< Iter_U >::value_type U; const size_t len = coinDistance(sfirst, slast); if (len <= 1) return; typedef CoinTriple< S, T, U > STU_triple; STU_triple *x = static_cast< STU_triple * >(::operator new(len * sizeof(STU_triple))); int i = 0; Iter_S scurrent = sfirst; Iter_T tcurrent = tfirst; Iter_U ucurrent = ufirst; while (scurrent != slast) { new (x + i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); } std::sort(x, x + len, tc); scurrent = sfirst; tcurrent = tfirst; ucurrent = ufirst; for (i = 0; i < len; ++i) { *scurrent++ = x[i].first; *tcurrent++ = x[i].second; *ucurrent++ = x[i].third; } ::operator delete(x); } //----------------------------------------------------------------------------- template < class Iter_S, class Iter_T, class Iter_U > void CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst) { typedef typename std::iterator_traits< Iter_S >::value_type S; typedef typename std::iterator_traits< Iter_T >::value_type T; typedef typename std::iterator_traits< Iter_U >::value_type U; CoinSort_3(sfirts, slast, tfirst, ufirst, CoinFirstLess_3< S, T, U >()); } #else //======================================================================= template < class S, class T, class U, class CoinCompare3 > void CoinSort_3(S *sfirst, S *slast, T *tfirst, U *ufirst, const CoinCompare3 &tc) { const size_t len = coinDistance(sfirst, slast); if (len <= 1) return; typedef CoinTriple< S, T, U > STU_triple; STU_triple *x = static_cast< STU_triple * >(::operator new(len * sizeof(STU_triple))); size_t i = 0; S *scurrent = sfirst; T *tcurrent = tfirst; U *ucurrent = ufirst; while (scurrent != slast) { new (x + i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); } std::sort(x, x + len, tc); scurrent = sfirst; tcurrent = tfirst; ucurrent = ufirst; for (i = 0; i < len; ++i) { *scurrent++ = x[i].first; *tcurrent++ = x[i].second; *ucurrent++ = x[i].third; } ::operator delete(x); } //----------------------------------------------------------------------------- template < class S, class T, class U > void CoinSort_3(S *sfirst, S *slast, T *tfirst, U *ufirst) { CoinSort_3(sfirst, slast, tfirst, ufirst, CoinFirstLess_3< S, T, U >()); } #endif //############################################################################# #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */