mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 08:12:28 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
314
tool/viz/generatematrix.c
Normal file
314
tool/viz/generatematrix.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*-*- 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/conv/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/rand/lcg.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/dtoa/dtoa.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
typedef double (*round_f)(double);
|
||||
typedef unsigned long (*rand_f)(void);
|
||||
|
||||
struct Range {
|
||||
double a;
|
||||
double b;
|
||||
};
|
||||
|
||||
short xn_ = 8;
|
||||
short yn_ = 8;
|
||||
double digs_ = 6;
|
||||
rand_f rand_;
|
||||
round_f rounder_;
|
||||
const char *path_ = "-";
|
||||
const char *name_ = "M";
|
||||
const char *type_ = "float";
|
||||
struct Range r1_ = {LONG_MIN, LONG_MAX};
|
||||
struct Range r2_ = {0, 1};
|
||||
StringTableFormatter *formatter_ = FormatStringTableAsCode;
|
||||
|
||||
static noreturn void PrintUsage(int rc, FILE *f) {
|
||||
fprintf(f, "Usage: %s%s", program_invocation_name, "\
|
||||
[FLAGS] [FILE]\n\
|
||||
\n\
|
||||
Flags:\n\
|
||||
-u unsigned\n\
|
||||
-c char\n\
|
||||
-s short\n\
|
||||
-i int\n\
|
||||
-l long\n\
|
||||
-d double\n\
|
||||
-b bytes [-uc]\n\
|
||||
-g non-deterministic rng\n\
|
||||
-S output assembly\n\
|
||||
-W output whitespace\n\
|
||||
-o PATH output path\n\
|
||||
-x FLEX\n\
|
||||
-w FLEX width\n\
|
||||
-y FLEX\n\
|
||||
-h FLEX height\n\
|
||||
-N NAME name\n\
|
||||
-T NAME type name\n\
|
||||
-A FLEX min value\n\
|
||||
-B FLEX max value\n\
|
||||
-R FUNC round function for indexing\n\
|
||||
-D FLEX decimal digits to printout\n\
|
||||
-v increases verbosity\n\
|
||||
-? shows this information\n\
|
||||
\n");
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static bool StringEquals(const char *a, const char *b) {
|
||||
return strcasecmp(a, b) == 0;
|
||||
}
|
||||
|
||||
static noreturn void ShowInvalidArg(const char *name, const char *s,
|
||||
const char *type) {
|
||||
fprintf(stderr, "error: invalid %s %s: %s\n", type, name, s);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static double ParseFlexidecimalOrDie(const char *name, const char *s,
|
||||
double min, double max) {
|
||||
double x;
|
||||
s = firstnonnull(s, "NULL");
|
||||
if (strchr(s, '.') || strchr(s, 'e')) {
|
||||
x = strtod(s, NULL);
|
||||
} else {
|
||||
x = strtol(s, NULL, 0);
|
||||
}
|
||||
if (min <= x && x <= max) {
|
||||
return x;
|
||||
} else {
|
||||
ShowInvalidArg(name, s, "flexidecimal");
|
||||
}
|
||||
}
|
||||
|
||||
static round_f ParseRoundingFunctionOrDie(const char *s) {
|
||||
if (isempty(s) || StringEquals(s, "none") || StringEquals(s, "null")) {
|
||||
return NULL;
|
||||
} else if (StringEquals(s, "round")) {
|
||||
return round;
|
||||
} else if (StringEquals(s, "rint")) {
|
||||
return rint;
|
||||
} else if (StringEquals(s, "nearbyint")) {
|
||||
return nearbyint;
|
||||
} else if (StringEquals(s, "trunc")) {
|
||||
return trunc;
|
||||
} else if (StringEquals(s, "floor")) {
|
||||
return floor;
|
||||
} else if (StringEquals(s, "ceil")) {
|
||||
return ceil;
|
||||
} else {
|
||||
ShowInvalidArg("round", s, "func");
|
||||
}
|
||||
}
|
||||
|
||||
static void ConfigureIntegralRange(const char *type, long min, long max) {
|
||||
type_ = type;
|
||||
r1_.a = min;
|
||||
r1_.b = max;
|
||||
r2_.a = min;
|
||||
r2_.b = max;
|
||||
if (!rounder_) rounder_ = round;
|
||||
}
|
||||
|
||||
void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
bool want_unsigned, want_char, want_short, want_int, want_long, want_double;
|
||||
want_unsigned = false;
|
||||
want_char = false;
|
||||
want_short = false;
|
||||
want_int = false;
|
||||
want_long = false;
|
||||
want_double = false;
|
||||
if (argc == 2 &&
|
||||
(StringEquals(argv[1], "--help") || StringEquals(argv[1], "-help"))) {
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
}
|
||||
while ((opt = getopt(argc, argv, "?vubcsildgSWo:x:w:y:h:N:A:B:C:E:T:R:D:")) !=
|
||||
-1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
want_unsigned = true;
|
||||
want_char = true;
|
||||
break;
|
||||
case 'u':
|
||||
want_unsigned = true;
|
||||
break;
|
||||
case 'c':
|
||||
want_char = true;
|
||||
break;
|
||||
case 's':
|
||||
want_short = true;
|
||||
break;
|
||||
case 'i':
|
||||
want_int = true;
|
||||
break;
|
||||
case 'l':
|
||||
want_long = true;
|
||||
break;
|
||||
case 'd':
|
||||
want_double = true;
|
||||
break;
|
||||
case 'g':
|
||||
rand_ = rand64;
|
||||
break;
|
||||
case 'N':
|
||||
name_ = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
path_ = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
formatter_ = FormatStringTableAsAssembly;
|
||||
break;
|
||||
case 'W':
|
||||
formatter_ = FormatStringTableBasic;
|
||||
break;
|
||||
case 't':
|
||||
type_ = optarg;
|
||||
break;
|
||||
case 'x':
|
||||
case 'w':
|
||||
xn_ = ParseFlexidecimalOrDie("width", optarg, 1, SHRT_MAX);
|
||||
break;
|
||||
case 'y':
|
||||
case 'h':
|
||||
yn_ = ParseFlexidecimalOrDie("height", optarg, 1, SHRT_MAX);
|
||||
break;
|
||||
case 'D':
|
||||
digs_ = ParseFlexidecimalOrDie("digs", optarg, 0, 15.95);
|
||||
break;
|
||||
case 'r':
|
||||
rounder_ = ParseRoundingFunctionOrDie(optarg);
|
||||
break;
|
||||
case 'A':
|
||||
r1_.a = ParseFlexidecimalOrDie("r1_.a", optarg, INT_MIN, INT_MAX);
|
||||
break;
|
||||
case 'B':
|
||||
r1_.b = ParseFlexidecimalOrDie("r1_.b", optarg, INT_MIN, INT_MAX);
|
||||
break;
|
||||
case 'C':
|
||||
r2_.a = ParseFlexidecimalOrDie("r2_.a", optarg, INT_MIN, INT_MAX);
|
||||
break;
|
||||
case 'E':
|
||||
r2_.b = ParseFlexidecimalOrDie("r2_.b", optarg, INT_MIN, INT_MAX);
|
||||
break;
|
||||
case '?':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
}
|
||||
}
|
||||
if (want_unsigned && want_char) {
|
||||
ConfigureIntegralRange("unsigned char", 0, 255);
|
||||
} else if (want_char) {
|
||||
ConfigureIntegralRange("signed char", -128, 127);
|
||||
} else if (want_unsigned && want_short) {
|
||||
ConfigureIntegralRange("unsigned short", USHRT_MIN, USHRT_MAX);
|
||||
} else if (want_short) {
|
||||
ConfigureIntegralRange("short", SHRT_MIN, SHRT_MAX);
|
||||
} else if (want_unsigned && want_int) {
|
||||
ConfigureIntegralRange("unsigned", UINT_MIN, UINT_MAX);
|
||||
} else if (want_int) {
|
||||
ConfigureIntegralRange("int", INT_MIN, INT_MAX);
|
||||
} else if (want_unsigned && want_long) {
|
||||
ConfigureIntegralRange("unsigned long", ULONG_MIN, ULONG_MAX);
|
||||
} else if (want_long) {
|
||||
ConfigureIntegralRange("long", LONG_MIN, LONG_MAX);
|
||||
} else if (want_double) {
|
||||
type_ = "double";
|
||||
r1_.a = LONG_MIN;
|
||||
r1_.b = LONG_MAX;
|
||||
digs_ = 19;
|
||||
}
|
||||
}
|
||||
|
||||
static void *SetRandom(long n, long p[n]) {
|
||||
long i;
|
||||
uint64_t r;
|
||||
if (rand_) {
|
||||
for (r = 1, i = 0; i < n; ++i) {
|
||||
p[i] = rand_();
|
||||
}
|
||||
} else {
|
||||
for (r = 1, i = 0; i < n; ++i) {
|
||||
p[i] = KnuthLinearCongruentialGenerator(&r) >> 32 |
|
||||
KnuthLinearCongruentialGenerator(&r) >> 32 << 32;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static double ConvertRange(double x, double a, double b, double c, double d) {
|
||||
return (d - c) / (b - a) * (x - a) + c;
|
||||
}
|
||||
|
||||
static double Compand(long x, double a, double b, double c, double d) {
|
||||
return ConvertRange(ConvertRange(x, LONG_MIN, LONG_MAX, a, b), a, b, c, d);
|
||||
}
|
||||
|
||||
static void GenerateMatrixImpl(long I[yn_][xn_], double M[yn_][xn_], FILE *f) {
|
||||
long y, x;
|
||||
for (y = 0; y < yn_; ++y) {
|
||||
for (x = 0; x < xn_; ++x) {
|
||||
M[y][x] = Compand(I[y][x], r1_.a, r1_.b, r2_.a, r2_.b);
|
||||
}
|
||||
if (rounder_) {
|
||||
for (x = 0; x < xn_; ++x) {
|
||||
M[y][x] = rounder_(M[y][x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
FormatMatrixDouble(yn_, xn_, M, fputs, f, formatter_, type_, name_, NULL,
|
||||
digs_, round);
|
||||
}
|
||||
|
||||
void GenerateMatrix(FILE *f) {
|
||||
GenerateMatrixImpl(SetRandom(yn_ * xn_, gc(calloc(yn_ * xn_, sizeof(long)))),
|
||||
gc(calloc(yn_ * xn_, sizeof(double))), f);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
FILE *f;
|
||||
showcrashreports();
|
||||
GetOpts(argc, argv);
|
||||
CHECK_NOTNULL((f = fopen(path_, "w")));
|
||||
if (optind < argc) FATALF("TODO(jart): support input files");
|
||||
GenerateMatrix(f);
|
||||
return fclose(f);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue