xs_random.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
  2. #ifndef _XS_RANDOM_H
  3. #define _XS_RANDOM_H
  4. unsigned int xs_rnd_int32_d(unsigned int *seed);
  5. void *xs_rnd_buf(void *buf, int size);
  6. #ifdef XS_IMPLEMENTATION
  7. #include <stdio.h>
  8. #include <sys/time.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. unsigned int xs_rnd_int32_d(unsigned int *seed)
  12. /* returns a deterministic random integer. If seed is NULL, uses a static one */
  13. {
  14. static unsigned int s = 0;
  15. if (seed == NULL)
  16. seed = &s;
  17. if (*seed == 0) {
  18. struct timeval tv;
  19. gettimeofday(&tv, NULL);
  20. *seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
  21. }
  22. /* Linear congruential generator by Numerical Recipes */
  23. *seed = (*seed * 1664525) + 1013904223;
  24. return *seed;
  25. }
  26. void *xs_rnd_buf(void *buf, int size)
  27. /* fills buf with random data */
  28. {
  29. #ifdef __OpenBSD__
  30. /* available since OpenBSD 2.2 */
  31. arc4random_buf(buf, size);
  32. #else
  33. FILE *f;
  34. int done = 0;
  35. if ((f = fopen("/dev/urandom", "r")) != NULL) {
  36. /* fill with great random data from the system */
  37. if (fread(buf, size, 1, f) == 1)
  38. done = 1;
  39. fclose(f);
  40. }
  41. if (!done) {
  42. /* fill the buffer with poor quality, deterministic data */
  43. unsigned int s = 0;
  44. unsigned char *p = (unsigned char *)buf;
  45. int n = size / sizeof(s);
  46. /* fill with full integers */
  47. while (n--) {
  48. xs_rnd_int32_d(&s);
  49. p = memcpy(p, &s, sizeof(s)) + sizeof(s);
  50. }
  51. if ((n = size % sizeof(s))) {
  52. /* fill the remaining */
  53. xs_rnd_int32_d(&s);
  54. memcpy(p, &s, n);
  55. }
  56. }
  57. #endif /* __OpenBSD__ */
  58. return buf;
  59. }
  60. #endif /* XS_IMPLEMENTATION */
  61. #endif /* XS_RANDOM_H */