Skip to content

Commit

Permalink
Allow random values to scale up to 64-bits
Browse files Browse the repository at this point in the history
Improves precision in reservoir sampling
  • Loading branch information
begriffs committed Dec 23, 2018
1 parent ea83436 commit 62a2b52
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 14 deletions.
22 changes: 10 additions & 12 deletions rand.c
Expand Up @@ -53,21 +53,17 @@ unsigned long defensive_seed(void)
* Alternative to the garbage implementation of rand() in many
* systems such as FreeBSD and OS X. Uses xorshift.
*
* Returns a value between 0 and DEFENSIVE_RAND_MAX, which on
* many platforms is smaller than what unsigned long can hold.
* Returns a value between 0 and DEFENSIVE_RAND_MAX.
* From https://nullprogram.com/blog/2018/07/31/
*/
unsigned long defensive_rand()
{
/*
* The long type should portably be at least 32 bits, and we
* mask the calculations to 32 bits in case long happens to be
* wider. The constants are tuned for a 32-bit type.
*/
unsigned long y = g_rand_state & DEFENSIVE_RAND_MAX;
y ^= (y << 13) & DEFENSIVE_RAND_MAX;
y ^= y >> 17;
y ^= (y << 5) & DEFENSIVE_RAND_MAX;
return (g_rand_state = y);
g_rand_state ^= g_rand_state >> 30;
g_rand_state *= 0xbf58476d1ce4e5b9UL;
g_rand_state ^= g_rand_state >> 27;
g_rand_state *= 0x94d049bb133111ebUL;
g_rand_state ^= g_rand_state >> 31;
return g_rand_state;
}

void defensive_srand(unsigned long s)
Expand All @@ -88,6 +84,8 @@ unsigned long djb2hash(const unsigned char *str)

/* It's better to combine entropic values this way rather
* than e.g. adding them together.
*
* From http://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
*/
unsigned long mix(unsigned long x, unsigned long y)
{
Expand Down
4 changes: 3 additions & 1 deletion rand.h
@@ -1,7 +1,9 @@
#ifndef RAND_H
#define RAND_H

#define DEFENSIVE_RAND_MAX 0xffffffffUL
#include <limits.h>

#define DEFENSIVE_RAND_MAX ULONG_MAX

void defensive_srand(unsigned long);
unsigned long defensive_seed(void);
Expand Down
3 changes: 2 additions & 1 deletion randln.c
Expand Up @@ -53,7 +53,8 @@ void via_fseek(FILE *fp)
if ((filesz = ftell(fp)) == -1)
die_perror(NULL);

pos = (int)((double)defensive_rand() / ((double)DEFENSIVE_RAND_MAX + 1) * filesz);
pos = ((double)defensive_rand() /
((double)DEFENSIVE_RAND_MAX)) * filesz;

if (fseek(fp, pos, SEEK_SET) != 0)
die_perror(NULL);
Expand Down

0 comments on commit 62a2b52

Please sign in to comment.