mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
320 lines
7.7 KiB
C
320 lines
7.7 KiB
C
#if 0
|
|
/*─────────────────────────────────────────────────────────────────╗
|
|
│ To the extent possible under law, Justine Tunney has waived │
|
|
│ all copyright and related or neighboring rights to this file, │
|
|
│ as it is written in the following disclaimers: │
|
|
│ • http://unlicense.org/ │
|
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
|
╚─────────────────────────────────────────────────────────────────*/
|
|
#endif
|
|
#include "ape/sections.internal.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/calls/struct/sigaction.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/fmt/conv.h"
|
|
#include "libc/intrin/bits.h"
|
|
#include "libc/log/check.h"
|
|
#include "libc/log/log.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/mem/mem.h"
|
|
#include "libc/nexgen32e/x86feature.h"
|
|
#include "libc/nt/runtime.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/stdio/rand.h"
|
|
#include "libc/stdio/stdio.h"
|
|
#include "libc/stdio/xorshift.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/ex.h"
|
|
#include "libc/sysv/consts/exit.h"
|
|
#include "libc/sysv/consts/grnd.h"
|
|
#include "libc/sysv/consts/sig.h"
|
|
#include "libc/testlib/hyperion.h"
|
|
#include "third_party/getopt/getopt.h"
|
|
|
|
#define B 4096
|
|
|
|
bool isdone;
|
|
bool isbinary;
|
|
unsigned long count = -1;
|
|
|
|
uint64_t bcast(uint64_t f(void)) {
|
|
unsigned i;
|
|
uint64_t x;
|
|
for (x = i = 0; i < 8; ++i) {
|
|
x <<= 8;
|
|
x |= f() & 255;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
uint64_t randv6(void) {
|
|
static int16_t gorp;
|
|
gorp = (gorp + 625) & 077777;
|
|
return gorp;
|
|
}
|
|
|
|
uint64_t randv7(void) {
|
|
static uint32_t randx = 1;
|
|
return ((randx = randx * 1103515245 + 12345) >> 16) & 077777;
|
|
}
|
|
|
|
uint64_t zero(void) {
|
|
return 0;
|
|
}
|
|
|
|
uint64_t inc(void) {
|
|
static uint64_t x;
|
|
return x++;
|
|
}
|
|
|
|
uint64_t unixv6(void) {
|
|
return bcast(randv6);
|
|
}
|
|
|
|
uint64_t unixv7(void) {
|
|
return bcast(randv7);
|
|
}
|
|
|
|
uint64_t ape(void) {
|
|
static int i;
|
|
if ((i += 8) > _end - _base) i = 8;
|
|
return READ64LE(_base + i);
|
|
}
|
|
|
|
uint64_t moby(void) {
|
|
static int i;
|
|
if ((i += 8) > kMobySize) i = 8;
|
|
return READ64LE(kMoby + i);
|
|
}
|
|
|
|
uint64_t knuth(void) {
|
|
uint64_t a, b;
|
|
static uint64_t x = 1;
|
|
x *= 6364136223846793005;
|
|
x += 1442695040888963407;
|
|
a = x >> 32;
|
|
x *= 6364136223846793005;
|
|
x += 1442695040888963407;
|
|
b = x >> 32;
|
|
return a | b << 32;
|
|
}
|
|
|
|
uint64_t rngset64(void) {
|
|
static unsigned i;
|
|
static uint64_t s;
|
|
if (!i) {
|
|
s = _rand64();
|
|
i = (s + 1) & (511);
|
|
}
|
|
return MarsagliaXorshift64(&s);
|
|
}
|
|
|
|
uint64_t xorshift64(void) {
|
|
static uint64_t s = kMarsagliaXorshift64Seed;
|
|
return MarsagliaXorshift64(&s);
|
|
}
|
|
|
|
uint64_t xorshift32(void) {
|
|
static uint32_t s = kMarsagliaXorshift32Seed;
|
|
uint64_t a = MarsagliaXorshift32(&s);
|
|
uint64_t b = MarsagliaXorshift32(&s);
|
|
return (uint64_t)a << 32 | b;
|
|
}
|
|
|
|
uint64_t libc(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, 0));
|
|
return x;
|
|
}
|
|
|
|
uint64_t GetRandom(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, 0));
|
|
return x;
|
|
}
|
|
|
|
uint32_t python(void) {
|
|
#define K 0 // 624 /* wut */
|
|
#define N 624
|
|
#define M 397
|
|
static int index;
|
|
static char once;
|
|
static uint32_t mt[N];
|
|
static const uint32_t mag01[2] = {0, 0x9908b0dfu};
|
|
uint32_t y;
|
|
int kk;
|
|
if (!once) {
|
|
char *sp;
|
|
ssize_t rc;
|
|
uint32_t i, j, k, s[K];
|
|
mt[0] = 19650218;
|
|
for (i = 1; i < N; i++) {
|
|
mt[i] = (1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
|
|
}
|
|
if (K) {
|
|
for (sp = (char *)s, i = 0; i < sizeof(s); i += rc) {
|
|
if ((rc = getrandom(sp + i, sizeof(s) - i, 0)) == -1) {
|
|
if (errno != EINTR) abort();
|
|
}
|
|
}
|
|
for (i = 1, j = 0, k = MAX(N, K); k; k--) {
|
|
mt[i] =
|
|
(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525u)) + s[j] + j;
|
|
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
|
if (++j >= K) j = 0;
|
|
}
|
|
for (k = N - 1; k; k--) {
|
|
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941u)) - i;
|
|
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
|
}
|
|
mt[0] = 0x80000000;
|
|
explicit_bzero(s, sizeof(s));
|
|
}
|
|
once = 1;
|
|
}
|
|
if (index >= N) {
|
|
for (kk = 0; kk < N - M; kk++) {
|
|
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
|
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 1];
|
|
}
|
|
for (; kk < N - 1; kk++) {
|
|
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
|
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 1];
|
|
}
|
|
y = (mt[N - 1] & 0x80000000u) | (mt[0] & 0x7fffffffu);
|
|
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 1];
|
|
index = 0;
|
|
}
|
|
y = mt[index++];
|
|
y ^= y >> 11;
|
|
y ^= (y << 7) & 0x9d2c5680u;
|
|
y ^= (y << 15) & 0xefc60000u;
|
|
y ^= y >> 18;
|
|
return y;
|
|
#undef M
|
|
#undef N
|
|
#undef K
|
|
}
|
|
|
|
uint64_t pythonx2(void) {
|
|
uint64_t x = python();
|
|
x <<= 32;
|
|
x |= python();
|
|
return x;
|
|
}
|
|
|
|
const struct Function {
|
|
const char *s;
|
|
uint64_t (*f)(void);
|
|
} kFunctions[] = {
|
|
{"ape", ape}, //
|
|
{"getrandom", GetRandom}, //
|
|
{"inc", inc}, //
|
|
{"knuth", knuth}, //
|
|
{"lemur64", lemur64}, //
|
|
{"libc", libc}, //
|
|
{"moby", moby}, //
|
|
{"mt19937", _mt19937}, //
|
|
{"python", pythonx2}, //
|
|
{"rand64", _rand64}, //
|
|
{"rdrand", rdrand}, //
|
|
{"rdrnd", rdrand}, //
|
|
{"rdseed", rdseed}, //
|
|
{"rngset64", rngset64}, //
|
|
{"unixv6", unixv6}, //
|
|
{"unixv7", unixv7}, //
|
|
{"vigna", vigna}, //
|
|
{"xorshift32", xorshift32}, //
|
|
{"xorshift64", xorshift64}, //
|
|
{"zero", zero}, //
|
|
};
|
|
|
|
void OnInt(int sig) {
|
|
isdone = true;
|
|
}
|
|
|
|
wontreturn void PrintUsage(FILE *f, int rc) {
|
|
fprintf(f, "Usage: %s [-b] [-n NUM] [FUNC]\n", program_invocation_name);
|
|
exit(rc);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
char *p;
|
|
int i, opt;
|
|
ssize_t rc;
|
|
uint64_t x;
|
|
static char buf[B];
|
|
uint64_t (*f)(void);
|
|
|
|
while ((opt = getopt(argc, argv, "hbc:n:")) != -1) {
|
|
switch (opt) {
|
|
case 'b':
|
|
isbinary = true;
|
|
break;
|
|
case 'c':
|
|
case 'n':
|
|
count = sizetol(optarg, 1024);
|
|
break;
|
|
case 'h':
|
|
PrintUsage(stdout, EXIT_SUCCESS);
|
|
default:
|
|
PrintUsage(stderr, EX_USAGE);
|
|
}
|
|
}
|
|
|
|
if (optind == argc) {
|
|
f = libc;
|
|
} else {
|
|
for (f = 0, i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
|
if (!strcasecmp(argv[optind], kFunctions[i].s)) {
|
|
f = kFunctions[i].f;
|
|
break;
|
|
}
|
|
}
|
|
if (!f) {
|
|
fprintf(stderr, "unknown function: %`'s\n", argv[optind]);
|
|
fprintf(stderr, "try: ");
|
|
for (i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
|
if (i) fprintf(stderr, ", ");
|
|
fprintf(stderr, "%s", kFunctions[i].s);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
signal(SIGINT, OnInt);
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
if (!isbinary) {
|
|
for (; count && !isdone && !feof(stdout); --count) {
|
|
printf("0x%016lx\n", f());
|
|
}
|
|
fflush(stdout);
|
|
return ferror(stdout) ? 1 : 0;
|
|
}
|
|
|
|
while (count && !isdone) {
|
|
if (count >= B) {
|
|
for (i = 0; i < B / 8; ++i) {
|
|
x = f();
|
|
p = buf + i * 8;
|
|
WRITE64LE(p, x);
|
|
}
|
|
for (i = 0; i < B; i += rc) {
|
|
rc = write(1, buf + i, B - i);
|
|
if (rc == -1 && errno == EPIPE) exit(1);
|
|
if (rc == -1) perror("write"), exit(1);
|
|
}
|
|
} else {
|
|
x = f();
|
|
rc = write(1, &x, MIN(8, count));
|
|
}
|
|
if (!rc) break;
|
|
if (rc == -1 && errno == EPIPE) exit(1);
|
|
if (rc == -1) perror("write"), exit(1);
|
|
count -= rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|