Fold LIBC_RAND into LIBC_STDIO/TINYMATH/INTRIN

This commit is contained in:
Justine Tunney 2022-08-11 12:26:30 -07:00
parent 05b8f82371
commit 8a0a2c0c36
183 changed files with 149 additions and 322 deletions

View file

@ -20,6 +20,7 @@
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/o.h"
int __fflush_impl(FILE *f) {

30
libc/stdio/g_rando.S Normal file
View file

@ -0,0 +1,30 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.bss
.align 8
g_rando:
.quad 0
.endobj g_rando,globl
.previous
.init.start 100,_init_g_rando
movb $1,g_rando(%rip)
.init.end 100,_init_g_rando

28
libc/stdio/getentropy.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
#include "libc/sysv/consts/grnd.h"
/**
* Returns random seeding bytes, the XNU/OpenBSD way.
* @see getrandom()
*/
int getentropy(void *buf, size_t size) {
return getrandom(buf, size, GRND_RANDOM);
}

146
libc/stdio/getrandom.c Normal file
View file

@ -0,0 +1,146 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/bits.h"
#include "libc/nexgen32e/kcpuids.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nexgen32e/x86info.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/xorshift.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/grnd.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
static bool have_getrandom;
/**
* Returns cryptographic random data.
*
* This random number seed generator obtains information from:
*
* - getrandom() on Linux
* - RtlGenRandom() on Windows
* - getentropy() on XNU and OpenBSD
* - sysctl(KERN_ARND) on FreeBSD and NetBSD
*
* The following flags may be specified:
*
* - GRND_RANDOM: Halt the entire system while I tap an entropy pool
* so small that it's hard to use statistics to test if it's random
* - GRND_NONBLOCK: Do not wait for i/o events or me to jiggle my
* mouse, and instead return immediately the moment data isn't
* available, even if the result needs to be -1 w/ EAGAIN
*
* This function is safe to use with fork() and vfork(). It will also
* close any file descriptor it ends up needing before it returns.
*
* @note this function could block a nontrivial time on old computers
* @note this function is indeed intended for cryptography
* @note this function takes around 900 cycles
* @asyncsignalsafe
* @restartable
* @vforksafe
*/
ssize_t getrandom(void *p, size_t n, unsigned f) {
char cf;
ssize_t rc;
uint64_t x;
int fd, cmd[2];
size_t i, j, m;
const char *via;
sigset_t neu, old;
if (n > 256) n = 256;
if ((f & ~(GRND_RANDOM | GRND_NONBLOCK))) return einval();
if (IsWindows()) {
via = "RtlGenRandom";
if (RtlGenRandom(p, n)) {
rc = n;
} else {
rc = __winerr();
}
} else if (IsFreebsd() || IsNetbsd()) {
via = "KERN_ARND";
if (IsFreebsd()) {
cmd[0] = 1; /* CTL_KERN */
cmd[1] = 37; /* KERN_ARND */
} else {
cmd[0] = 1; /* CTL_KERN */
cmd[1] = 81; /* KERN_ARND */
}
m = n;
if ((rc = sysctl(cmd, 2, p, &m, 0, 0)) != -1) {
rc = m;
}
} else if (have_getrandom) {
via = "getrandom";
if ((rc = sys_getrandom(p, n, f & (GRND_RANDOM | GRND_NONBLOCK))) != -1) {
if (!rc && (IsXnu() || IsOpenbsd())) {
rc = n;
}
}
} else if ((fd = __sys_openat(
AT_FDCWD,
(via = (f & GRND_RANDOM) ? "/dev/random" : "/dev/urandom"),
O_RDONLY | ((f & GRND_NONBLOCK) ? O_NONBLOCK : 0), 0)) !=
-1) {
rc = sys_read(fd, p, n);
sys_close(fd);
} else {
rc = enosys();
}
STRACE("getrandom(%p, %'zu, %#x) via %s → %'ld% m", p, n, f, via, rc);
return rc;
}
static textstartup void getrandom_init(void) {
int e, rc;
e = errno;
struct sigaction sa, oldsa;
if (IsBsd()) {
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sigaction(SIGSYS, &sa, &oldsa);
}
if (!(rc = sys_getrandom(0, 0, 0))) {
have_getrandom = true;
}
STRACE("sys_getrandom(0,0,0) → %d% m", rc);
if (IsBsd()) {
sigaction(SIGSYS, &oldsa, 0);
}
errno = e;
}
const void *const g_getrandom_init[] initarray = {getrandom_init};

View file

@ -11,6 +11,8 @@ extern char g_stdinbuf[BUFSIZ];
extern char g_stdoutbuf[BUFSIZ];
extern char g_stderrbuf[BUFSIZ];
hidden extern uint64_t g_rando;
int __fflush_impl(FILE *) hidden;
int __fflush_register(FILE *) hidden;
void __fflush_unregister(FILE *) hidden;

14
libc/stdio/lcg.internal.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_LCG_H_
#define COSMOPOLITAN_LIBC_LCG_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
forceinline uint64_t KnuthLinearCongruentialGenerator(uint64_t prev[1]) {
/* Knuth, D.E., "The Art of Computer Programming," Vol 2,
Seminumerical Algorithms, Third Edition, Addison-Wesley, 1998,
p. 106 (line 26) & p. 108 */
prev[0] = prev[0] * 6364136223846793005 + 1442695040888963407;
return prev[0]; /* be sure to shift! */
}
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_LCG_H_ */

45
libc/stdio/lemur64.c Normal file
View file

@ -0,0 +1,45 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
/**
* Returns linear congruential deterministic pseudorandom data, e.g.
*
* uint64_t x = lemur64();
*
* You can generate different types of numbers as follows:
*
* int64_t x = lemur64() >> 1; // make positive signed integer
* double x = _real1(lemur64()); // make float on [0,1]-interval
*
* If you want a fast pseudorandom number generator that seeds itself
* automatically on startup and fork() then consider rand64(). If you
* want true random data then consider rdseed, rdrand, and getrandom.
*
* @return 64 bits of pseudorandom data
* @note this is Lemire's Lehmer generator
* @note this function takes at minimum 1 cycle
* @note this function passes bigcrush and practrand
* @note this function is not intended for cryptography
* @see rand64(), rngset(), _real1(), _real2(), _real3()
*/
uint64_t lemur64(void) {
static uint128_t s = 2131259787901769494;
return (s *= 15750249268501108917ull) >> 64;
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/rand/rand.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/temp.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"

View file

@ -20,8 +20,8 @@
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/rand/lcg.internal.h"
#include "libc/rand/rand.h"
#include "libc/stdio/lcg.internal.h"
#include "libc/stdio/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/temp.h"
#include "libc/str/str.h"

146
libc/stdio/mt19937.c Normal file
View file

@ -0,0 +1,146 @@
/*-*- 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;
}

42
libc/stdio/rand.c Normal file
View file

@ -0,0 +1,42 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/internal.h"
#include "libc/stdio/lcg.internal.h"
#include "libc/stdio/rand.h"
/**
* Returns 31-bit linear congruential pseudorandom number, e.g.
*
* int x = rand();
* assert(x >= 0);
*
* This function always returns a positive number. If srand() isn't
* called, then it'll return the same sequence each time your program
* runs. Faster and more modern alternatives exist to this function.
*
* This function is not thread safe in the sense that multiple threads
* might simultaneously generate the same random values.
*
* @note this function does well on bigcrush and practrand
* @note this function is not intended for cryptography
* @see lemur64(), rand64(), rdrand()
*/
int rand(void) {
return KnuthLinearCongruentialGenerator(&g_rando) >> 33;
}

43
libc/stdio/rand.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef COSMOPOLITAN_LIBC_RAND_RAND_H_
#define COSMOPOLITAN_LIBC_RAND_RAND_H_
#define RAND_MAX __INT_MAX__
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § random
*/
int rand(void);
void srand(uint64_t);
double poz(double);
double pochisq(double, int);
void rt_init(int);
void rt_add(void *, int);
void rt_end(double *, double *, double *, double *, double *);
char *strfry(char *);
int getentropy(void *, size_t);
ssize_t getrandom(void *, size_t, unsigned);
char *initstate(unsigned, char *, size_t);
char *setstate(char *);
long random(void);
void srandom(unsigned);
uint64_t lemur64(void);
uint64_t rand64(void);
uint64_t vigna(void);
uint64_t vigna_r(uint64_t[hasatleast 1]);
void svigna(uint64_t);
uint64_t rdrand(void);
uint64_t rdseed(void);
void _smt19937(uint64_t);
void _Smt19937(uint64_t[], size_t);
uint64_t _mt19937(void);
double _real1(uint64_t);
double _real2(uint64_t);
double _real3(uint64_t);
double MeasureEntropy(const char *, size_t);
void *rngset(void *, size_t, uint64_t (*)(void), size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RAND_RAND_H_ */

0
libc/stdio/rand.mk Executable file
View file

128
libc/stdio/random.c Normal file
View file

@ -0,0 +1,128 @@
/*-*- 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
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/stdio/rand.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/*
* this code uses the same lagged fibonacci generator as the
* original bsd random implementation except for the seeding
* which was broken in the original
*/
static uint32_t init[] = {
0x00000000, 0x5851f42d, 0xc0b18ccf, 0xcbb5f646, 0xc7033129, 0x30705b04,
0x20fd5db4, 0x9a8b7f78, 0x502959d8, 0xab894868, 0x6c0356a7, 0x88cdb7ff,
0xb477d43f, 0x70a3a52b, 0xa8e4baf1, 0xfd8341fc, 0x8ae16fd9, 0x742d2f7a,
0x0d1f0796, 0x76035e09, 0x40f7702c, 0x6fa72ca5, 0xaaa84157, 0x58a0df74,
0xc74a0364, 0xae533cc4, 0x04185faf, 0x6de3b115, 0x0cab8628, 0xf043bfa4,
0x398150e9, 0x37521657,
};
static int n = 31;
static int i = 3;
static int j = 0;
static uint32_t *x = init + 1;
static uint32_t lcg31(uint32_t x) {
return (1103515245 * x + 12345) & 0x7fffffff;
}
static uint64_t lcg64(uint64_t x) {
return 6364136223846793005ull * x + 1;
}
static void *savestate(void) {
x[-1] = (n << 16) | (i << 8) | j;
return x - 1;
}
static void loadstate(uint32_t *state) {
x = state + 1;
n = x[-1] >> 16;
i = (x[-1] >> 8) & 0xff;
j = x[-1] & 0xff;
}
void srandom(unsigned seed) {
int k;
uint64_t s = seed;
if (!n) {
x[0] = s;
return;
}
i = n == 31 || n == 7 ? 3 : 1;
j = 0;
for (k = 0; k < n; k++) {
s = lcg64(s);
x[k] = s >> 32;
}
/* make sure x contains at least one odd number */
x[0] |= 1;
}
char *initstate(unsigned seed, char *state, size_t size) {
void *old;
if (size < 8) return 0;
old = savestate();
if (size < 32) {
n = 0;
} else if (size < 64) {
n = 7;
} else if (size < 128) {
n = 15;
} else if (size < 256) {
n = 31;
} else {
n = 63;
}
x = (uint32_t *)state + 1;
srandom(seed);
savestate();
return old;
}
char *setstate(char *state) {
void *old;
old = savestate();
loadstate((uint32_t *)state);
return old;
}
long random(void) {
long k;
if (!n) return (x[0] = lcg31(x[0]));
x[i] += x[j];
k = x[i] >> 1;
if (++i == n) i = 0;
if (++j == n) j = 0;
return k;
}

81
libc/stdio/rdrand.c Normal file
View file

@ -0,0 +1,81 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/asmflag.h"
#include "libc/errno.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/stdio/rand.h"
#include "libc/sysv/consts/grnd.h"
STATIC_YOINK("rdrand_init");
static dontinline uint64_t rdrand_failover(void) {
int f;
size_t i;
ssize_t r;
volatile uint64_t b;
register uint64_t x;
for (f = GRND_RANDOM | GRND_NONBLOCK, i = 0; i < 8; i += r) {
if ((r = getrandom((char *)&b + i, 8 - i, f)) <= 0) {
if (r == -1 && errno == EINTR) {
r = 0;
} else if (r == -1 && errno == EAGAIN) {
r = 0;
f = 0;
} else {
return rand64();
}
}
}
x = b;
b = 0;
return x;
}
/**
* Retrieves 64-bits of hardware random data from RDRAND instruction.
*
* If RDRAND isn't available (we check CPUID and we also disable it
* automatically for microarchitectures where it's slow or buggy) then
* we try getrandom(), RtlGenRandom(), or sysctl(KERN_ARND). If those
* aren't available then we try /dev/urandom and if that fails, we try
* getauxval(AT_RANDOM), and if not we finally use RDTSC and getpid().
*
* @note this function could block a nontrivial time on old computers
* @note this function is indeed intended for cryptography
* @note this function takes around 300 cycles
* @see rngset(), rdseed(), rand64()
* @asyncsignalsafe
* @vforksafe
*/
uint64_t rdrand(void) {
int i;
char cf;
uint64_t x;
if (X86_HAVE(RDRND)) {
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdrand\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) return x;
asm volatile("pause");
}
}
return rdrand_failover();
}

43
libc/stdio/rdrand_init.c Normal file
View file

@ -0,0 +1,43 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/nexgen32e/kcpuids.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/nexgen32e/x86info.h"
#include "libc/stdio/rand.h"
textstartup void rdrand_init(int argc, char **argv, char **envp,
intptr_t *auxv) {
extern unsigned kMutableCpuids[KCPUIDS_LEN][4] asm("kCpuids");
/*
* Clear RDRAND on AMD models before Zen and then some
* since it's not only slow but can freeze after sleep
* https://bugzilla.redhat.com/show_bug.cgi?id=1150286
*/
if ((X86_HAVE(RDRND) || X86_HAVE(RDSEED)) &&
(IsAuthenticAMD() &&
(kX86CpuFamily < 0x17 ||
(kX86CpuFamily == 0x17 &&
(0x70 <= kX86CpuModel && kX86CpuModel <= 0x7F))))) {
kMutableCpuids[KCPUIDS_1H][KCPUIDS_ECX] &= ~(1u << 30);
kMutableCpuids[KCPUIDS_7H][KCPUIDS_EBX] &= ~(1u << 18);
}
}
const void *const g_rdrand_init[] initarray = {rdrand_init};

56
libc/stdio/rdseed.c Normal file
View file

@ -0,0 +1,56 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/asmflag.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/grnd.h"
/**
* Retrieves 64-bits of true random data from RDSEED instruction.
*
* If RDSEED isn't available, we'll try RDRAND (which we automatically
* disable for microarchitectures where it's known to be slow or buggy).
* If RDRAND isn't available then we try getrandom(), RtlGenRandom(), or
* sysctl(KERN_ARND). If those aren't available then we try /dev/urandom
* and if that fails, we use RDTSC and getpid().
*
* @note this function could block a nontrivial time on old computers
* @note this function is indeed intended for cryptography
* @note this function takes around 800 cycles
* @see rngset(), rdrand(), rand64()
* @asyncsignalsafe
* @vforksafe
*/
uint64_t rdseed(void) {
int i;
char cf;
uint64_t x;
if (X86_HAVE(RDSEED)) {
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdseed\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) return x;
asm volatile("pause");
}
}
return rdrand();
}

