Files
dnf-utils/sgutil/sgu_utils.cpp
T
2025-09-01 20:47:58 +08:00

110 lines
3.3 KiB
C++

#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<std::pair< int64_t, int64_t>>& 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<int64_t> 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<int64_t>& points)
{
points.clear();
if (nSegmentSize <= 0 || counts <= 0 || counts > nSegmentSize)
return;
// Use a set to avoid duplicate points
std::set<int64_t> uniquePoints;
while (static_cast<int32_t>(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<int64_t>(std::rand()) << 32 | static_cast<int64_t>(std::rand()) << 16 | static_cast<int64_t>(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<int64_t>(std::rand()) << 16 | static_cast<int64_t>(std::rand())) % range;
}
else {
return minValue + (static_cast<int64_t>(std::rand()) << 32 | static_cast<int64_t>(std::rand()) << 16 | static_cast<int64_t>(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<uint8_t>(std::rand() % 256);
}
}