#pragma once /* Programmed by: Thomas Kim First Version: Nov. 12, 2017 Last Version: Nov. 12, 2017 if you want to re-define default index_t to something else for example, int, then #define index_t int before including this file to stdafx.h, such as #define index_t int #include "tmp_split_ranges.h" Do NOT include "tmp_split_ranges.h" to multiple files */ #ifndef _TMP_SPLIT_RANGES_H #define _TMP_SPLIT_RANGES_H #include #include #include #include #include #include #include #include #include #include #ifndef index_t //default index_t type #define index_t size_t #endif template using range = std::pair; typedef range range_t; template using rngvctr = std::vector>; typedef rngvctr range_vctr_t; template std::string DisplayRange(const range& rg, bool thousands=true) { std::ostringstream os; if (thousands) os.imbue(std::locale("")); os << "[" << rg.first << ", " << rg.second << ") - count: " << (rg.second - rg.first); return os.str(); } /* st ed 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 minimum span = 3; [1, 5), [5, 8), [8, 11) 1, 2, 3, 4, 5 -> [1, 5) : 4 5, 6, 7, 8 -> [5, 8) : 3 8, 9, 10, 11 -> [8, 11): 3 */ template rngvctr SplitRangeSpan(T min_span, T st, T ed) { T dist = ed - st; T rnd = dist % min_span; T count = dist / min_span; rngvctr rng; if (rnd == 0) { T prev = st; for (T i = 0; i < count; ++i) { rng.emplace_back(range(prev, prev + min_span)); prev += min_span; } return rng; } else { if (count >= rnd) { T span1 = min_span + 1; T prev = st; for (T i = 0; i < rnd; ++i) { rng.emplace_back(range(prev, prev + span1)); prev += span1; } count = count - rnd; for (T i = 0; i < count; ++i) { rng.emplace_back(range(prev, prev + min_span)); prev += min_span; } return rng; } else { return SplitRangeCount(count, st, ed); } } } #define DivideRangeSpan(span, start, end) SplitRangeSpan((span), (start), (end)) template rngvctr SplitRangeCount(T count, T st, T ed) { T dist = ed - st; T span = dist / count; T rnd = dist % count; rngvctr rng; if (rnd == 0) { T prev = st; for (T i = 0; i < count; ++i) { rng.push_back(range(prev, prev + span)); prev += span; } return rng; } else { T span1 = span + 1; T prev = st; for (T i = 0; i < rnd; ++i) { rng.emplace_back(range(prev, prev + span1)); prev += span1; } // rnd = dist % count; // rnd cannot be greater than count count = count - rnd; for (T i = 0; i < count; ++i) { rng.emplace_back(range(prev, prev + span)); prev += span; } return rng; } } #define DivideRangeCount(count, start, end) SplitRangeCount((count), (start), (end)) template std::string DisplayRanges(const rngvctr& rngs, int width=9, bool thousands=true) { if (!rngs.empty()) { std::ostringstream os; if (thousands) os.imbue(std::locale("")); os << "Range count: " << rngs.size() << std::endl<< "Max range: " << (rngs[0].second - rngs[0].first) << " elements, Min range: " << (rngs.back().second - rngs.back().first) << " elements."<