30
libc/stdio/real1.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
/**
* Generates number on [0,1]-real-interval, e.g.
*
* double x = _real1(lemur64())
*
* @see lemur64(), mt19937()
*/
double _real1(uint64_t x) {
return 1. / 9007199254740991. * (x >> 11);
}

30
libc/stdio/real2.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
/**
* Generates number on [0,1)-real-interval, e.g.
*
* double x = _real2(lemur64())
*
* @see lemur64(), mt19937()
*/
double _real2(uint64_t x) {
return 1. / 9007199254740992. * (x >> 11);
}

30
libc/stdio/real3.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
/**
* Generates number on (0,1)-real-interval, e.g.
*
* double x = _real3(lemur64())
*
* @see lemur64(), mt19937()
*/
double _real3(uint64_t x) {
return 1. / 4503599627370496. * ((x >> 12) + .5);
}

94
libc/stdio/rngset.c Normal file
View file

@ -0,0 +1,94 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
/**
* Fills memory with random bytes, e.g.
*
* char buf[512];
* rngset(buf, sizeof(buf), 0, 0);
*
* If reseed is zero then the internal PRNG is disabled and bytes are
* simply copied in little-endian order from the seed function. If seed
* is NULL then the reseed parameter is used as the seed value for the
* internal PRNG. If seed!=NULL and reseed>8 then reseed is the number
* of bytes after which the seed() function should be called again, to
* freshen up the PRNG.
*
* The main advantage of this generator is that it produces data at 13
* gigabytes per second since Vigna's Algorithm vectorizes better than
* alternatives, going even faster than xorshift.
*
* @return original buf
*/
noasan void *rngset(void *b, size_t n, uint64_t seed(void), size_t reseed) {
size_t m;
uint64_t i, x, t = 0;
unsigned char *p = b;
if (IsAsan()) {
__asan_verify(b, n);
}
if (!seed) {
t = reseed;
reseed = -1;
} else if (reseed < 8) {
reseed = 8;
}
while (n) {
if (seed) t = seed();
if (!seed || reseed > 8) {
n -= (m = reseed < n ? reseed : n);
while (m >= 8) {
x = (t += 0x9e3779b97f4a7c15);
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
x = (x ^ (x >> 31));
__builtin_memcpy(p, &x, 8);
p += 8;
m -= 8;
}
while (m--) {
*p++ = t;
t >>= 8;
}
} else if (n >= 8) {
p[0] = (0x00000000000000FF & t) >> 000;
p[1] = (0x000000000000FF00 & t) >> 010;
p[2] = (0x0000000000FF0000 & t) >> 020;
p[3] = (0x00000000FF000000 & t) >> 030;
p[4] = (0x000000FF00000000 & t) >> 040;
p[5] = (0x0000FF0000000000 & t) >> 050;
p[6] = (0x00FF000000000000 & t) >> 060;
p[7] = (0xFF00000000000000 & t) >> 070;
p += 8;
n -= 8;
} else {
while (n) {
*p++ = t;
t >>= 8;
--n;
}
}
}
return b;
}

