mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
54
libc/rand/devrand.c
Normal file
54
libc/rand/devrand.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Reads random bytes from system pseudo random number api.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int devrand(void *buf, size_t size) {
|
||||
int fd;
|
||||
size_t got;
|
||||
ssize_t rc;
|
||||
unsigned char *p, *pe;
|
||||
fd = -1;
|
||||
if (IsWindows()) return enosys();
|
||||
if ((fd = openat$sysv(AT_FDCWD, "/dev/urandom", O_RDONLY, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
p = buf;
|
||||
pe = p + size;
|
||||
while (p < pe) {
|
||||
if ((rc = read$sysv(fd, p, pe - p)) == -1) break;
|
||||
if (!(got = (size_t)rc)) break;
|
||||
p += got;
|
||||
}
|
||||
close$sysv(fd);
|
||||
return p == pe ? 0 : -1;
|
||||
}
|
32
libc/rand/g_rando.S
Normal file
32
libc/rand/g_rando.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:asm; 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
.yoink __FILE__
|
||||
|
||||
.bss
|
||||
.align 8
|
||||
g_rando:.quad 0
|
||||
.endobj g_rando,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 100,_init_g_rando
|
||||
movq $1,g_rando(%rip)
|
||||
.init.end 100,_init_g_rando
|
48
libc/rand/g_rando32.c
Normal file
48
libc/rand/g_rando32.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
hidden uint32_t g_rando32;
|
||||
|
||||
textstartup static void g_rando32_init() {
|
||||
register intptr_t *auxv asm("r15"); /* @see libc/crt/crt.S */
|
||||
asm volatile("" : "=r"(auxv));
|
||||
if (!IsXnu() && !IsWindows()) {
|
||||
for (intptr_t *auxvp = auxv; auxvp[0]; auxvp += 2) {
|
||||
if (auxvp[0] == AT_RANDOM) {
|
||||
uint8_t(*sysrandseed)[16] = (uint8_t(*)[16])auxvp[1];
|
||||
if (sysrandseed) g_rando32 ^= read32le(&(*sysrandseed)[8]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_rando32 ^= kMarsagliaXorshift32Seed;
|
||||
if (IsWindows()) {
|
||||
g_rando32 ^= winrandish();
|
||||
} else {
|
||||
devrand(&g_rando32, sizeof(g_rando32));
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_rando32_ctor[] initarray = {g_rando32_init};
|
48
libc/rand/g_rando64.c
Normal file
48
libc/rand/g_rando64.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
hidden uint64_t g_rando64;
|
||||
|
||||
textstartup static void g_rando64_init() {
|
||||
register intptr_t *auxv asm("r15"); /* @see libc/crt/crt.S */
|
||||
asm volatile("" : "=r"(auxv));
|
||||
if (!IsXnu() && !IsWindows()) {
|
||||
for (intptr_t *auxvp = auxv; auxvp[0]; auxvp += 2) {
|
||||
if (auxvp[0] == AT_RANDOM) {
|
||||
uint8_t(*sysrandseed)[16] = (uint8_t(*)[16])auxvp[1];
|
||||
if (sysrandseed) g_rando64 ^= read64le(&(*sysrandseed)[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_rando64 ^= kMarsagliaXorshift64Seed;
|
||||
if (IsWindows()) {
|
||||
g_rando64 ^= winrandish();
|
||||
} else {
|
||||
devrand(&g_rando64, sizeof(g_rando64));
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_rando64_ctor[] initarray = {g_rando64_init};
|
29
libc/rand/getentropy.c
Normal file
29
libc/rand/getentropy.c
Normal 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/rand/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);
|
||||
}
|
51
libc/rand/getrandom.c
Normal file
51
libc/rand/getrandom.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns random bytes appropriate for random seeding.
|
||||
*
|
||||
* @param size should be the smallest value that meets your requirements
|
||||
* @param flags may be GRND_{RANDOM,NONBLOCK}
|
||||
* @return number of bytes copied on success; or -1 w/ errno, which
|
||||
* indicates only that the request couldn't be serviced by the host
|
||||
* kernel; this wrapper will still fill the buffer with random bytes
|
||||
* from fallback sources no matter what
|
||||
*/
|
||||
ssize_t getrandom(void *buf, size_t size, unsigned flags) {
|
||||
ssize_t rc = getrandom$sysv(buf, size, flags);
|
||||
size_t i = rc == -1 ? 0 : (size_t)rc;
|
||||
if (i > size) abort();
|
||||
if (i < size) {
|
||||
unsigned char *p = buf;
|
||||
int olderr = errno;
|
||||
do {
|
||||
uint64_t i64 = rand64();
|
||||
memcpy(&p[i], &i64, min(sizeof(i64), size - i));
|
||||
} while ((i += sizeof(uint64_t)) < size);
|
||||
errno = olderr;
|
||||
}
|
||||
return rc;
|
||||
}
|
10
libc/rand/internal.h
Normal file
10
libc/rand/internal.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RAND_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_RAND_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
hidden extern uint64_t g_rando;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RAND_INTERNAL_H_ */
|
16
libc/rand/lcg.h
Normal file
16
libc/rand/lcg.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LCG_H_
|
||||
#define COSMOPOLITAN_LIBC_LCG_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LCG_H_ */
|
142
libc/rand/poz.c
Normal file
142
libc/rand/poz.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi│
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
/* clang-format off */
|
||||
/*
|
||||
|
||||
Compute probability of measured Chi Square value.
|
||||
|
||||
This code was developed by Gary Perlman of the Wang
|
||||
Institute (full citation below) and has been minimally
|
||||
modified for use in this program.
|
||||
|
||||
*/
|
||||
|
||||
#include "libc/math.h"
|
||||
|
||||
/*HEADER
|
||||
Module: z.c
|
||||
Purpose: compute approximations to normal z distribution probabilities
|
||||
Programmer: Gary Perlman
|
||||
Organization: Wang Institute, Tyngsboro, MA 01879
|
||||
Copyright: none
|
||||
Tabstops: 4
|
||||
*/
|
||||
|
||||
#define Z_MAX 6.0 /* maximum meaningful z value */
|
||||
|
||||
/*FUNCTION poz: probability of normal z value */
|
||||
/*ALGORITHM
|
||||
Adapted from a polynomial approximation in:
|
||||
Ibbetson D, Algorithm 209
|
||||
Collected Algorithms of the CACM 1963 p. 616
|
||||
Note:
|
||||
This routine has six digit accuracy, so it is only useful for absolute
|
||||
z values < 6. For z values >= to 6.0, poz() returns 0.0.
|
||||
*/
|
||||
static double /*VAR returns cumulative probability from -oo to z */
|
||||
poz(const double z) /*VAR normal z value */
|
||||
{
|
||||
double y, x, w;
|
||||
|
||||
if (z == 0.0) {
|
||||
x = 0.0;
|
||||
} else {
|
||||
y = 0.5 * fabs(z);
|
||||
if (y >= (Z_MAX * 0.5)) {
|
||||
x = 1.0;
|
||||
} else if (y < 1.0) {
|
||||
w = y * y;
|
||||
x = ((((((((0.000124818987 * w
|
||||
-0.001075204047) * w +0.005198775019) * w
|
||||
-0.019198292004) * w +0.059054035642) * w
|
||||
-0.151968751364) * w +0.319152932694) * w
|
||||
-0.531923007300) * w +0.797884560593) * y * 2.0;
|
||||
} else {
|
||||
y -= 2.0;
|
||||
x = (((((((((((((-0.000045255659 * y
|
||||
+0.000152529290) * y -0.000019538132) * y
|
||||
-0.000676904986) * y +0.001390604284) * y
|
||||
-0.000794620820) * y -0.002034254874) * y
|
||||
+0.006549791214) * y -0.010557625006) * y
|
||||
+0.011630447319) * y -0.009279453341) * y
|
||||
+0.005353579108) * y -0.002141268741) * y
|
||||
+0.000535310849) * y +0.999936657524;
|
||||
}
|
||||
}
|
||||
return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
|
||||
}
|
||||
|
||||
/*
|
||||
Module: chisq.c
|
||||
Purpose: compute approximations to chisquare distribution probabilities
|
||||
Contents: pochisq()
|
||||
Uses: poz() in z.c (Algorithm 209)
|
||||
Programmer: Gary Perlman
|
||||
Organization: Wang Institute, Tyngsboro, MA 01879
|
||||
Copyright: none
|
||||
Tabstops: 4
|
||||
*/
|
||||
|
||||
#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */
|
||||
#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */
|
||||
#define BIGX 20.0 /* max value to represent exp (x) */
|
||||
#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x))
|
||||
|
||||
/*FUNCTION pochisq: probability of chi sqaure value */
|
||||
/*ALGORITHM Compute probability of chi square value.
|
||||
Adapted from:
|
||||
Hill, I. D. and Pike, M. C. Algorithm 299
|
||||
Collected Algorithms for the CACM 1967 p. 243
|
||||
Updated for rounding errors based on remark in
|
||||
ACM TOMS June 1985, page 185
|
||||
*/
|
||||
|
||||
double pochisq(
|
||||
const double ax, /* obtained chi-square value */
|
||||
const int df /* degrees of freedom */
|
||||
)
|
||||
{
|
||||
double x = ax;
|
||||
double a, y, s;
|
||||
double e, c, z;
|
||||
int even; /* true if df is an even number */
|
||||
|
||||
y = 0.0; /* XXX: blind modification due to GCC error */
|
||||
|
||||
if (x <= 0.0 || df < 1) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
a = 0.5 * x;
|
||||
even = (2 * (df / 2)) == df;
|
||||
if (df > 1) {
|
||||
y = ex(-a);
|
||||
}
|
||||
s = (even ? y : (2.0 * poz(-sqrt(x))));
|
||||
if (df > 2) {
|
||||
x = 0.5 * (df - 1.0);
|
||||
z = (even ? 1.0 : 0.5);
|
||||
if (a > BIGX) {
|
||||
e = (even ? 0.0 : LOG_SQRT_PI);
|
||||
c = log(a);
|
||||
while (z <= x) {
|
||||
e = log(z) + e;
|
||||
s += ex(c * z - a - e);
|
||||
z += 1.0;
|
||||
}
|
||||
return (s);
|
||||
} else {
|
||||
e = (even ? 1.0 : (I_SQRT_PI / sqrt(a)));
|
||||
c = 0.0;
|
||||
while (z <= x) {
|
||||
e = e * (a / z);
|
||||
c = c + e;
|
||||
z += 1.0;
|
||||
}
|
||||
return (c * y + s);
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
36
libc/rand/rand.h
Normal file
36
libc/rand/rand.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RAND_RAND_H_
|
||||
#define COSMOPOLITAN_LIBC_RAND_RAND_H_
|
||||
#include "libc/ncabi.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § random ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define RAND_MAX __INT_MAX__ /* only applies to rand() */
|
||||
void srand(uint64_t) nothrow nocallback; /* seeds rand() only */
|
||||
int rand(void) nothrow nocallback; /* ≥0 unseeded lcg prng */
|
||||
uint32_t rand32(void) nothrow nocallback; /* random as possible rng */
|
||||
uint64_t rand64(void) nothrow nocallback; /* random as possible rng */
|
||||
double poz(double); /* verify our claims */
|
||||
double pochisq(double, int);
|
||||
void rt_init(int);
|
||||
void rt_add(void *, int);
|
||||
void rt_end(double *, double *, double *, double *, double *);
|
||||
void *rngset(void *, size_t, uint64_t (*)(void), size_t) paramsnonnull();
|
||||
char *strfry(char *);
|
||||
int getentropy(void *, size_t);
|
||||
ssize_t getrandom(void *, size_t, unsigned);
|
||||
int devrand(void *, size_t);
|
||||
int64_t winrandish(void);
|
||||
uint64_t rdrand(void);
|
||||
float randf(void);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
NCABI_DECLARE_0(NCABI_NOPRUNE, int, __rand, "rand")
|
||||
#define rand() __rand()
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RAND_RAND_H_ */
|
54
libc/rand/rand.mk
Normal file
54
libc/rand/rand.mk
Normal file
|
@ -0,0 +1,54 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += LIBC_RAND
|
||||
|
||||
LIBC_RAND_ARTIFACTS += LIBC_RAND_A
|
||||
LIBC_RAND = $(LIBC_RAND_A_DEPS) $(LIBC_RAND_A)
|
||||
LIBC_RAND_A = o/$(MODE)/libc/rand/rand.a
|
||||
LIBC_RAND_A_FILES := $(wildcard libc/rand/*)
|
||||
LIBC_RAND_A_HDRS = $(filter %.h,$(LIBC_RAND_A_FILES))
|
||||
LIBC_RAND_A_SRCS_S = $(filter %.S,$(LIBC_RAND_A_FILES))
|
||||
LIBC_RAND_A_SRCS_C = $(filter %.c,$(LIBC_RAND_A_FILES))
|
||||
|
||||
LIBC_RAND_A_SRCS = \
|
||||
$(LIBC_RAND_A_SRCS_S) \
|
||||
$(LIBC_RAND_A_SRCS_C)
|
||||
|
||||
LIBC_RAND_A_OBJS = \
|
||||
$(LIBC_RAND_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_RAND_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_RAND_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_RAND_A_CHECKS = \
|
||||
$(LIBC_RAND_A).pkg \
|
||||
$(LIBC_RAND_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_RAND_A_DIRECTDEPS = \
|
||||
LIBC_STUBS \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_SYSV
|
||||
|
||||
LIBC_RAND_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_RAND_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_RAND_A): libc/rand/ \
|
||||
$(LIBC_RAND_A).pkg \
|
||||
$(LIBC_RAND_A_OBJS)
|
||||
|
||||
$(LIBC_RAND_A).pkg: \
|
||||
$(LIBC_RAND_A_OBJS) \
|
||||
$(foreach x,$(LIBC_RAND_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
LIBC_RAND_LIBS = $(foreach x,$(LIBC_RAND_ARTIFACTS),$($(x)))
|
||||
LIBC_RAND_SRCS = $(foreach x,$(LIBC_RAND_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_RAND_HDRS = $(foreach x,$(LIBC_RAND_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_RAND_CHECKS = $(foreach x,$(LIBC_RAND_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_RAND_OBJS = $(foreach x,$(LIBC_RAND_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_RAND_OBJS): $(BUILD_FILES) libc/rand/rand.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/rand
|
||||
o/$(MODE)/libc/rand: $(LIBC_RAND_CHECKS)
|
31
libc/rand/rand.ncabi.c
Normal file
31
libc/rand/rand.ncabi.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/rand/internal.h"
|
||||
#include "libc/rand/lcg.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Returns 31-bit random number using a linear congruential generator.
|
||||
*
|
||||
* Please note that, unlike rand32(), the rand() function uses the same
|
||||
* seed at startup by default, unless srand() is called. This makes it
|
||||
* useful in cases where deterministic behavior is needed.
|
||||
*/
|
||||
int(rand)(void) { return KnuthLinearCongruentialGenerator(&g_rando) >> 33; }
|
42
libc/rand/rand32.c
Normal file
42
libc/rand/rand32.c
Normal 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=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
|
||||
/**
|
||||
* This function is an independent 32-bit clone of rand64().
|
||||
*/
|
||||
nodebuginfo uint32_t(rand32)(void) {
|
||||
uint32_t res;
|
||||
if (X86_HAVE(RDRND)) {
|
||||
res = rdrand();
|
||||
} else {
|
||||
if (IsWindows()) {
|
||||
res = kMarsagliaXorshift32Seed ^ winrandish();
|
||||
} else {
|
||||
devrand(&res, sizeof(res));
|
||||
}
|
||||
hidden extern uint32_t g_rando32;
|
||||
res ^= MarsagliaXorshift32(&g_rando32);
|
||||
}
|
||||
return res;
|
||||
}
|
49
libc/rand/rand64.c
Normal file
49
libc/rand/rand64.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
|
||||
/**
|
||||
* Returns nondeterministic random number.
|
||||
*
|
||||
* This function uses a good random source if it's available, which
|
||||
* takes ~400 cycles (~99ns). Otherwise it's seeded at program start
|
||||
* with the system provided random value and may perform a few
|
||||
* microseconds worth of system calls to get a good value.
|
||||
*
|
||||
* @see rngset()
|
||||
*/
|
||||
nodebuginfo uint64_t(rand64)(void) {
|
||||
uint64_t res;
|
||||
if (X86_HAVE(RDRND)) {
|
||||
res = rdrand();
|
||||
} else {
|
||||
if (IsWindows()) {
|
||||
res = winrandish();
|
||||
} else {
|
||||
devrand(&res, sizeof(res));
|
||||
}
|
||||
hidden extern uint64_t g_rando64;
|
||||
res ^= MarsagliaXorshift64(&g_rando64);
|
||||
}
|
||||
return res;
|
||||
}
|
28
libc/rand/randf.c
Normal file
28
libc/rand/randf.c
Normal 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/rand/internal.h"
|
||||
#include "libc/rand/lcg.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
float randf(void) {
|
||||
return (float)(int)(KnuthLinearCongruentialGenerator(&g_rando) >> 32) /
|
||||
INT_MAX;
|
||||
}
|
22
libc/rand/rando.c
Normal file
22
libc/rand/rando.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/rand/internal.h"
|
||||
|
||||
uint64_t g_rando;
|
184
libc/rand/randtest.c
Normal file
184
libc/rand/randtest.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/* clang-format off */
|
||||
/*
|
||||
|
||||
Apply various randomness tests to a stream of bytes
|
||||
|
||||
by John Walker -- September 1996
|
||||
http://www.fourmilab.ch/
|
||||
|
||||
*/
|
||||
|
||||
#include "libc/math.h"
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define log2of10 3.32192809488736234787
|
||||
|
||||
static int binary = FALSE; /* Treat input as a bitstream */
|
||||
|
||||
static long ccount[256], /* Bins to count occurrences of values */
|
||||
totalc = 0; /* Total bytes counted */
|
||||
static double prob[256]; /* Probabilities per bin for entropy */
|
||||
|
||||
/* RT_LOG2 -- Calculate log to the base 2 */
|
||||
|
||||
static double rt_log2(double x)
|
||||
{
|
||||
return log2of10 * log10(x);
|
||||
}
|
||||
|
||||
#define MONTEN 6 /* Bytes used as Monte Carlo
|
||||
co-ordinates. This should be no more
|
||||
bits than the mantissa of your
|
||||
"double" floating point type. */
|
||||
|
||||
static int mp, sccfirst;
|
||||
static unsigned int monte[MONTEN];
|
||||
static long inmont, mcount;
|
||||
static double cexp_, incirc, montex, montey, montepi,
|
||||
scc, sccun, sccu0, scclast, scct1, scct2, scct3,
|
||||
ent, chisq, datasum;
|
||||
|
||||
/* RT_INIT -- Initialise random test counters. */
|
||||
|
||||
void rt_init(int binmode)
|
||||
{
|
||||
int i;
|
||||
|
||||
binary = binmode; /* Set binary / byte mode */
|
||||
|
||||
/* Initialise for calculations */
|
||||
|
||||
ent = 0.0; /* Clear entropy accumulator */
|
||||
chisq = 0.0; /* Clear Chi-Square */
|
||||
datasum = 0.0; /* Clear sum of bytes for arithmetic mean */
|
||||
|
||||
mp = 0; /* Reset Monte Carlo accumulator pointer */
|
||||
mcount = 0; /* Clear Monte Carlo tries */
|
||||
inmont = 0; /* Clear Monte Carlo inside count */
|
||||
incirc = 65535.0 * 65535.0;/* In-circle distance for Monte Carlo */
|
||||
|
||||
sccfirst = TRUE; /* Mark first time for serial correlation */
|
||||
scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */
|
||||
|
||||
incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ccount[i] = 0;
|
||||
}
|
||||
totalc = 0;
|
||||
}
|
||||
|
||||
/* RT_ADD -- Add one or more bytes to accumulation. */
|
||||
|
||||
void rt_add(void *buf, int bufl)
|
||||
{
|
||||
unsigned char *bp = buf;
|
||||
int oc, c, bean;
|
||||
|
||||
while (bean = 0, (bufl-- > 0)) {
|
||||
oc = *bp++;
|
||||
|
||||
do {
|
||||
if (binary) {
|
||||
c = !!(oc & 0x80);
|
||||
} else {
|
||||
c = oc;
|
||||
}
|
||||
ccount[c]++; /* Update counter for this bin */
|
||||
totalc++;
|
||||
|
||||
/* Update inside / outside circle counts for Monte Carlo
|
||||
computation of PI */
|
||||
|
||||
if (bean == 0) {
|
||||
monte[mp++] = oc; /* Save character for Monte Carlo */
|
||||
if (mp >= MONTEN) { /* Calculate every MONTEN character */
|
||||
int mj;
|
||||
|
||||
mp = 0;
|
||||
mcount++;
|
||||
montex = montey = 0;
|
||||
for (mj = 0; mj < MONTEN / 2; mj++) {
|
||||
montex = (montex * 256.0) + monte[mj];
|
||||
montey = (montey * 256.0) + monte[(MONTEN / 2) + mj];
|
||||
}
|
||||
if ((montex * montex + montey * montey) <= incirc) {
|
||||
inmont++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update calculation of serial correlation coefficient */
|
||||
|
||||
sccun = c;
|
||||
if (sccfirst) {
|
||||
sccfirst = FALSE;
|
||||
scclast = 0;
|
||||
sccu0 = sccun;
|
||||
} else {
|
||||
scct1 = scct1 + scclast * sccun;
|
||||
}
|
||||
scct2 = scct2 + sccun;
|
||||
scct3 = scct3 + (sccun * sccun);
|
||||
scclast = sccun;
|
||||
oc <<= 1;
|
||||
} while (binary && (++bean < 8));
|
||||
}
|
||||
}
|
||||
|
||||
/* RT_END -- Complete calculation and return results. */
|
||||
|
||||
void rt_end(double *r_ent, double *r_chisq, double *r_mean,
|
||||
double *r_montepicalc, double *r_scc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Complete calculation of serial correlation coefficient */
|
||||
|
||||
scct1 = scct1 + scclast * sccu0;
|
||||
scct2 = scct2 * scct2;
|
||||
scc = totalc * scct3 - scct2;
|
||||
if (scc == 0.0) {
|
||||
scc = -100000;
|
||||
} else {
|
||||
scc = (totalc * scct1 - scct2) / scc;
|
||||
}
|
||||
|
||||
/* Scan bins and calculate probability for each bin and
|
||||
Chi-Square distribution. The probability will be reused
|
||||
in the entropy calculation below. While we're at it,
|
||||
we sum of all the data which will be used to compute the
|
||||
mean. */
|
||||
|
||||
cexp_ = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */
|
||||
for (i = 0; i < (binary ? 2 : 256); i++) {
|
||||
double a = ccount[i] - cexp_;
|
||||
|
||||
prob[i] = ((double) ccount[i]) / totalc;
|
||||
chisq += (a * a) / cexp_;
|
||||
datasum += ((double) i) * ccount[i];
|
||||
}
|
||||
|
||||
/* Calculate entropy */
|
||||
|
||||
for (i = 0; i < (binary ? 2 : 256); i++) {
|
||||
if (prob[i] > 0.0) {
|
||||
ent += prob[i] * rt_log2(1 / prob[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate Monte Carlo value for PI from percentage of hits
|
||||
within the circle */
|
||||
|
||||
montepi = 4.0 * (((double) inmont) / mcount);
|
||||
|
||||
/* Return results through arguments */
|
||||
|
||||
*r_ent = ent;
|
||||
*r_chisq = chisq;
|
||||
*r_mean = datasum / totalc;
|
||||
*r_montepicalc = montepi;
|
||||
*r_scc = scc;
|
||||
}
|
47
libc/rand/rdrand.c
Normal file
47
libc/rand/rdrand.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Intel Secure Key Digital Random Number Generator
|
||||
* Introduced w/ Ivy Bridge c. 2013 and Excavator c. 2015
|
||||
* @see rand32(), rand64(), and randcpy()
|
||||
*/
|
||||
uint64_t rdrand(void) {
|
||||
char cf;
|
||||
size_t i;
|
||||
uint64_t res;
|
||||
assert(X86_HAVE(RDRND));
|
||||
for (;;) {
|
||||
for (i = 0; i < 10; ++i) {
|
||||
/* CF=1: Destination register valid. Quoth Intel DRNG-SIG 4.1.3 */
|
||||
asm volatile(CFLAG("rdrand\t%1")
|
||||
: CF(cf), "=r"(res)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return res;
|
||||
}
|
||||
asm volatile("rep nop"); /* unlikely 140 cycle spin */
|
||||
}
|
||||
}
|
54
libc/rand/rngset.c
Normal file
54
libc/rand/rngset.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Fills memory with random bytes.
|
||||
*
|
||||
* @param seed can be rand64
|
||||
* @param reseed is number of bytes between seed() calls
|
||||
* @return buf
|
||||
*/
|
||||
void *rngset(void *buf, size_t size, uint64_t (*seed)(void), size_t reseed) {
|
||||
unsigned char *p;
|
||||
uint64_t i, x, state;
|
||||
i = 0;
|
||||
p = buf;
|
||||
state = seed();
|
||||
for (i = 0; size - i >= sizeof(x); i += sizeof(x)) {
|
||||
x = MarsagliaXorshift64(&state);
|
||||
memcpy(p + i, &x, sizeof(x));
|
||||
if (i >= reseed) {
|
||||
state = seed();
|
||||
p += i;
|
||||
size -= i;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (i < size) {
|
||||
x = MarsagliaXorshift64(&state);
|
||||
for (; i < size; ++i, x >>= 8) {
|
||||
p[i] = x & 0xff;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
27
libc/rand/srand.c
Normal file
27
libc/rand/srand.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
extern uint64_t g_rando;
|
||||
|
||||
/**
|
||||
* Seeds random number generator that's used by rand().
|
||||
*/
|
||||
void(srand)(uint64_t seed) { g_rando = seed; }
|
30
libc/rand/strfry.c
Normal file
30
libc/rand/strfry.c
Normal 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/shuffle.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Jumbles up string.
|
||||
*/
|
||||
char *strfry(char *s) {
|
||||
shuffle(rand, s, strlen(s));
|
||||
return s;
|
||||
}
|
44
libc/rand/winrandish.c
Normal file
44
libc/rand/winrandish.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/struct/point.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/rand/rand.h"
|
||||
|
||||
/**
|
||||
* Returns somewhat randomish number on Windows.
|
||||
*/
|
||||
textwindows int64_t winrandish(void) {
|
||||
int64_t res;
|
||||
struct NtPoint point;
|
||||
res = ((int64_t)NtGetPid() << 17) ^ NtGetTid() ^ rdtsc();
|
||||
/*
|
||||
* This function is intended for older CPUs built before 2012, so
|
||||
* let's avoid having our CUI apps yoink USER32.DLL until we're
|
||||
* certain we need it, thus avoiding a hundred lines of noise in
|
||||
* NtTrace.exe output.
|
||||
*/
|
||||
typeof(GetCursorPos) *GetCursorPos_ =
|
||||
GetProcAddress(GetModuleHandle("user32.dll"), "GetCursorPos");
|
||||
if (GetCursorPos_ && GetCursorPos_(&point)) res ^= point.x * point.y;
|
||||
return res;
|
||||
}
|
28
libc/rand/xorshift.h
Normal file
28
libc/rand/xorshift.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_
|
||||
#define COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_
|
||||
|
||||
#define kMarsagliaXorshift64Seed 88172645463325252
|
||||
#define kMarsagliaXorshift32Seed 2463534242
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline 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;
|
||||
}
|
||||
|
||||
forceinline 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;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RAND_XORSHIFT_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue