| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * random.c -- pseudo random number generator |
| * Copyright (C) 1994 Chris Wallace (csw@bruce.cs.monash.edu.au) |
| */ |
| |
| #include <sys/types.h> |
| |
| /* |
| * modified by dxm@sgi.com so that this file acts as a drop in replacement |
| * for srandom and random. |
| */ |
| |
| /* |
| * A random number generator called as a function by |
| * random (iseed) or irandm (iseed) |
| * The parameter should be a pointer to a 2-element int32_t vector. |
| * The first function returns a double uniform in 0 .. 1. |
| * The second returns a int32_t integer uniform in 0 .. 2**31-1 |
| * Both update iseed[] in exactly the same way. |
| * iseed[] must be a 2-element integer vector. |
| * The initial value of the second element may be anything. |
| * |
| * The period of the random sequence is 2**32 * (2**32-1) |
| * The table mt[0:127] is defined by mt[i] = 69069 ** (128-i) |
| */ |
| |
| #define MASK ((int32_t) 593970775) |
| /* or in hex, 23674657 */ |
| |
| #define SCALE ((double) 1.0 / (1024.0 * 1024.0 * 1024.0 * 2.0)) |
| /* i.e. 2 to power -31 */ |
| |
| static int32_t mt [128] = { |
| 902906369, |
| 2030498053, |
| -473499623, |
| 1640834941, |
| 723406961, |
| 1993558325, |
| -257162999, |
| -1627724755, |
| 913952737, |
| 278845029, |
| 1327502073, |
| -1261253155, |
| 981676113, |
| -1785280363, |
| 1700077033, |
| 366908557, |
| -1514479167, |
| -682799163, |
| 141955545, |
| -830150595, |
| 317871153, |
| 1542036469, |
| -946413879, |
| -1950779155, |
| 985397153, |
| 626515237, |
| 530871481, |
| 783087261, |
| -1512358895, |
| 1031357269, |
| -2007710807, |
| -1652747955, |
| -1867214463, |
| 928251525, |
| 1243003801, |
| -2132510467, |
| 1874683889, |
| -717013323, |
| 218254473, |
| -1628774995, |
| -2064896159, |
| 69678053, |
| 281568889, |
| -2104168611, |
| -165128239, |
| 1536495125, |
| -39650967, |
| 546594317, |
| -725987007, |
| 1392966981, |
| 1044706649, |
| 687331773, |
| -2051306575, |
| 1544302965, |
| -758494647, |
| -1243934099, |
| -75073759, |
| 293132965, |
| -1935153095, |
| 118929437, |
| 807830417, |
| -1416222507, |
| -1550074071, |
| -84903219, |
| 1355292929, |
| -380482555, |
| -1818444007, |
| -204797315, |
| 170442609, |
| -1636797387, |
| 868931593, |
| -623503571, |
| 1711722209, |
| 381210981, |
| -161547783, |
| -272740131, |
| -1450066095, |
| 2116588437, |
| 1100682473, |
| 358442893, |
| -1529216831, |
| 2116152005, |
| -776333095, |
| 1265240893, |
| -482278607, |
| 1067190005, |
| 333444553, |
| 86502381, |
| 753481377, |
| 39000101, |
| 1779014585, |
| 219658653, |
| -920253679, |
| 2029538901, |
| 1207761577, |
| -1515772851, |
| -236195711, |
| 442620293, |
| 423166617, |
| -1763648515, |
| -398436623, |
| -1749358155, |
| -538598519, |
| -652439379, |
| 430550625, |
| -1481396507, |
| 2093206905, |
| -1934691747, |
| -962631983, |
| 1454463253, |
| -1877118871, |
| -291917555, |
| -1711673279, |
| 201201733, |
| -474645415, |
| -96764739, |
| -1587365199, |
| 1945705589, |
| 1303896393, |
| 1744831853, |
| 381957665, |
| 2135332261, |
| -55996615, |
| -1190135011, |
| 1790562961, |
| -1493191723, |
| 475559465, |
| 69069 |
| }; |
| |
| double |
| _random (int32_t is [2]) |
| { |
| int32_t it, leh, nit; |
| |
| it = is [0]; |
| leh = is [1]; |
| if (it <= 0) |
| it = (it + it) ^ MASK; |
| else |
| it = it + it; |
| nit = it - 1; |
| /* to ensure all-ones pattern omitted */ |
| leh = leh * mt[nit & 127] + nit; |
| is [0] = it; is [1] = leh; |
| if (leh < 0) leh = ~leh; |
| return (SCALE * ((int32_t) (leh | 1))); |
| } |
| |
| |
| |
| int32_t |
| _irandm (int32_t is [2]) |
| { |
| int32_t it, leh, nit; |
| |
| it = is [0]; |
| leh = is [1]; |
| if (it <= 0) |
| it = (it + it) ^ MASK; |
| else |
| it = it + it; |
| nit = it - 1; |
| /* to ensure all-ones pattern omitted */ |
| leh = leh * mt[nit & 127] + nit; |
| is [0] = it; is [1] = leh; |
| if (leh < 0) leh = ~leh; |
| return (leh); |
| } |
| |
| /* |
| * make this a drop in replacement for random and srandom |
| * |
| * XXX not thread safe I guess. |
| */ |
| |
| static int32_t saved_seed[2]; |
| |
| long random(void) |
| { |
| return _irandm(saved_seed); |
| } |
| |
| void srandom(unsigned seed) |
| { |
| saved_seed[0]=seed; |
| saved_seed[1]=0; |
| _irandm(saved_seed); |
| } |
| |