Simple PRNG implementation
This commit is contained in:
parent
655b310328
commit
f2de9bcd07
2 changed files with 91 additions and 0 deletions
47
prand.c
Normal file
47
prand.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "prand.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define BUILD_SEED \
|
||||
((uint64_t)(__TIME__[0]) * (uint64_t)(__TIME__[1]) * \
|
||||
(uint64_t)(__TIME__[3]) * (uint64_t)(__TIME__[4]) * \
|
||||
(uint64_t)(__TIME__[6]) * (uint64_t)(__TIME__[7]))
|
||||
|
||||
#define PRNG_SAVE_INTERVAL 50 // Save every 1000 calls to prand()
|
||||
|
||||
static uint64_t seed = BUILD_SEED;
|
||||
|
||||
uint64_t prand() {
|
||||
seed = seed * 6364136223846793005ULL + 1;
|
||||
return seed;
|
||||
}
|
||||
|
||||
inline uint64_t prand_range(uint64_t min, uint64_t max) {
|
||||
return min + (prand() % (max - min + 1));
|
||||
}
|
||||
|
||||
void sprand(uint64_t s) {
|
||||
if (s) {
|
||||
seed = s;
|
||||
} else {
|
||||
rand_reseed();
|
||||
}
|
||||
}
|
||||
|
||||
void rand_reseed() { seed = BUILD_SEED; }
|
||||
|
||||
#define PRAND_MAIN
|
||||
#ifdef PRAND_MAIN
|
||||
int main() {
|
||||
// time(NULL) provides a somewhat unique seed at runtime
|
||||
sprand(time(NULL));
|
||||
|
||||
|
||||
uint64_t rn1 = prand();
|
||||
uint64_t rn2 = prand();
|
||||
|
||||
printf("rn1 = %lu\n", rn1);
|
||||
printf("rn2 = %lu\n", rn2);
|
||||
}
|
||||
#endif
|
44
prand.h
Normal file
44
prand.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* This is a PRNG for non-cryptographic use. May be used on micros given that
|
||||
* the seed is periodically saved to EEPROM or flash.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets the seed for the PRNG.
|
||||
*
|
||||
* @param s The specific seed value or zero. If zero is passed, it will call
|
||||
* rand_reseed().
|
||||
*/
|
||||
void sprand(uint64_t s);
|
||||
|
||||
/**
|
||||
* @brief Generates a pseudo-random 64-bit number.
|
||||
*
|
||||
* Saves PRNG state to flash periodically.
|
||||
*
|
||||
* Uses a simple Linear Congruential Generator (LCG) to produce
|
||||
* a sequence of pseudo-random numbers.
|
||||
*
|
||||
* @return A pseudo-random 64-bit unsigned integer.
|
||||
*/
|
||||
uint64_t prand();
|
||||
|
||||
/**
|
||||
* @brief Generates a random number within a specified range.
|
||||
*
|
||||
* Produces a random number in the inclusive range [min, max].
|
||||
* Ensures uniform distribution by applying a modulo operation.
|
||||
*
|
||||
* @param min The lower bound of the range (inclusive).
|
||||
* @param max The upper bound of the range (inclusive).
|
||||
* @return A random number between min and max.
|
||||
*/
|
||||
inline uint64_t prand_range(uint64_t min, uint64_t max);
|
||||
|
||||
/**
|
||||
* @brief Re-seeds the PRNG seed state from BUILD_SEED.
|
||||
*/
|
||||
void rand_reseed();
|
Loading…
Add table
Reference in a new issue