Unoptimize the higher part of the domain of csrand_uniform()
__int128, which is needed for optimizing that part of the range, is not
always available. We need the unoptimized version for portability
reasons.
Closes: <https://github.com/shadow-maint/shadow/issues/634>
Fixes: 1a0e13f94e
("Optimize csrand_uniform()")
Reported-by: Adam Sampson <ats@offog.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
parent
0712b236c3
commit
2a61122b5e
@ -9,17 +9,23 @@
|
|||||||
#ident "$Id$"
|
#ident "$Id$"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#if HAVE_SYS_RANDOM_H
|
#if HAVE_SYS_RANDOM_H
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "bit.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "shadowlog.h"
|
#include "shadowlog.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t csrand_uniform32(uint32_t n);
|
||||||
|
static unsigned long csrand_uniform_slow(unsigned long n);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a uniformly-distributed CS random u_long value.
|
* Return a uniformly-distributed CS random u_long value.
|
||||||
*/
|
*/
|
||||||
@ -69,16 +75,37 @@ fail:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a uniformly-distributed CS random value in the interval [0, n-1].
|
* Return a uniformly-distributed CS random value in the interval [0, n-1].
|
||||||
*
|
|
||||||
* Fast Random Integer Generation in an Interval
|
|
||||||
* ACM Transactions on Modeling and Computer Simulation 29 (1), 2019
|
|
||||||
* <https://arxiv.org/abs/1805.10941>
|
|
||||||
*/
|
*/
|
||||||
unsigned long
|
unsigned long
|
||||||
csrand_uniform(unsigned long n)
|
csrand_uniform(unsigned long n)
|
||||||
{
|
{
|
||||||
unsigned long bound, rem;
|
if (n == 0 || n > UINT32_MAX)
|
||||||
unsigned __int128 r, mult;
|
return csrand_uniform_slow(n);
|
||||||
|
|
||||||
|
return csrand_uniform32(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a uniformly-distributed CS random value in the interval [min, max].
|
||||||
|
*/
|
||||||
|
unsigned long
|
||||||
|
csrand_interval(unsigned long min, unsigned long max)
|
||||||
|
{
|
||||||
|
return csrand_uniform(max - min + 1) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast Random Integer Generation in an Interval
|
||||||
|
* ACM Transactions on Modeling and Computer Simulation 29 (1), 2019
|
||||||
|
* <https://arxiv.org/abs/1805.10941>
|
||||||
|
*/
|
||||||
|
static uint32_t
|
||||||
|
csrand_uniform32(uint32_t n)
|
||||||
|
{
|
||||||
|
uint32_t bound, rem;
|
||||||
|
uint64_t r, mult;
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return csrand();
|
return csrand();
|
||||||
@ -97,11 +124,18 @@ csrand_uniform(unsigned long n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static unsigned long
|
||||||
* Return a uniformly-distributed CS random value in the interval [min, max].
|
csrand_uniform_slow(unsigned long n)
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
csrand_interval(unsigned long min, unsigned long max)
|
|
||||||
{
|
{
|
||||||
return csrand_uniform(max - min + 1) + min;
|
unsigned long r, max, mask;
|
||||||
|
|
||||||
|
max = n - 1;
|
||||||
|
mask = bit_ceil_wrapul(n) - 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
r = csrand();
|
||||||
|
r &= mask; // optimization
|
||||||
|
} while (r > max); // p = ((mask+1) % n) / (mask+1); W.C.: p=0.5
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user