diff --git a/include/Vutils.h b/include/Vutils.h index 5017b8f..f127e8f 100644 --- a/include/Vutils.h +++ b/include/Vutils.h @@ -218,8 +218,12 @@ bool vuapi use_std_io_console_window(); bool vuapi is_flag_on(ulongptr flags, ulongptr flag); intptr vuapi gcd(ulongptr count, ...); // UCLN intptr vuapi lcm(ulongptr count, ...); // BCNN -float vuapi fast_sqrtf(const float number); // Estimates the square root of a 32-bit floating-point number (from Quake III Arena) void vuapi hex_dump(const void* data, int size); +float vuapi fast_sqrtf(const float number); // Estimates the square root of a 32-bit floating-point number (from Quake III Arena) +void divide_items_into_pieces(const size_t num_items, const size_t num_pieces, + std::function fn); +size_t divide_items_into_num_items_per_piece(const size_t num_items, const size_t num_items_per_piece, + std::function fn); #include "template/math.tpl" diff --git a/src/details/math.cpp b/src/details/math.cpp index 4198390..556aa1e 100644 --- a/src/details/math.cpp +++ b/src/details/math.cpp @@ -128,4 +128,90 @@ float vuapi fast_sqrtf(const float number) return 1.F / q_rsqrt(number); } +/** + * Divides a set of items into a specified number of pieces. + * @param[in] num_items The number of items. + * @param[in] num_pieces The number of pieces. + * @param[in] fn The function that apply to each piece. + * idx The piece index. + * beg The index of the begin item in piece. + * end The index of the end item in piece. + * num The number of items in piece. + * Eg. In these cases, the number of items of each piece as the following: + * (4, 1) => (4) + * (4, 2) => (2, 2) + * (4, 3) => (1, 1, 2) + * (4, 4) => (1, 1, 1, 1) + * (4, 5) => (1, 1, 1, 1, 0) + */ +void divide_items_into_pieces(const size_t num_items, const size_t num_pieces, + std::function fn) +{ + if (fn == nullptr) + { + return; + } + + size_t num_items_per_piece = std::max(1, int(num_items / float(num_pieces) + 0.5F)); + + for (size_t idx = 0; idx < num_pieces; ++idx) + { + size_t beg = idx * num_items_per_piece; + size_t end = idx == num_pieces - 1 ? num_items : (idx + 1) * num_items_per_piece; + size_t num = end - beg; + + beg = idx < num_items ? beg : -1; + end = idx < num_items ? end - 1 : -1; + num = idx < num_items ? num : 0; + + fn(idx, beg, end, num); + } +} + +/** + * Divides a set of items into a specified number of items per piece. + * @param[in] num_items The number of items. + * @param[in] num_pieces The number of item per piece. + * @param[in] fn The function that apply to each piece. + * idx The piece index. + * beg The index of the begin item in piece. + * end The index of the end item in piece. + * num The number of items in piece. + * @return The number of pieces. + * Eg. The number of items of each piece as the following. + * (4, 1) => (1, 1, 1, 1) + * (4, 2) => (2, 2) + * (4, 3) => (3, 1, 1) + * (4, 4) => (4) + * (4, 5) => (4) + */ +size_t divide_items_into_num_items_per_piece(const size_t num_items, const size_t num_items_per_piece, + std::function fn) +{ + if (fn == nullptr) + { + return 0; + } + + size_t result = 0; + + std::vector piece; + + for (size_t j = 1; j <= num_items; j++) + { + size_t i = j - 1; + + piece.push_back(i); + + if (j % num_items_per_piece == 0 || i == num_items - 1) + { + fn(result, piece.front(), piece.back(), piece.size()); + piece.clear(); + result += 1; + } + } + + return result; +} + } // namespace vu \ No newline at end of file