typename Container::value_type maximum_by(Compare comp, const Container& xs) { internal::check_compare_for_container<Compare, Container>(); assert(is_not_empty(xs)); return *std::max_element(std::begin(xs), std::end(xs), comp); }
Result median(const Container& xs) { assert(is_not_empty(xs)); if (size_of_cont(xs) == 1) return static_cast<Result>(xs.front()); // std::nth_element (instead of sorting) // would be faster for random-access containers // but not work at all on other containers like std::list. auto xsSorted = sort(xs); if (size_of_cont(xsSorted) % 2 == 1) { auto it = std::begin(xsSorted); internal::advance_iterator(it, size_of_cont(xsSorted) / 2); return static_cast<Result>(*it); } else { auto it1 = std::begin(xsSorted); internal::advance_iterator(it1, size_of_cont(xsSorted) / 2 - 1); auto it2 = it1; ++it2; return static_cast<Result>(*it1 + *it2) / static_cast<Result>(2); } }
typename std::size_t maximum_idx_by(Compare comp, const Container& xs) { internal::check_compare_for_container<Compare, Container>(); assert(is_not_empty(xs)); return static_cast<std::size_t>(std::distance(std::begin(xs), std::max_element(std::begin(xs), std::end(xs), comp))); }
//TODO at other end bool try_steal(JOB& job) { lock_type lock(m_mutex); if (is_not_empty()) { job = m_jobs.back(); m_jobs.pop_back(); return true; } return false; }
T elem_at_idx_or_wrap(signed int idx, const Container& xs) { assert(is_not_empty(xs)); const signed int cont_size = static_cast<signed int>(size_of_cont(xs)); if (idx < 0) idx = cont_size - (std::abs(idx) % cont_size); else idx = idx % cont_size; auto it = std::begin(xs); internal::advance_iterator(it, static_cast<std::size_t>(idx)); return *it; }
T elem_at_idx_or_replicate(signed int idx, const Container& xs) { assert(is_not_empty(xs)); if (idx < 0) { return xs.front(); } if (idx >= static_cast<signed int>(size_of_cont(xs))) { return xs.back(); } auto it = std::begin(xs); internal::advance_iterator(it, static_cast<std::size_t>(idx)); return *it; }
Container extrapolate_wrap(std::size_t count_begin, std::size_t count_end, const Container& xs) { assert(is_not_empty(xs)); Container ys; const auto xs_size = size_of_cont(xs); internal::prepare_container(ys, xs_size + count_begin + count_end); auto it = internal::get_back_inserter<Container>(ys); const signed int idx_end = static_cast<signed int>(xs_size + count_end); const signed int idx_start = -static_cast<signed int>(count_begin); for (signed int idx = idx_start; idx < idx_end; ++idx) { *it = elem_at_idx_or_wrap(idx, xs); } return ys; }
Result median(const Container& xs) { assert(is_not_empty(xs)); if (size_of_cont(xs) == 1) return static_cast<Result>(xs.front()); auto xsSorted = sort(xs); if (size_of_cont(xsSorted) % 2 == 1) { auto it = std::begin(xsSorted); internal::advance_iterator(it, size_of_cont(xsSorted) / 2); return static_cast<Result>(*it); } else { auto it1 = std::begin(xsSorted); internal::advance_iterator(it1, size_of_cont(xsSorted) / 2 - 1); auto it2 = it1; ++it2; return static_cast<Result>(*it1 + *it2) / static_cast<Result>(2); } }