#if !defined NXS_STL_ALGORITHM_EXTENSIONS #define NXS_STL_ALGORITHM_EXTENSIONS #include "phycas/phycas.h" #include #include #include #include #include #include // This file contains simple extensions to stl algorithms that // are listed in boost's unofficial wiki site's STLAlgorithmExtensions site // (or are very similar to the algorithm's suggested there. #include #include "ncl/misc/nxs_copy.hpp" /*---------------------------------------------------------------------------------------------------------------------- | copy_if | from Meyers, Effective STL p 156 */ template < typename InputIterator, typename OutputIterator, typename Predicate> OutputIterator copy_if(InputIterator beginIt, InputIterator endIt, OutputIterator destIt, Predicate p) { while (beginIt != endIt) { if (p(*beginIt)) { *destIt = *beginIt; ++destIt; } ++beginIt; } return destIt; } /*---------------------------------------------------------------------------------------------------------------------- | copy_if_ptr is like copy_if, but dereferences ptr before calling the predicate */ template < typename InputIterator, typename OutputIterator, typename Predicate> OutputIterator copy_if_ptr(InputIterator beginIt, InputIterator endIt, OutputIterator destIt, Predicate p) { while (beginIt != endIt) { if (p(**beginIt)) { *destIt = *beginIt; ++destIt; } ++beginIt; } return destIt; } template void AppendUnique(std::vector *dest, const std::vector toAppend) { typedef typename std::vector::const_iterator VecIt; for (VecIt newIt = toAppend.begin(); newIt != toAppend.end(); ++newIt) { VecIt dIt = find(dest->begin(), dest->end(), *newIt); if (dIt == dest->end()) dest->push_back(*newIt); } } /*---------------------------------------------------------------------------------------------------------------------- | Simple structure that stores the value of a variable at creation and restores it on destruction. | Makes it easier to write exception safe code in cases when a variable needs to be returned to it original value | before leaving a function. */ template class RestoreOnExit { T &ref; T orig; public: RestoreOnExit(T &r) : ref(r), orig(r){} ~RestoreOnExit() { ref = orig; } }; /*---------------------------------------------------------------------------------------------------------------------- | Similar to the Perl split function. Copies the original container of T objects into the list outList as | smaller containers broken at the specified value (which is omitted). | e.g. if the incoming string "usr/home/mine" and the splitAtVal was the char '/', then the resulting list would | have three strings "usr" "home" and "mine" */ template void split(const ORIG_CONTAINER &origContainer, T splitAtVal, std::list *outList) { typedef typename ORIG_CONTAINER::const_iterator OrigCIt; OrigCIt begIt = origContainer.begin(); const OrigCIt endIt = origContainer.end(); if (begIt == endIt) return; //empty container sent OrigCIt copyToIt; for (;;) { copyToIt = find(begIt, endIt, splitAtVal); if (begIt == copyToIt) outList->push_back(ORIG_CONTAINER()); else { outList->push_back(ORIG_CONTAINER(begIt,copyToIt)); begIt = copyToIt; } if (copyToIt == endIt) return; ++begIt; } } template inline bool all(InputIterator first, InputIterator last, Predicate p) { for (; first != last; ++first) { if (!p(*first)) return false; } return true; } /*---------------------------------------------------------------------------------------------------------------------- | Returns the sum of squares of all elements in the range. */ template T sum_sq(InputIterator start, const InputIterator finish, T initialV) { for (;start != finish; ++start) { T x = (*start)*(*start); // Comment from similar operation in praxis code DLS 22jun00: Use of the temporary variable here seems to be important for numerical accuracy (not sure why, but different code is generated in both PPC Metrowerks and Dec Alpha compilers) initialV += x; } return initialV; } /*---------------------------------------------------------------------------------------------------------------------- | Returns the sum of squares of all elements in the range. */ template void scale(InputIterator start, const InputIterator finish, const T multiplier) { for (;start != finish; ++start) *start *= multiplier; } /*---------------------------------------------------------------------------------------------------------------------- | Swaps the references to min_v and max_v if min_v < max_v */ template inline void pho_sort(T &min_v, T &max_v) { if (max_v < min_v) std::swap(min_v, max_v); } /*---------------------------------------------------------------------------------------------------------------------- | Swaps the references to min_v and max_v if min_v < max_v */ template inline void sum_sq(T &min_v, T &max_v) { if (max_v < min_v) std::swap(min_v, max_v); } /*---------------------------------------------------------------------------------------------------------------------- | Swaps the references to min_v and max_v if min_v < max_v */ template inline std::pair &swap_pair_order(std::pair &p) { std::swap(p.first, p.second); return p; } /*---------------------------------------------------------------------------------------------------------------------- | return Sum of fir[i]*sec[i] for i < n */ template inline T sum_of_array_product_n(const T *fir, const T *sec, unsigned n) { T temp = T(0); for (unsigned i = 0; i< n; ++i) temp += fir[i]*sec[i]; return temp; } template inline bool any(InputIterator first, InputIterator last, Predicate p) { for (; first != last; ++first) { if (p(*first)) return true; } return false; } template inline void replace_all(OutputIterator first, OutputIterator last, const T &new_val) { for (; first != last; ++first) *first = new_val; } //deals with const pointers template inline bool equals_n(InputIterator l, InputIterator r, unsigned nElements) { for (unsigned i = 0; i < nElements; ++i) if (!(*l == *r)) return false; return true; } template inline bool exact_count(InputIterator first, InputIterator last, T const&v, unsigned count = 1) { first = find(first, last, v); if (first == last) return (count == 0); unsigned nFound = 1; if (nFound <= count) { first = find(++first,last, v); if (first == last) return (nFound == count); else ++nFound; } return false; } template inline bool exact_count_if(InputIterator first, InputIterator last, Predicate pred, int count = 1) { first = find_if(first, last, pred); if (first == last) return (count == 0); unsigned nFound = 1; if (nFound <= count) { first = find_if(++first,last, pred); if (first == last) return (nFound == count); else ++nFound; } return false; } template inline bool exists_and_only(InputIterator first, InputIterator last, T const&v) { first = find(first, last, v); return (first != last && find(++first,last, v) == last); } template inline bool exists_and_only_if(InputIterator first, InputIterator last, Predicate pred) { first = find_if(first, last, pred); return (first != last && find_if(++first,last, pred) == last); } //Performs f() on any element elem in [first, last) where pred(elem) is true template UnaryFunction for_each_if( InputIterator first, InputIterator last, Predicate pred, UnaryFunction f) { for(;first != last; ++first) { if (pred(*first)) f(*first); } return f; } namespace ncl { class XEmptyContainer: public std::invalid_argument { public: XEmptyContainer(const std::string & msg):invalid_argument(msg){} }; #if 1 /// Calculates the mean in double precision. template double calc_mean_dbl_unchecked(const std::vector & container) { return (double) std::accumulate(container.begin(), container.end(), T(0)) /(double) container.size(); } /// Calculates the mean in double precision. template double calc_mean_dbl(const std::vector & container) { if (container.empty()) throw XEmptyContainer("empty container in calc_mean_dbl"); return calc_mean_dbl_unchecked(container); } template T sort_to_get_median_unchecked(std::vector & container) /// should be specialized for sorted containers { std::sort(container.begin(), container.end()); return container[(unsigned) container.size()/2]; } template T sort_to_get_median(std::vector & container) /// should be specialized for sorted containers { if (container.empty()) throw XEmptyContainer("empty container in sort_to_get_median"); return sort_to_get_median_unchecked(container); } #else /// Calculates the mean in double precision. template