#include "Utils.h"


int getRandomNumber(int min, int max) {
    thread_local static std::random_device rd;
    thread_local static std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(min, max);
    return dist(gen);
}

// Function to generate a random number between 0 and 1
float getRandomFraction(float min, float max) {
    thread_local static std::random_device rd;
    thread_local static std::mt19937 gen(rd());
    std::uniform_real_distribution<float> dist(min, max);
    return dist(gen);
}

float getRandomFractionFast() {
    thread_local static std::vector<float> randomValues;
    thread_local static size_t index = 0;
    thread_local static const size_t size = 10000;

    if (randomValues.empty()) {
        // Seed the random number generator
        thread_local static std::random_device rd;
        thread_local static std::mt19937 gen(rd());
        std::uniform_real_distribution<float> dist(0.0f, 1.0f);

        // Pre-generate random values
        randomValues.reserve(size);
        for (size_t i = 0; i < size; ++i) {
            randomValues.push_back(dist(gen));
        }
    }

    // Get the next random value from the list
    float randomValue = randomValues[index];
    index = (index + 1) % size; // Wrap around when reaching the end of the list

    return randomValue;
}

std::vector<int> argsort(const std::vector<float>& values) {
    // Create an index vector [0, 1, 2, ..., n-1]
    std::vector<int> indices(values.size());
    std::iota(indices.begin(), indices.end(), 0);

    // Sort the indices based on the values
    std::sort(indices.begin(), indices.end(), [&values](size_t i1, size_t i2) {
        return values[i1] < values[i2];
        });

    return indices;
}
