cOMS/utils/RandomUtils.h
Dennis Eichhorn 2059cc6e77
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (autobuild, c-cpp) (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
update
2025-06-14 19:10:16 +00:00

115 lines
2.5 KiB
C
Executable File

/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef COMS_UTILS_RANDOM_H
#define COMS_UTILS_RANDOM_H
#include <stdlib.h>
#include "../stdlib/Types.h"
#include "../utils/TestUtils.h"
#include "../utils/TimeUtils.h"
// PERFORMANCE: Approx. 4x faster than rand()
inline
uint32 rand_fast(uint32* state) {
static const uint32 z = 0x9E3779B9;
uint32 x = *state;
x ^= ((x << 13) | (x >> 19)) ^ ((x << 5) | (x >> 27));
x *= z;
x ^= x >> 16;
x *= z;
x ^= x >> 15;
*state = x;
return x;
}
inline
uint64 rand_fast(uint64* state) {
static const uint64 z = 0x9FB21C651E98DF25;
uint64 x = *state;
x ^= ((x << 49) | (x >> 15)) ^ ((x << 24) | (x >> 40));
x *= z;
x ^= x >> 35;
x *= z;
x ^= x >> 28;
*state = x;
return x;
}
uint32 rand_fast(uint32* state, int32 max) {
return (uint32) (((uint64) rand_fast(state) * max) >> 32);
}
/**
* Picks n random elements from end and stores them in begin.
*/
inline
void random_unique(int32* array, int32 size) {
for (int32 i = size - 1; i > 0; --i) {
int32 j = rand() % (i + 1);
int32 temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
/**
* Gets random index based value probability
*/
int32 random_weighted_index(const int32* arr, int32 array_count)
{
uint32 prob_sum = 0;
for (int32 i = 0; i < array_count; ++i) {
prob_sum += arr[i];
}
uint32 random_prob = rand() % (prob_sum + 1);
uint32 current_rarity = 0;
int32 item_rarity = array_count - 1;
for (int32 i = 0; i < array_count - 1; ++i) {
current_rarity += arr[i];
if (current_rarity < random_prob) {
item_rarity = i;
break;
}
}
return item_rarity;
}
// WARNING: The allowed_chars string length needs to be of power 2 for performance reasons
// Supporting any allowed_chars length is trivial but usually we prefer the performance improvement
void random_string(const char* allowed_chars, uint32 allowed_length, char* out, int32 out_length) {
ASSERT_SIMPLE(allowed_length & 2 == 0);
const uint32 mask = allowed_length - 1;
uint64 x = time_index();
size_t i = 0;
while (i < out_length) {
uint64 rand_val = rand_fast(&x);
for (int32 j = 0; j < 8 && i < out_length; ++j, ++i) {
out[i] = allowed_chars[((rand_val >> (8 * j)) & 0xFF) & allowed_length];
}
}
out[out_length] = '\0';
}
#endif