/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ │ │ Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, │ │ All rights reserved. │ │ │ │ Redistribution and use in source and binary forms, with or without │ │ modification, are permitted provided that the following conditions │ │ are met: │ │ │ │ 1. Redistributions of source code must retain the above copyright │ │ notice, this list of conditions and the following disclaimer. │ │ │ │ 2. Redistributions in binary form must reproduce the above │ │ copyright notice, this list of conditions and the following │ │ disclaimer in the documentation and/or other materials │ │ provided with the distribution. │ │ │ │ 3. The names of its contributors may not be used to endorse or │ │ promote products derived from this software without specific │ │ prior written permission. │ │ │ │ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS │ │ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT │ │ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR │ │ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT │ │ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, │ │ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT │ │ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, │ │ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY │ │ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT │ │ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE │ │ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. │ │ │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/intrin/likely.h" #include "libc/macros.internal.h" #include "libc/stdio/rand.h" asm(".ident\t\"\\n\\n\ mt19937 (BSD-3)\\n\ Copyright 1997-2004 Makoto Matsumoto and Takuji Nishimura\""); asm(".include \"libc/disclaimer.inc\""); /* * A C-program for MT19937-64 (2004/9/29 version). * Coded by Takuji Nishimura and Makoto Matsumoto. * * This is a 64-bit version of Mersenne Twister pseudorandom number * generator. * * Before using, initialize the state by using init_genrand64(seed) * or init_by_array64(init_key, key_length). * * References: * T. Nishimura, ``Tables of 64-bit Mersenne Twisters'' * ACM Transactions on Modeling and * Computer Simulation 10. (2000) 348--357. * M. Matsumoto and T. Nishimura, * ``Mersenne Twister: a 623-dimensionally equidistributed * uniform pseudorandom number generator'' * ACM Transactions on Modeling and * Computer Simulation 8. (Jan. 1998) 3--30. * * Any feedback is very welcome. * http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces) */ #define NN 312 #define MM 156 #define LM 0x7fffffff #define UM 0xffffffff80000000 static int mti = NN + 1; static uint64_t mt[NN]; static const uint64_t mag01[2] = {0, 0xb5026f5aa96619e9}; /** * Initializes mt[NN] with small seed value. * * @see mt19937(), Smt19937() */ void _smt19937(uint64_t seed) { mt[0] = seed; for (mti = 1; mti < NN; mti++) { mt[mti] = 0x5851f42d4c957f2d * (mt[mti - 1] ^ (mt[mti - 1] >> 62)) + mti; } } /** * Initializes mt[NN] with array. * * @param K is the array for initializing keys * @param n is its length * @see mt19937(), smt19937() */ void _Smt19937(uint64_t K[], size_t n) { size_t i, j, k; _smt19937(19650218); for (i = 1, j = 0, k = MAX(NN, n); k; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 62)) * 0x369dea0f31a53f85)) + K[j] + j; if (++i >= NN) mt[0] = mt[NN - 1], i = 1; if (++j >= n) j = 0; } for (k = NN - 1; k; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 62)) * 0x27bb2ee687b0b0fd)) - i; if (++i >= NN) mt[0] = mt[NN - 1], i = 1; } mt[0] = 0x8000000000000000; /* assures non-zero initial array */ } /** * Generates random integer on [0, 2^64)-interval. * * This uses the Mersenne Twister pseudorandom number generator. * * @see smt19937(), Smt19937() */ uint64_t _mt19937(void) { int i; uint64_t x; if (mti >= NN) { if (mti == NN + 1) _smt19937(5489); for (i = 0; i < NN - MM; i++) { x = (mt[i] & UM) | (mt[i + 1] & LM); mt[i] = mt[i + MM] ^ (x >> 1) ^ mag01[x & 1]; } for (; i < NN - 1; i++) { x = (mt[i] & UM) | (mt[i + 1] & LM); mt[i] = mt[i + (MM - NN)] ^ (x >> 1) ^ mag01[x & 1]; } x = (mt[NN - 1] & UM) | (mt[0] & LM); mt[NN - 1] = mt[MM - 1] ^ (x >> 1) ^ mag01[x & 1]; mti = 0; } x = mt[mti++]; x ^= (x >> 29) & 0x5555555555555555; x ^= (x << 17) & 0x71d67fffeda60000; x ^= (x << 37) & 0xfff7eee000000000; x ^= (x >> 43); return x; }