/* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ #ifndef ALGO_H #define ALGO_H #include #include #include #include #include #include #include template inline const T& __median(const T& a, const T& b, const T& c) { if (a < b) if (b < c) return b; else if (a < c) return c; else return a; else if (a < c) return a; else if (b < c) return c; else return b; } template inline const T& __median(const T& a, const T& b, const T& c, Compare comp) { if (comp(a, b)) if (comp(b, c)) return b; else if (comp(a, c)) return c; else return a; else if (comp(a, c)) return a; else if (comp(b, c)) return c; else return b; } template Function for_each(InputIterator first, InputIterator last, Function f) { while (first != last) f(*first++); return f; } template InputIterator find(InputIterator first, InputIterator last, const T& value) { while (first != last && *first != value) ++first; return first; } template InputIterator find_if(InputIterator first, InputIterator last, Predicate pred) { while (first != last && !pred(*first)) ++first; return first; } template ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last) { if (first == last) return last; ForwardIterator next = first; while(++next != last) { if (*first == *next) return first; first = next; } return last; } template ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred) { if (first == last) return last; ForwardIterator next = first; while(++next != last) { if (binary_pred(*first, *next)) return first; first = next; } return last; } template void count(InputIterator first, InputIterator last, const T& value, Size& n) { while (first != last) if (*first++ == value) ++n; } template void count_if(InputIterator first, InputIterator last, Predicate pred, Size& n) { while (first != last) if (pred(*first++)) ++n; } template ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Distance1*, Distance2*) { Distance1 d1 = 0; distance(first1, last1, d1); Distance2 d2 = 0; distance(first2, last2, d2); if (d1 < d2) return last1; ForwardIterator1 current1 = first1; ForwardIterator2 current2 = first2; while (current2 != last2) if (*current1++ != *current2++) if (d1-- == d2) return last1; else { current1 = ++first1; current2 = first2; } return (current2 == last2) ? first1 : last1; } template inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { return __search(first1, last1, first2, last2, distance_type(first1), distance_type(first2)); } template ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate binary_pred, Distance1*, Distance2*) { Distance1 d1 = 0; distance(first1, last1, d1); Distance2 d2 = 0; distance(first2, last2, d2); if (d1 < d2) return last1; ForwardIterator1 current1 = first1; ForwardIterator2 current2 = first2; while (current2 != last2) if (!binary_pred(*current1++, *current2++)) if (d1-- == d2) return last1; else { current1 = ++first1; current2 = first2; } return (current2 == last2) ? first1 : last1; } template inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate binary_pred) { return __search(first1, last1, first2, last2, binary_pred, distance_type(first1), distance_type(first2)); } template ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { while (first1 != last1) iter_swap(first1++, first2++); return first2; } template OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op) { while (first != last) *result++ = op(*first++); return result; } template OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op) { while (first1 != last1) *result++ = binary_op(*first1++, *first2++); return result; } template void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) { while (first != last) { if (*first == old_value) *first = new_value; ++first; } } template void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value) { while (first != last) { if (pred(*first)) *first = new_value; ++first; } } template OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value) { while (first != last) { *result++ = *first == old_value ? new_value : *first; ++first; } return result; } template OutputIterator replace_copy_if(Iterator first, Iterator last, OutputIterator result, Predicate pred, const T& new_value) { while (first != last) { *result++ = pred(*first) ? new_value : *first; ++first; } return result; } template void generate(ForwardIterator first, ForwardIterator last, Generator gen) { while (first != last) *first++ = gen(); } template OutputIterator generate_n(OutputIterator first, Size n, Generator gen) { while (n-- > 0) *first++ = gen(); return first; } template OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value) { while (first != last) { if (*first != value) *result++ = *first; ++first; } return result; } template OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred) { while (first != last) { if (!pred(*first)) *result++ = *first; ++first; } return result; } template ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value) { first = find(first, last, value); ForwardIterator next = first; return first == last ? first : remove_copy(++next, last, first, value); } template ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred) { first = find_if(first, last, pred); ForwardIterator next = first; return first == last ? first : remove_copy_if(++next, last, first, pred); } template ForwardIterator __unique_copy(InputIterator first, InputIterator last, ForwardIterator result, forward_iterator_tag) { *result = *first; while (++first != last) if (*result != *first) *++result = *first; return ++result; } template inline BidirectionalIterator __unique_copy(InputIterator first, InputIterator last, BidirectionalIterator result, bidirectional_iterator_tag) { return __unique_copy(first, last, result, forward_iterator_tag()); } template inline RandomAccessIterator __unique_copy(InputIterator first, InputIterator last, RandomAccessIterator result, random_access_iterator_tag) { return __unique_copy(first, last, result, forward_iterator_tag()); } template OutputIterator __unique_copy(InputIterator first, InputIterator last, OutputIterator result, T*) { T value = *first; *result = value; while (++first != last) if (value != *first) { value = *first; *++result = value; } return ++result; } template inline OutputIterator __unique_copy(InputIterator first, InputIterator last, OutputIterator result, output_iterator_tag) { return __unique_copy(first, last, result, value_type(first)); } template inline OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) return result; return __unique_copy(first, last, result, iterator_category(result)); } template ForwardIterator __unique_copy(InputIterator first, InputIterator last, ForwardIterator result, BinaryPredicate binary_pred, forward_iterator_tag) { *result = *first; while (++first != last) if (!binary_pred(*result, *first)) *++result = *first; return ++result; } template inline BidirectionalIterator __unique_copy(InputIterator first, InputIterator last, BidirectionalIterator result, BinaryPredicate binary_pred, bidirectional_iterator_tag) { return __unique_copy(first, last, result, binary_pred, forward_iterator_tag()); } template inline RandomAccessIterator __unique_copy(InputIterator first, InputIterator last, RandomAccessIterator result, BinaryPredicate binary_pred, random_access_iterator_tag) { return __unique_copy(first, last, result, binary_pred, forward_iterator_tag()); } template OutputIterator __unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred, T*) { T value = *first; *result = value; while (++first != last) if (!binary_pred(value, *first)) { value = *first; *++result = value; } return ++result; } template inline OutputIterator __unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred, output_iterator_tag) { return __unique_copy(first, last, result, binary_pred, value_type(first)); } template inline OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred) { if (first == last) return result; return __unique_copy(first, last, result, binary_pred, iterator_category(result)); } template ForwardIterator unique(ForwardIterator first, ForwardIterator last) { first = adjacent_find(first, last); return unique_copy(first, last, first); } template ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred) { first = adjacent_find(first, last, binary_pred); return unique_copy(first, last, first, binary_pred); } template void __reverse(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag) { while (true) if (first == last || first == --last) return; else iter_swap(first++, last); } template void __reverse(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) { while (first < last) iter_swap(first++, --last); } template inline void reverse(BidirectionalIterator first, BidirectionalIterator last) { __reverse(first, last, iterator_category(first)); } template OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result) { while (first != last) *result++ = *--last; return result; } template void __rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Distance*, forward_iterator_tag) { for (ForwardIterator i = middle; ;) { iter_swap(first++, i++); if (first == middle) { if (i == last) return; middle = i; } else if (i == last) i = middle; } } template void __rotate(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance*, bidirectional_iterator_tag) { reverse(first, middle); reverse(middle, last); reverse(first, last); } template EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n) { while (n != 0) { EuclideanRingElement t = m % n; m = n; n = t; } return m; } template void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator initial, Distance shift, T*) { T value = *initial; RandomAccessIterator ptr1 = initial; RandomAccessIterator ptr2 = ptr1 + shift; while (ptr2 != initial) { *ptr1 = *ptr2; ptr1 = ptr2; if (last - ptr2 > shift) ptr2 += shift; else ptr2 = first + (shift - (last - ptr2)); } *ptr1 = value; } template void __rotate(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Distance*, random_access_iterator_tag) { Distance n = __gcd(last - first, middle - first); while (n--) __rotate_cycle(first, last, first + n, middle - first, value_type(first)); } template inline void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) { if (first == middle || middle == last) return; __rotate(first, middle, last, distance_type(first), iterator_category(first)); } template OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) { return copy(first, middle, copy(middle, last, result)); } unsigned long __long_random(unsigned long); template void __random_shuffle(RandomAccessIterator first, RandomAccessIterator last, Distance*) { if (first == last) return; for (RandomAccessIterator i = first + 1; i != last; ++i) iter_swap(i, first + Distance(__long_random((i - first) + 1))); } template inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last) { __random_shuffle(first, last, distance_type(first)); } template void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand) { if (first == last) return; for (RandomAccessIterator i = first + 1; i != last; ++i) iter_swap(i, first + rand((i - first) + 1)); } template BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred) { while (true) { while (true) if (first == last) return first; else if (pred(*first)) ++first; else break; --last; while (true) if (first == last) return first; else if (!pred(*last)) --last; else break; iter_swap(first, last); ++first; } } template ForwardIterator __inplace_stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred, Distance len) { if (len == 1) return pred(*first) ? last : first; ForwardIterator middle = first; advance(middle, len / 2); ForwardIterator first_cut = __inplace_stable_partition(first, middle, pred, len / 2); ForwardIterator second_cut = __inplace_stable_partition(middle, last, pred, len - len / 2); rotate(first_cut, middle, second_cut); len = 0; distance(middle, second_cut, len); advance(first_cut, len); return first_cut; } template ForwardIterator __stable_partition_adaptive(ForwardIterator first, ForwardIterator last, Predicate pred, Distance len, Pointer buffer, Distance buffer_size, Distance& fill_pointer, T*) { if (len <= buffer_size) { len = 0; ForwardIterator result1 = first; Pointer result2 = buffer; while (first != last && len < fill_pointer) if (pred(*first)) *result1++ = *first++; else { *result2++ = *first++; ++len; } if (first != last) { raw_storage_iterator result3 = result2; while (first != last) if (pred(*first)) *result1++ = *first++; else { *result3++ = *first++; ++len; } fill_pointer = len; } copy(buffer, buffer + len, result1); return result1; } ForwardIterator middle = first; advance(middle, len / 2); ForwardIterator first_cut = __stable_partition_adaptive (first, middle, pred, len / 2, buffer, buffer_size, fill_pointer, (T*)0); ForwardIterator second_cut = __stable_partition_adaptive (middle, last, pred, len - len / 2, buffer, buffer_size, fill_pointer, (T*)0); rotate(first_cut, middle, second_cut); len = 0; distance(middle, second_cut, len); advance(first_cut, len); return first_cut; } template ForwardIterator __stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred, Distance len, pair p) { if (p.first == 0) return __inplace_stable_partition(first, last, pred, len); Distance fill_pointer = 0; ForwardIterator result = __stable_partition_adaptive(first, last, pred, len, p.first, p.second, fill_pointer, value_type(first)); destroy(p.first, p.first + fill_pointer); return_temporary_buffer(p.first); return result; } template inline ForwardIterator __stable_partition_aux(ForwardIterator first, ForwardIterator last, Predicate pred, Distance*) { Distance len = 0; distance(first, last, len); return __stable_partition(first, last, pred, len, get_temporary_buffer(len, value_type(first))); } template inline ForwardIterator stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred) { return __stable_partition_aux(first, last, pred, distance_type(first)); } template RandomAccessIterator __unguarded_partition(RandomAccessIterator first, RandomAccessIterator last, T pivot) { while (1) { while (*first < pivot) ++first; --last; while (pivot < *last) --last; if (!(first < last)) return first; iter_swap(first, last); ++first; } } template RandomAccessIterator __unguarded_partition(RandomAccessIterator first, RandomAccessIterator last, T pivot, Compare comp) { while (1) { while (comp(*first, pivot)) ++first; --last; while (comp(pivot, *last)) --last; if (!(first < last)) return first; iter_swap(first, last); ++first; } } const int __stl_threshold = 16; template void __quick_sort_loop_aux(RandomAccessIterator first, RandomAccessIterator last, T*) { while (last - first > __stl_threshold) { RandomAccessIterator cut = __unguarded_partition (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1)))); if (cut - first >= last - cut) { __quick_sort_loop(cut, last); last = cut; } else { __quick_sort_loop(first, cut); first = cut; } } } template inline void __quick_sort_loop(RandomAccessIterator first, RandomAccessIterator last) { __quick_sort_loop_aux(first, last, value_type(first)); } template void __quick_sort_loop_aux(RandomAccessIterator first, RandomAccessIterator last, T*, Compare comp) { while (last - first > __stl_threshold) { RandomAccessIterator cut = __unguarded_partition (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1), comp)), comp); if (cut - first >= last - cut) { __quick_sort_loop(cut, last, comp); last = cut; } else { __quick_sort_loop(first, cut, comp); first = cut; } } } template inline void __quick_sort_loop(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { __quick_sort_loop_aux(first, last, value_type(first), comp); } template void __unguarded_linear_insert(RandomAccessIterator last, T value) { RandomAccessIterator next = last; --next; while (value < *next) { *last = *next; last = next--; } *last = value; } template void __unguarded_linear_insert(RandomAccessIterator last, T value, Compare comp) { RandomAccessIterator next = last; --next; while (comp(value , *next)) { *last = *next; last = next--; } *last = value; } template inline void __linear_insert(RandomAccessIterator first, RandomAccessIterator last, T*) { T value = *last; if (value < *first) { copy_backward(first, last, last + 1); *first = value; } else __unguarded_linear_insert(last, value); } template inline void __linear_insert(RandomAccessIterator first, RandomAccessIterator last, T*, Compare comp) { T value = *last; if (comp(value, *first)) { copy_backward(first, last, last + 1); *first = value; } else __unguarded_linear_insert(last, value, comp); } template void __insertion_sort(RandomAccessIterator first, RandomAccessIterator last) { if (first == last) return; for (RandomAccessIterator i = first + 1; i != last; ++i) __linear_insert(first, i, value_type(first)); } template void __insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { if (first == last) return; for (RandomAccessIterator i = first + 1; i != last; ++i) __linear_insert(first, i, value_type(first), comp); } template void __unguarded_insertion_sort_aux(RandomAccessIterator first, RandomAccessIterator last, T*) { for (RandomAccessIterator i = first; i != last; ++i) __unguarded_linear_insert(i, T(*i)); } template inline void __unguarded_insertion_sort(RandomAccessIterator first, RandomAccessIterator last) { __unguarded_insertion_sort_aux(first, last, value_type(first)); } template void __unguarded_insertion_sort_aux(RandomAccessIterator first, RandomAccessIterator last, T*, Compare comp) { for (RandomAccessIterator i = first; i != last; ++i) __unguarded_linear_insert(i, T(*i), comp); } template inline void __unguarded_insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { __unguarded_insertion_sort_aux(first, last, value_type(first), comp); } template void __final_insertion_sort(RandomAccessIterator first, RandomAccessIterator last) { if (last - first > __stl_threshold) { __insertion_sort(first, first + __stl_threshold); __unguarded_insertion_sort(first + __stl_threshold, last); } else __insertion_sort(first, last); } template void __final_insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { if (last - first > __stl_threshold) { __insertion_sort(first, first + __stl_threshold, comp); __unguarded_insertion_sort(first + __stl_threshold, last, comp); } else __insertion_sort(first, last, comp); } template void sort(RandomAccessIterator first, RandomAccessIterator last) { __quick_sort_loop(first, last); __final_insertion_sort(first, last); } template void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { __quick_sort_loop(first, last, comp); __final_insertion_sort(first, last, comp); } template void __inplace_stable_sort(RandomAccessIterator first, RandomAccessIterator last) { if (last - first < 15) { __insertion_sort(first, last); return; } RandomAccessIterator middle = first + (last - first) / 2; __inplace_stable_sort(first, middle); __inplace_stable_sort(middle, last); __merge_without_buffer(first, middle, last, middle - first, last - middle); } template void __inplace_stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { if (last - first < 15) { __insertion_sort(first, last, comp); return; } RandomAccessIterator middle = first + (last - first) / 2; __inplace_stable_sort(first, middle, comp); __inplace_stable_sort(middle, last, comp); __merge_without_buffer(first, middle, last, middle - first, last - middle, comp); } template void __merge_sort_loop(RandomAccessIterator1 first, RandomAccessIterator1 last, RandomAccessIterator2 result, Distance step_size) { Distance two_step = 2 * step_size; while (last - first >= two_step) { result = merge(first, first + step_size, first + step_size, first + two_step, result); first += two_step; } step_size = min(Distance(last - first), step_size); merge(first, first + step_size, first + step_size, last, result); } template void __merge_sort_loop(RandomAccessIterator1 first, RandomAccessIterator1 last, RandomAccessIterator2 result, Distance step_size, Compare comp) { Distance two_step = 2 * step_size; while (last - first >= two_step) { result = merge(first, first + step_size, first + step_size, first + two_step, result, comp); first += two_step; } step_size = min(Distance(last - first), step_size); merge(first, first + step_size, first + step_size, last, result, comp); } const int __stl_chunk_size = 7; template void __chunk_insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Distance chunk_size) { while (last - first >= chunk_size) { __insertion_sort(first, first + chunk_size); first += chunk_size; } __insertion_sort(first, last); } template void __chunk_insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Distance chunk_size, Compare comp) { while (last - first >= chunk_size) { __insertion_sort(first, first + chunk_size, comp); first += chunk_size; } __insertion_sort(first, last, comp); } template void __merge_sort_with_buffer(RandomAccessIterator first, RandomAccessIterator last, Pointer buffer, Distance*, T*) { Distance len = last - first; Pointer buffer_last = buffer + len; Distance step_size = __stl_chunk_size; __chunk_insertion_sort(first, last, step_size); while (step_size < len) { __merge_sort_loop(first, last, buffer, step_size); step_size *= 2; __merge_sort_loop(buffer, buffer_last, first, step_size); step_size *= 2; } } template void __merge_sort_with_buffer(RandomAccessIterator first, RandomAccessIterator last, Pointer buffer, Distance*, T*, Compare comp) { Distance len = last - first; Pointer buffer_last = buffer + len; Distance step_size = __stl_chunk_size; __chunk_insertion_sort(first, last, step_size, comp); while (step_size < len) { __merge_sort_loop(first, last, buffer, step_size, comp); step_size *= 2; __merge_sort_loop(buffer, buffer_last, first, step_size, comp); step_size *= 2; } } template void __stable_sort_adaptive(RandomAccessIterator first, RandomAccessIterator last, Pointer buffer, Distance buffer_size, T*) { Distance len = (last - first + 1) / 2; RandomAccessIterator middle = first + len; if (len > buffer_size) { __stable_sort_adaptive(first, middle, buffer, buffer_size, (T*)0); __stable_sort_adaptive(middle, last, buffer, buffer_size, (T*)0); } else { __merge_sort_with_buffer(first, middle, buffer, (Distance*)0, (T*)0); __merge_sort_with_buffer(middle, last, buffer, (Distance*)0, (T*)0); } __merge_adaptive(first, middle, last, Distance(middle - first), Distance(last - middle), buffer, buffer_size, (T*)0); } template void __stable_sort_adaptive(RandomAccessIterator first, RandomAccessIterator last, Pointer buffer, Distance buffer_size, T*, Compare comp) { Distance len = (last - first + 1) / 2; RandomAccessIterator middle = first + len; if (len > buffer_size) { __stable_sort_adaptive(first, middle, buffer, buffer_size, (T*)0, comp); __stable_sort_adaptive(middle, last, buffer, buffer_size, (T*)0, comp); } else { __merge_sort_with_buffer(first, middle, buffer, (Distance*)0, (T*)0, comp); __merge_sort_with_buffer(middle, last, buffer, (Distance*)0, (T*)0, comp); } __merge_adaptive(first, middle, last, Distance(middle - first), Distance(last - middle), buffer, buffer_size, (T*)0, comp); } template inline void __stable_sort(RandomAccessIterator first, RandomAccessIterator last, pair p, T*) { if (p.first == 0) { __inplace_stable_sort(first, last); return; } Distance len = min(p.second, last - first); copy(first, first + len, raw_storage_iterator(p.first)); __stable_sort_adaptive(first, last, p.first, p.second, (T*)0); destroy(p.first, p.first + len); return_temporary_buffer(p.first); } template inline void __stable_sort(RandomAccessIterator first, RandomAccessIterator last, pair p, T*, Compare comp) { if (p.first == 0) { __inplace_stable_sort(first, last, comp); return; } Distance len = min(p.second, last - first); copy(first, first + len, raw_storage_iterator(p.first)); __stable_sort_adaptive(first, last, p.first, p.second, (T*)0, comp); destroy(p.first, p.first + len); return_temporary_buffer(p.first); } template inline void __stable_sort_aux(RandomAccessIterator first, RandomAccessIterator last, T*, Distance*) { __stable_sort(first, last, get_temporary_buffer(Distance(last - first), (T*)0), (T*)0); } template inline void __stable_sort_aux(RandomAccessIterator first, RandomAccessIterator last, T*, Distance*, Compare comp) { __stable_sort(first, last, get_temporary_buffer(Distance(last - first), (T*)0), (T*)0, comp); } template inline void stable_sort(RandomAccessIterator first, RandomAccessIterator last) { __stable_sort_aux(first, last, value_type(first), distance_type(first)); } template inline void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) { __stable_sort_aux(first, last, value_type(first), distance_type(first), comp); } template void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, T*) { make_heap(first, middle); for (RandomAccessIterator i = middle; i < last; ++i) if (*i < *first) __pop_heap(first, middle, i, T(*i), distance_type(first)); sort_heap(first, middle); } template inline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) { __partial_sort(first, middle, last, value_type(first)); } template void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, T*, Compare comp) { make_heap(first, middle, comp); for (RandomAccessIterator i = middle; i < last; ++i) if (comp(*i, *first)) __pop_heap(first, middle, i, T(*i), comp, distance_type(first)); sort_heap(first, middle, comp); } template inline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp) { __partial_sort(first, middle, last, value_type(first), comp); } template RandomAccessIterator __partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Distance*, T*) { if (result_first == result_last) return result_last; RandomAccessIterator result_real_last = result_first; while(first != last && result_real_last != result_last) *result_real_last++ = *first++; make_heap(result_first, result_real_last); while (first != last) { if (*first < *result_first) __adjust_heap(result_first, Distance(0), Distance(result_real_last - result_first), T(*first)); ++first; } sort_heap(result_first, result_real_last); return result_real_last; } template inline RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last) { return __partial_sort_copy(first, last, result_first, result_last, distance_type(result_first), value_type(first)); } template RandomAccessIterator __partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp, Distance*, T*) { if (result_first == result_last) return result_last; RandomAccessIterator result_real_last = result_first; while(first != last && result_real_last != result_last) *result_real_last++ = *first++; make_heap(result_first, result_real_last, comp); while (first != last) { if (comp(*first, *result_first)) __adjust_heap(result_first, Distance(0), Distance(result_real_last - result_first), T(*first), comp); ++first; } sort_heap(result_first, result_real_last, comp); return result_real_last; } template inline RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp) { return __partial_sort_copy(first, last, result_first, result_last, comp, distance_type(result_first), value_type(first)); } template void __nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, T*) { while (last - first > 3) { RandomAccessIterator cut = __unguarded_partition (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1)))); if (cut <= nth) first = cut; else last = cut; } __insertion_sort(first, last); } template inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) { __nth_element(first, nth, last, value_type(first)); } template void __nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, T*, Compare comp) { while (last - first > 3) { RandomAccessIterator cut = __unguarded_partition (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1), comp)), comp); if (cut <= nth) first = cut; else last = cut; } __insertion_sort(first, last, comp); } template inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp) { __nth_element(first, nth, last, value_type(first), comp); } template ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (*middle < value) { first = middle; ++first; len = len - half - 1; } else len = half; } return first; } template inline ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, bidirectional_iterator_tag) { return __lower_bound(first, last, value, (Distance*)0, forward_iterator_tag()); } template RandomAccessIterator __lower_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle; while (len > 0) { half = len / 2; middle = first + half; if (*middle < value) { first = middle + 1; len = len - half - 1; } else len = half; } return first; } template inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value) { return __lower_bound(first, last, value, distance_type(first), iterator_category(first)); } template ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (comp(*middle, value)) { first = middle; ++first; len = len - half - 1; } else len = half; } return first; } template inline ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, bidirectional_iterator_tag) { return __lower_bound(first, last, value, comp, (Distance*)0, forward_iterator_tag()); } template RandomAccessIterator __lower_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Compare comp, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle; while (len > 0) { half = len / 2; middle = first + half; if (comp(*middle, value)) { first = middle + 1; len = len - half - 1; } else len = half; } return first; } template inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) { return __lower_bound(first, last, value, comp, distance_type(first), iterator_category(first)); } template ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (value < *middle) len = half; else { first = middle; ++first; len = len - half - 1; } } return first; } template inline ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, bidirectional_iterator_tag) { return __upper_bound(first, last, value, (Distance*)0, forward_iterator_tag()); } template RandomAccessIterator __upper_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle; while (len > 0) { half = len / 2; middle = first + half; if (value < *middle) len = half; else { first = middle + 1; len = len - half - 1; } } return first; } template inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value) { return __upper_bound(first, last, value, distance_type(first), iterator_category(first)); } template ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (comp(value, *middle)) len = half; else { first = middle; ++first; len = len - half - 1; } } return first; } template inline ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, bidirectional_iterator_tag) { return __upper_bound(first, last, value, comp, (Distance*)0, forward_iterator_tag()); } template RandomAccessIterator __upper_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Compare comp, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle; while (len > 0) { half = len / 2; middle = first + half; if (comp(value, *middle)) len = half; else { first = middle + 1; len = len - half - 1; } } return first; } template inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) { return __upper_bound(first, last, value, comp, distance_type(first), iterator_category(first)); } template pair __equal_range(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle, left, right; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (*middle < value) { first = middle; ++first; len = len - half - 1; } else if (value < *middle) len = half; else { left = lower_bound(first, middle, value); advance(first, len); right = upper_bound(++middle, first, value); return pair(left, right); } } return pair(first, first); } template inline pair __equal_range(ForwardIterator first, ForwardIterator last, const T& value, Distance*, bidirectional_iterator_tag) { return __equal_range(first, last, value, (Distance*)0, forward_iterator_tag()); } template pair __equal_range(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle, left, right; while (len > 0) { half = len / 2; middle = first + half; if (*middle < value) { first = middle + 1; len = len - half - 1; } else if (value < *middle) len = half; else { left = lower_bound(first, middle, value); right = upper_bound(++middle, first + len, value); return pair(left, right); } } return pair(first, first); } template inline pair equal_range(ForwardIterator first, ForwardIterator last, const T& value) { return __equal_range(first, last, value, distance_type(first), iterator_category(first)); } template pair __equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, forward_iterator_tag) { Distance len = 0; distance(first, last, len); Distance half; ForwardIterator middle, left, right; while (len > 0) { half = len / 2; middle = first; advance(middle, half); if (comp(*middle, value)) { first = middle; ++first; len = len - half - 1; } else if (comp(value, *middle)) len = half; else { left = lower_bound(first, middle, value, comp); advance(first, len); right = upper_bound(++middle, first, value, comp); return pair(left, right); } } return pair(first, first); } template inline pair __equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, bidirectional_iterator_tag) { return __equal_range(first, last, value, comp, (Distance*)0, forward_iterator_tag()); } template pair __equal_range(RandomAccessIterator first, RandomAccessIterator last, const T& value, Compare comp, Distance*, random_access_iterator_tag) { Distance len = last - first; Distance half; RandomAccessIterator middle, left, right; while (len > 0) { half = len / 2; middle = first + half; if (comp(*middle, value)) { first = middle + 1; len = len - half - 1; } else if (comp(value, *middle)) len = half; else { left = lower_bound(first, middle, value, comp); right = upper_bound(++middle, first + len, value, comp); return pair(left, right); } } return pair(first, first); } template inline pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) { return __equal_range(first, last, value, comp, distance_type(first), iterator_category(first)); } template bool binary_search(ForwardIterator first, ForwardIterator last, const T& value) { ForwardIterator i = lower_bound(first, last, value); return i != last && !(value < *i); } template bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) { ForwardIterator i = lower_bound(first, last, value, comp); return i != last && !comp(value, *i); } template OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { while (first1 != last1 && first2 != last2) if (*first2 < *first1) *result++ = *first2++; else *result++ = *first1++; return copy(first2, last2, copy(first1, last1, result)); } template OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first2, *first1)) *result++ = *first2++; else *result++ = *first1++; return copy(first2, last2, copy(first1, last1, result)); } template void __merge_without_buffer(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2) { if (len1 == 0 || len2 == 0) return; if (len1 + len2 == 2) { if (*middle < *first) iter_swap(first, middle); return; } BidirectionalIterator first_cut = first; BidirectionalIterator second_cut = middle; Distance len11 = 0; Distance len22 = 0; if (len1 > len2) { len11 = len1 / 2; advance(first_cut, len11); second_cut = lower_bound(middle, last, *first_cut); distance(middle, second_cut, len22); } else { len22 = len2 / 2; advance(second_cut, len22); first_cut = upper_bound(first, middle, *second_cut); distance(first, first_cut, len11); } rotate(first_cut, middle, second_cut); BidirectionalIterator new_middle = first_cut; advance(new_middle, len22); __merge_without_buffer(first, first_cut, new_middle, len11, len22); __merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22); } template void __merge_without_buffer(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2, Compare comp) { if (len1 == 0 || len2 == 0) return; if (len1 + len2 == 2) { if (comp(*middle, *first)) iter_swap(first, middle); return; } BidirectionalIterator first_cut = first; BidirectionalIterator second_cut = middle; Distance len11 = 0; Distance len22 = 0; if (len1 > len2) { len11 = len1 / 2; advance(first_cut, len11); second_cut = lower_bound(middle, last, *first_cut, comp); distance(middle, second_cut, len22); } else { len22 = len2 / 2; advance(second_cut, len22); first_cut = upper_bound(first, middle, *second_cut, comp); distance(first, first_cut, len11); } rotate(first_cut, middle, second_cut); BidirectionalIterator new_middle = first_cut; advance(new_middle, len22); __merge_without_buffer(first, first_cut, new_middle, len11, len22, comp); __merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22, comp); } template OutputIterator __borland_bugfix_copy(InputIterator first, InputIterator last, OutputIterator result) { // this is used in __rotate_adaptive to work around some obscure Borland // bug. It is the same as copy, but with a different (and appropriate) name. while (first != last) *result++ = *first++; return result; } template BidirectionalIterator1 __rotate_adaptive(BidirectionalIterator1 first, BidirectionalIterator1 middle, BidirectionalIterator1 last, Distance len1, Distance len2, BidirectionalIterator2 buffer, Distance buffer_size) { BidirectionalIterator2 buffer_end; if (len1 > len2 && len2 <= buffer_size) { buffer_end = __borland_bugfix_copy(middle, last, buffer); copy_backward(first, middle, last); return copy(buffer, buffer_end, first); } else if (len1 <= buffer_size) { buffer_end = __borland_bugfix_copy(first, middle, buffer); copy(middle, last, first); return copy_backward(buffer, buffer_end, last); } else { rotate(first, middle, last); advance(first, len2); return first; } } template BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIterator2 first2, BidirectionalIterator2 last2, BidirectionalIterator3 result) { if (first1 == last1) return copy_backward(first2, last2, result); if (first2 == last2) return copy_backward(first1, last1, result); --last1; --last2; while (true) { if (*last2 < *last1) { *--result = *last1; if (first1 == last1) return copy_backward(first2, ++last2, result); --last1; } else { *--result = *last2; if (first2 == last2) return copy_backward(first1, ++last1, result); --last2; } } } template BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIterator2 first2, BidirectionalIterator2 last2, BidirectionalIterator3 result, Compare comp) { if (first1 == last1) return copy_backward(first2, last2, result); if (first2 == last2) return copy_backward(first1, last1, result); --last1; --last2; while (true) { if (comp(*last2, *last1)) { *--result = *last1; if (first1 == last1) return copy_backward(first2, ++last2, result); --last1; } else { *--result = *last2; if (first2 == last2) return copy_backward(first1, ++last1, result); --last2; } } } template void __merge_adaptive(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2, Pointer buffer, Distance buffer_size, T*) { if (len1 <= len2 && len1 <= buffer_size) { Pointer end_buffer = copy(first, middle, buffer); merge(buffer, end_buffer, middle, last, first); } else if (len2 <= buffer_size) { Pointer end_buffer = copy(middle, last, buffer); __merge_backward(first, middle, buffer, end_buffer, last); } else { BidirectionalIterator first_cut = first; BidirectionalIterator second_cut = middle; Distance len11 = 0; Distance len22 = 0; if (len1 > len2) { len11 = len1 / 2; advance(first_cut, len11); second_cut = lower_bound(middle, last, *first_cut); distance(middle, second_cut, len22); } else { len22 = len2 / 2; advance(second_cut, len22); first_cut = upper_bound(first, middle, *second_cut); distance(first, first_cut, len11); } BidirectionalIterator new_middle = __rotate_adaptive(first_cut, middle, second_cut, len1 - len11, len22, buffer, buffer_size); __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, buffer_size, (T*)0); __merge_adaptive(new_middle, second_cut, last, len1 - len11, len2 - len22, buffer, buffer_size, (T*)0); } } template void __merge_adaptive(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2, Pointer buffer, Distance buffer_size, T*, Compare comp) { if (len1 <= len2 && len1 <= buffer_size) { Pointer end_buffer = copy(first, middle, buffer); merge(buffer, end_buffer, middle, last, first, comp); } else if (len2 <= buffer_size) { Pointer end_buffer = copy(middle, last, buffer); __merge_backward(first, middle, buffer, end_buffer, last, comp); } else { BidirectionalIterator first_cut = first; BidirectionalIterator second_cut = middle; Distance len11 = 0; Distance len22 = 0; if (len1 > len2) { len11 = len1 / 2; advance(first_cut, len11); second_cut = lower_bound(middle, last, *first_cut, comp); distance(middle, second_cut, len22); } else { len22 = len2 / 2; advance(second_cut, len22); first_cut = upper_bound(first, middle, *second_cut, comp); distance(first, first_cut, len11); } BidirectionalIterator new_middle = __rotate_adaptive(first_cut, middle, second_cut, len1 - len11, len22, buffer, buffer_size); __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, buffer_size, (T*)0, comp); __merge_adaptive(new_middle, second_cut, last, len1 - len11, len2 - len22, buffer, buffer_size, (T*)0, comp); } } template void __inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2, pair p, T*) { if (p.first == 0) { __merge_without_buffer(first, middle, last, len1, len2); return; } Distance len = min(p.second, len1 + len2); fill_n(raw_storage_iterator(p.first), len, *first); __merge_adaptive(first, middle, last, len1, len2, p.first, p.second, (T*)0); destroy(p.first, p.first + len); return_temporary_buffer(p.first); } template void __inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance len1, Distance len2, pair p, T*, Compare comp) { if (p.first == 0) { __merge_without_buffer(first, middle, last, len1, len2, comp); return; } Distance len = min(p.second, len1 + len2); fill_n(raw_storage_iterator(p.first), len, *first); __merge_adaptive(first, middle, last, len1, len2, p.first, p.second, (T*)0, comp); destroy(p.first, p.first + len); return_temporary_buffer(p.first); } template inline void __inplace_merge_aux(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, T*, Distance*) { Distance len1 = 0; distance(first, middle, len1); Distance len2 = 0; distance(middle, last, len2); __inplace_merge(first, middle, last, len1, len2, get_temporary_buffer(len1 + len2, (T*)0), (T*)0); } template inline void __inplace_merge_aux(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, T*, Distance*, Compare comp) { Distance len1 = 0; distance(first, middle, len1); Distance len2 = 0; distance(middle, last, len2); __inplace_merge(first, middle, last, len1, len2, get_temporary_buffer(len1 + len2, (T*)0), (T*)0, comp); } template inline void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { if (first == middle || middle == last) return; __inplace_merge_aux(first, middle, last, value_type(first), distance_type(first)); } template inline void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp) { if (first == middle || middle == last) return; __inplace_merge_aux(first, middle, last, value_type(first), distance_type(first), comp); } template bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { while (first1 != last1 && first2 != last2) if (*first2 < *first1) return false; else if(*first1 < *first2) ++first1; else ++first1, ++first2; return first2 == last2; } template bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first2, *first1)) return false; else if(comp(*first1, *first2)) ++first1; else ++first1, ++first2; return first2 == last2; } template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { while (first1 != last1 && first2 != last2) if (*first1 < *first2) *result++ = *first1++; else if (*first2 < *first1) *result++ = *first2++; else { *result++ = *first1++; first2++; } return copy(first2, last2, copy(first1, last1, result)); } template OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first1, *first2)) *result++ = *first1++; else if (comp(*first2, *first1)) *result++ = *first2++; else { *result++ = *first1++; ++first2; } return copy(first2, last2, copy(first1, last1, result)); } template OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { while (first1 != last1 && first2 != last2) if (*first1 < *first2) ++first1; else if (*first2 < *first1) ++first2; else { *result++ = *first1++; ++first2; } return result; } template OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first1, *first2)) ++first1; else if (comp(*first2, *first1)) ++first2; else { *result++ = *first1++; ++first2; } return result; } template OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { while (first1 != last1 && first2 != last2) if (*first1 < *first2) *result++ = *first1++; else if (*first2 < *first1) ++first2; else { ++first1; ++first2; } return copy(first1, last1, result); } template OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first1, *first2)) *result++ = *first1++; else if (comp(*first2, *first1)) ++first2; else { ++first1; ++first2; } return copy(first1, last1, result); } template OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) { while (first1 != last1 && first2 != last2) if (*first1 < *first2) *result++ = *first1++; else if (*first2 < *first1) *result++ = *first2++; else { ++first1; ++first2; } return copy(first2, last2, copy(first1, last1, result)); } template OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp) { while (first1 != last1 && first2 != last2) if (comp(*first1, *first2)) *result++ = *first1++; else if (comp(*first2, *first1)) *result++ = *first2++; else { ++first1; ++first2; } return copy(first2, last2, copy(first1, last1, result)); } template ForwardIterator max_element(ForwardIterator first, ForwardIterator last) { if (first == last) return first; ForwardIterator result = first; while (++first != last) if (*result < *first) result = first; return result; } template ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp) { if (first == last) return first; ForwardIterator result = first; while (++first != last) if (comp(*result, *first)) result = first; return result; } template ForwardIterator min_element(ForwardIterator first, ForwardIterator last) { if (first == last) return first; ForwardIterator result = first; while (++first != last) if (*first < *result) result = first; return result; } template ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp) { if (first == last) return first; ForwardIterator result = first; while (++first != last) if (comp(*first, *result)) result = first; return result; } template bool next_permutation(BidirectionalIterator first, BidirectionalIterator last) { if (first == last) return false; BidirectionalIterator i = first; ++i; if (i == last) return false; i = last; --i; for(;;) { BidirectionalIterator ii = i--; if (*i < *ii) { BidirectionalIterator j = last; while (!(*i < *--j)); iter_swap(i, j); reverse(ii, last); return true; } if (i == first) { reverse(first, last); return false; } } } template bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp) { if (first == last) return false; BidirectionalIterator i = first; ++i; if (i == last) return false; i = last; --i; for(;;) { BidirectionalIterator ii = i--; if (comp(*i, *ii)) { BidirectionalIterator j = last; while (!comp(*i, *--j)); iter_swap(i, j); reverse(ii, last); return true; } if (i == first) { reverse(first, last); return false; } } } template bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last) { if (first == last) return false; BidirectionalIterator i = first; ++i; if (i == last) return false; i = last; --i; for(;;) { BidirectionalIterator ii = i--; if (*ii < *i) { BidirectionalIterator j = last; while (!(*--j < *i)); iter_swap(i, j); reverse(ii, last); return true; } if (i == first) { reverse(first, last); return false; } } } template bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp) { if (first == last) return false; BidirectionalIterator i = first; ++i; if (i == last) return false; i = last; --i; for(;;) { BidirectionalIterator ii = i--; if (comp(*ii, *i)) { BidirectionalIterator j = last; while (!comp(*--j, *i)); iter_swap(i, j); reverse(ii, last); return true; } if (i == first) { reverse(first, last); return false; } } } template T accumulate(InputIterator first, InputIterator last, T init) { while (first != last) init = init + *first++; return init; } template T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op) { while (first != last) init = binary_op(init, *first++); return init; } template T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) { while (first1 != last1) init = init + (*first1++ * *first2++); return init; } template T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2) { while (first1 != last1) init = binary_op1(init, binary_op2(*first1++, *first2++)); return init; } template OutputIterator __partial_sum(InputIterator first, InputIterator last, OutputIterator result, T*) { T value = *first; while (++first != last) { value = value + *first; *++result = value; } return ++result; } template OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) return result; *result = *first; return __partial_sum(first, last, result, value_type(first)); } template OutputIterator __partial_sum(InputIterator first, InputIterator last, OutputIterator result, T*, BinaryOperation binary_op) { T value = *first; while (++first != last) { value = binary_op(value, *first); *++result = value; } return ++result; } template OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) { if (first == last) return result; *result = *first; return __partial_sum(first, last, result, value_type(first), binary_op); } template OutputIterator __adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, T*) { T value = *first; while (++first != last) { T tmp = *first; *++result = tmp - value; value = tmp; } return ++result; } template OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) return result; *result = *first; return __adjacent_difference(first, last, result, value_type(first)); } template OutputIterator __adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, T*, BinaryOperation binary_op) { T value = *first; while (++first != last) { T tmp = *first; *++result = binary_op(tmp, value); value = tmp; } return ++result; } template OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) { if (first == last) return result; *result = *first; return __adjacent_difference(first, last, result, value_type(first), binary_op); } template void iota(ForwardIterator first, ForwardIterator last, T value) { while (first != last) *first++ = value++; } #endif