#include "sgu_stdafx.h" #include "sgu_utils.h" #ifdef min #undef min #endif #ifdef max #undef max #endif bool generateRandomSegment(int64_t memorySize, int64_t minSize, int64_t maxSize, int32_t counts, std::vector>& segmentArray) { // Cannot allocate: not enough space if ((int64_t)counts * minSize > memorySize) return false; // Calculate the base partition size for each segment int64_t basePartition = memorySize / counts; int64_t remain = memorySize % counts; std::vector regionSizes(counts, minSize); int64_t totalAssigned = minSize * counts; // First assign the minimum size to each segment, then randomly distribute the remaining space int64_t extraSpace = memorySize - totalAssigned; for (int i = 0; i < counts && extraSpace > 0; ++i) { int64_t maxExtra = std::min(extraSpace, maxSize - minSize); int64_t add = randomInRange(0, maxExtra); regionSizes[i] += add; extraSpace -= add; } // Shuffle the allocation to avoid always concentrating at the front std::random_shuffle(regionSizes.begin(), regionSizes.end()); // Calculate the start position of each segment, distribute them evenly int64_t offset = 0; for (int i = 0; i < counts; ++i) { int64_t partitionStart = (memorySize * i) / counts; int64_t partitionEnd = (memorySize * (i + 1)) / counts; int64_t partitionLen = partitionEnd - partitionStart; // The segment length cannot exceed the partition length int64_t regionLen = std::min(regionSizes[i], partitionLen); // Random start position within the partition int64_t maxStart = partitionLen - regionLen; int64_t startInPartition = randomInRange(0, maxStart); int64_t regionStart = partitionStart + startInPartition; segmentArray.push_back(std::make_pair(regionStart, regionLen)); } return true; } // Randomly generate 'counts' points on a segment of length 'nSegmentSize'. void generateRandomPointsInSegment(int64_t nSegmentSize, int32_t counts, std::vector& points) { points.clear(); if (nSegmentSize <= 0 || counts <= 0 || counts > nSegmentSize) return; // Use a set to avoid duplicate points std::set uniquePoints; while (static_cast(uniquePoints.size()) < counts) { int64_t pt = randomInRange(0, nSegmentSize-1); uniquePoints.insert(pt); } points.assign(uniquePoints.begin(), uniquePoints.end()); std::sort(points.begin(), points.end()); return; } int64_t randomInRange(int64_t minValue, int64_t maxValue) { if (minValue > maxValue) { std::swap(minValue, maxValue); } if (minValue == maxValue) { return minValue; } int64_t range = maxValue - minValue + 1; if (range <= 0) { // Overflow case return minValue + (static_cast(std::rand()) << 32 | static_cast(std::rand()) << 16 | static_cast(std::rand())) % range; } else if (range <= RAND_MAX) { return minValue + std::rand() % range; } else if (range <= (int64_t)RAND_MAX * RAND_MAX) { return minValue + (static_cast(std::rand()) << 16 | static_cast(std::rand())) % range; } else { return minValue + (static_cast(std::rand()) << 32 | static_cast(std::rand()) << 16 | static_cast(std::rand())) % range; } } void fillRandomData(uint8_t* buffer, int64_t size) { if (!buffer || size <= 0) return; for (int64_t i = 0; i < size; ++i) { buffer[i] = static_cast(std::rand() % 256); } }