Skip to content

Commit d84d3ad

Browse files
committed
Fix thread local rng implementation in C so it's correctly unbiased and actually random.
1 parent 304ed25 commit d84d3ad

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

src/julia_internal.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,18 +1308,31 @@ JL_DLLEXPORT size_t jl_maxrss(void);
13081308

13091309
STATIC_INLINE uint64_t cong(uint64_t max, uint64_t *seed) JL_NOTSAFEPOINT
13101310
{
1311-
if (max == 0)
1311+
if (max < 2)
13121312
return 0;
13131313
uint64_t mask = ~(uint64_t)0;
1314-
--max;
1315-
mask >>= __builtin_clzll(max|1);
1316-
uint64_t x;
1314+
int zeros = __builtin_clzll(max);
1315+
int bits = CHAR_BIT * sizeof(uint64_t) - zeros;
1316+
mask = mask >> zeros;
13171317
do {
1318-
*seed = 69069 * (*seed) + 362437;
1319-
x = *seed & mask;
1320-
} while (x > max);
1321-
return x;
1318+
uint64_t value = 69069 * (*seed) + 362437;
1319+
*seed = value;
1320+
uint64_t x = value & mask;
1321+
if (x < max) {
1322+
return x;
1323+
}
1324+
int bits_left = zeros;
1325+
while (bits_left >= bits) {
1326+
value >>= bits;
1327+
x = value & mask;
1328+
if (x < max) {
1329+
return x;
1330+
}
1331+
bits_left -= bits;
1332+
}
1333+
} while (1);
13221334
}
1335+
13231336
JL_DLLEXPORT uint64_t jl_rand(void) JL_NOTSAFEPOINT;
13241337
JL_DLLEXPORT void jl_srand(uint64_t) JL_NOTSAFEPOINT;
13251338
JL_DLLEXPORT void jl_init_rand(void);

0 commit comments

Comments
 (0)