| /*===------------ 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; |
| } |