26
libc/stdio/srand.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
extern uint64_t g_rando;
/**
* Seeds random number generator that's used by rand().
*/
void(srand)(uint64_t seed) { g_rando = seed; }

View file

@ -29,8 +29,8 @@ LIBC_STDIO_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_KERNEL32 \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \
@ -57,6 +57,10 @@ o//libc/stdio/appendw.o: private \
OVERRIDE_CFLAGS += \
-Os
o/$(MODE)/libc/stdio/mt19937.o: private \
OVERRIDE_CFLAGS += \
-ffunction-sections
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS))

29
libc/stdio/strfry.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/shuffle.internal.h"
#include "libc/stdio/rand.h"
#include "libc/str/str.h"
/**
* Jumbles up string.
*/
char *strfry(char *s) {
shuffle(rand, s, strlen(s));
return s;
}

View file

@ -18,7 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/rand/rand.h"
#include "libc/stdio/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/temp.h"
#include "libc/str/str.h"

78
libc/stdio/vigna.c Normal file
View file

@ -0,0 +1,78 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/rand.h"
static uint64_t g_vigna;
/**
* Returns deterministic pseudorandom data, e.g.
*
* uint64_t x = vigna();
*
* You can generate different types of numbers as follows:
*
* int64_t x = vigna() >> 1; // make positive signed integer
* double x = _real1(vigna()); // make float on [0,1]-interval
*
* You can seed this random number generator using:
*
* svigna(rdseed());
*
* You may use the reentrant version of this function:
*
* static uint64_t s = 0;
* uint64_t x = svigna_r(&s);
*
* If you want to fill a buffer with data then rngset() implements
* vigna's algorithm to do that extremely well:
*
* char buf[4096];
* rngset(buf, sizeof(buf), vigna, 0);
*
* If you want a fast pseudorandom number generator that seeds itself
* automatically on startup and fork() then consider rand64(). If you
* want true random data then consider rdseed, rdrand, and getrandom.
*
* @return 64 bits of pseudorandom data
* @note this function is not intended for cryptography
* @note this function passes bigcrush and practrand
* @note this function takes at minimum 4 cycles
*/
uint64_t vigna(void) {
return vigna_r(&g_vigna);
}
/**
* Returns pseudorandom data.
* @see vigna() for easy api
*/
uint64_t vigna_r(uint64_t state[hasatleast 1]) {
uint64_t z = (state[0] += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
/**
* Seeds vigna() pseudorandom number generator.
* @see vigna(), vigna_r()
*/
void svigna(uint64_t seed) {
g_vigna = seed;
}

15
libc/stdio/xorshift.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_
#define COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_
#define kMarsagliaXorshift64Seed 88172645463325252
#define kMarsagliaXorshift32Seed 2463534242
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
uint32_t MarsagliaXorshift32(uint32_t[hasatleast 1]);
uint64_t MarsagliaXorshift64(uint64_t[hasatleast 1]);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_ */

28
libc/stdio/xorshift32.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/xorshift.h"
uint32_t MarsagliaXorshift32(uint32_t state[hasatleast 1]) {
uint32_t x = state[0];
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
state[0] = x;
return x;
}

28
libc/stdio/xorshift64.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/stdio/xorshift.h"
uint64_t MarsagliaXorshift64(uint64_t state[hasatleast 1]) {
uint64_t x = state[0];
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
state[0] = x;
return x;
}