blob: b4a95d1bc7d74b10978b752991846b013dc7dbd5 [file] [log] [blame]
/*===------------ glibc_compat_rand.c - glibc rand emulation --------------===*\
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
\*===----------------------------------------------------------------------===*/
#include "glibc_compat_rand.h"
/**
* This rand implementation is designed to emulate the implementation of
* rand/srand in recent versions of glibc. This is used for programs which
* require this specific rand implementation in order to pass verification
* tests.
*
* For more information, see: http://www.mathstat.dal.ca/~selinger/random/
**/
#define TABLE_SIZE 344
static unsigned int table[TABLE_SIZE];
static int next;
int glibc_compat_rand(void) {
/* Calculate the indices i-3 and i-31 in the circular vector. */
int i3 = (next < 3) ? (TABLE_SIZE + next - 3) : (next - 3);
int i31 = (next < 31) ? (TABLE_SIZE + next - 31) : (next - 31);
table[next] = table[i3] + table[i31];
unsigned int r = table[next] >> 1;
++next;
if (next >= TABLE_SIZE)
next = 0;
return r;
}
void glibc_compat_srand(unsigned int seed) {
if (seed == 0)
seed = 1;
table[0] = seed;
for (int i = 1; i < 31; i++) {
int r = (16807ll * table[i - 1]) % 2147483647;
if (r < 0)
r += 2147483647;
table[i] = r;
}
for (int i = 31; i < 34; i++)
table[i] = table[i - 31];
for (int i = 34; i < TABLE_SIZE; i++)
table[i] = table[i - 31] + table[i - 3];
next = 0;
}