├── README.md
├── UNLICENSE
├── aes128ni
├── Makefile
├── README.md
├── aes128ni.h
└── tests
│ ├── dump.c
│ └── tests.c
├── aidrivers
├── Makefile
├── README.md
├── aidrivers.c
├── loop.png
├── loopoverlay.png
└── map.png
├── animation
├── 4d6drop1.c
├── boxes.c
├── cavewalk.c
├── chaosgame.c
├── colorsort.c
├── epidemic.c
├── fire.c
├── fizzlefade.c
├── galton.c
├── halvorsen.c
├── lorenz.c
├── magnet.c
├── mold.c
├── monster.c
├── mtvisualize.c
├── nearest.c
├── normhash.c
├── pixelsort.c
├── plants.c
├── primegaps.c
├── randu.c
├── rooks.c
├── sandpiles.c
├── starfield.c
├── starwars.c
├── voronoi.c
├── walk3d.c
└── walkers.c
├── animaze
├── Makefile
└── animaze.c
├── attractors
├── .gitignore
├── Makefile
├── README.md
└── attractors.c
├── birdgen
├── .gitattributes
├── README.md
├── actual.list
├── birdgen.c
├── birdgen.go
├── colors.list
├── index.html
├── prefixes.list
├── qualifiers.list
├── species.list
└── suffixes.list
├── bloom-filter
├── Makefile
├── README.md
├── bloom.c
├── bloom.h
└── main.c
├── brianvm
├── README.md
├── brianvm.c
└── brianvm.lua
├── checksums
├── adler32.h
├── arxseq64.c
├── ascon.c
├── chunky64.c
├── crc16x25.h
├── crc32.h
├── crc32c.h
├── fletcher64.c
├── gimli.c
├── hash22.c
├── hash22.go
├── md2.c
├── murmurhash3.h
├── sha1.c
├── sha256.c
└── test.c
├── cols
├── Makefile
├── README.md
├── cols.1
└── cols.c
├── cp1252
├── Makefile
├── README.md
├── cp1252.c
└── tests.c
├── csvquote
├── .gitignore
├── Makefile
├── README.md
├── csvquote.1
├── csvquote.c
└── etc
│ └── csvdump.c
├── elsiefour
├── Makefile
├── README.md
├── lc4.c
└── lc4.h
├── glove
├── GNUmakefile
├── README.md
├── glove-convert_posix.c
├── glove-convert_win32.c
├── glove-lookup.c
├── glove-lookup_posix.c
├── glove-lookup_win32.c
├── glove.c
├── glove.def
└── glove.h
├── hexmap
├── Makefile
├── bmp.h
├── getopt.h
└── hexmap.c
├── int32trie
├── Makefile
├── README.md
├── int32trie.c
├── int32trie.h
└── test.c
├── iseven
├── README.md
├── iseven.c
├── iseven.dot
└── iseven.png
├── libwinsane
├── Makefile
├── README.md
├── init.c
├── manifest.rc
└── utf8.xml
├── marvin32
├── README.md
└── marvin32.c
├── misc
├── 1brc.c
├── 2pow.c
├── 3sum.cpp
├── abacaba.c
├── abacaba.go
├── adaclean.c
├── adafrien.c
├── adafrien2.c
├── aliquot.cpp
├── altsixteen.c
├── anagram.cpp
├── aoc23-15.c
├── arena-hashtrie.go
├── asmint.c
├── atroll.c
├── b32v16.c
├── barcode.c
├── barrier.py
├── bf.c
├── biome.c
├── brodnik.cpp
├── bswap.c
├── buddy.c
├── cake.c
├── casefold.c
├── chacha-test.lua
├── chacha.lua
├── chacha.py
├── channel.py
├── charsets.c
├── cistercian.c
├── codename.c
├── collatz.cpp
├── concurrent-hash-trie.c
├── condvar.cpp
├── constrainsort.c
├── coro.c
├── cses-distinct.c
├── cses-tickets.c
├── cut.c
├── d6gen.h
├── dandelions.c
├── dice.c
├── dumpbin-exports.c
├── dumpdata.s
├── eid.c
├── envsort.c
├── findmem.c
├── findpath.cpp
├── fivefive.c
├── float16.c
├── freedict.c
├── gale-shapley.c
├── glitch.c
├── graphgen.c
├── hashmap.c
├── hashtrie_test.go
├── hist.c
├── html.c
├── idnabake.c
├── importless.c
├── int32len.c
├── interpenv.c
├── ipv4_crypt.c
├── ipv6fmt.c
├── jsonb.c
├── kcs.c
├── kruskal.lua
├── latin2.c
├── lightsout.c
├── list-github.sh
├── lookandsay.c
├── lottery.c
├── luhn.c
├── mac.c
├── mandelbrot.f90
├── markov.c
├── matchn.c
├── maximals.c
├── mcpi.c
├── mergesort.c
├── minipng.c
├── msi-hashtrie-bench.c
├── msws.c
├── mutex.c
├── mutex2.c
├── numprefix.c
├── objrender.c
├── once.c
├── openbsd.py
├── peb-explore.c
├── pi.c
├── pi.go
├── pink.c
├── pixelfont.c
├── practical.c
├── printenv.c
├── prng32.c
├── ptr.cpp
├── queue.c
├── queue.go
├── quniq.c
├── rabin-karp.c
├── rainbow.c
├── rc4.c
├── read-password-w32.c
├── recip.c
├── rfc1035encode.c
├── riskattack.c
├── rtttl.c
├── rule30.c
├── scsp.c
├── sleep.s
├── slice.c
├── sliding.cpp
├── snake.c
├── sort.c
├── sorting_networks.c
├── sortu64.c
├── sponge.c
├── stack_head.c
├── streamtok.c
├── sudoku.c
├── summarize.c
├── thuemorse.c
├── tiles.c
├── towns.c
├── treap.c
├── triangle.c
├── true.s
├── twotone.c
├── utf8_branchless.c
├── uuidperm.c
├── uwords.c
├── uwords.go
├── vfork.c
├── waitgroup.c
├── wc.go
├── whitespace.c
├── wilson.c
├── wordhist.c
├── wordle.c
├── xgetdelim.c
├── xgetdelim.h
├── xstrtok.h
└── xxtea.c
├── mmlfg
├── Mmlfg.java
├── README.md
├── mmlfg.c
├── mmlfg.el
├── mmlfg.go
├── mmlfg.js
├── mmlfg.lua
└── mmlfg.py
├── monocrypt
├── Makefile
├── README.md
├── monocrypt.c
├── monocypher.c
├── monocypher.h
├── platform.c
└── platform.h
├── mt19937
├── README.md
├── mt19937.h
├── mt19937_64.h
└── test.c
├── parsers
├── README.md
├── bpspatch.c
├── canfigger.c
├── chars.c
├── chars.dot
├── cmdline.c
├── comments.c
├── csv.c
├── execstack.c
├── fslint.c
├── glb.c
├── ihex.c
├── imgo.c
├── ini-hashtrie.c
├── ini.c
├── ipspatch.c
├── json-sqrt.c
├── leb128.c
├── morsecode.c
├── pbm2bmp.c
├── pgm_parser.c
├── punycode.c
├── qoi.c
├── strtonum.c
├── urldecode.c
├── utf8.c
├── utf8_decode.c
└── ytid.c
├── pbmview
├── .gitignore
├── GNUmakefile
├── Makefile
├── README.md
├── pbmview.c
└── pbmview.ico
├── place-2022
├── Makefile
├── README.md
├── convert.c
└── render.c
├── pngattach
├── .gitignore
├── Makefile
├── README.md
├── pngattach.1
└── pngattach.c
├── primesieve
├── Makefile
├── main.c
└── primesieve.c
├── prips
├── Makefile
├── README.md
├── prips.1
└── prips.c
├── regex-wrap
├── GNUmakefile
├── Makefile
├── README.md
├── main.c
├── regex.cpp
├── regex.def
└── regex.h
├── set32
├── Makefile
├── README.md
├── set32.h
└── test.c
├── sfcw
├── GNUmakefile
├── Makefile
├── README.md
├── resource.rc
├── sfcw.c
├── sfcw.exe.manifest
└── sfcw.ico
├── siphash
├── Makefile
├── README.md
├── siphash-embed.h
├── siphash.c
├── siphash.h
└── test.c
├── skipjack
├── Makefile
├── README.md
├── skipjack.h
└── tests
│ ├── dump.c
│ └── test.c
├── sp4
├── README.md
├── sp4.c
├── sponge4.bas
└── sponge4.lua
├── spaceship
├── README.md
├── examples.png
└── spaceship.c
├── speck
├── Makefile
├── README.md
├── speck.h
├── speckcrypt.c
└── tests.c
├── splitxix33
├── README.md
├── Splitxix33.java
├── splitxix33.c
├── splitxix33.cc
├── splitxix33.el
├── splitxix33.go
├── splitxix33.js
├── splitxix33.lua
└── splitxix33.py
├── userscript
└── reddit-llm-translate.user.js
├── uuid
├── Makefile
├── README.md
├── etc
│ └── main.c
├── uuid.js
├── uuid.lua
├── uuidgen.c
└── uuidgen.h
├── w32bundle
├── .gitignore
├── GNUmakefile
├── README.md
├── builder.cpp
├── common.cpp
├── loader.cpp
├── message.c
└── test.c
├── water-sort
├── GNUmakefile
├── README.md
├── genseeds.c
├── index.html.in
├── main.py
├── main_sdl2.c
├── main_wasm.c
├── main_windows.c
├── seeds.txt
└── water-sort.c
├── wgl-demo
├── Makefile
└── main.c
└── windows
├── README.md
├── cal.c
├── ccpad.c
├── cloc.c
├── deflate.c
├── du.c
├── emerald.c
├── getfiletype.c
├── getip.c
├── imageview.c
├── opengl.go
├── setlaa.c
├── shuttercount.c
├── smacxfix.c
├── sponge.c
├── watc.c
└── wc.c
/README.md:
--------------------------------------------------------------------------------
1 | # Personal scratch code
2 |
3 | This repository is a pile of scratch mini-projects I've written over the
4 | years that capture various experiments and lessons learned. When working
5 | on other projects, I will sometimes harvest code snippets from this
6 | scratch repository. Some of this code is complete, working, and tested,
7 | but not sufficiently substantial to warrant its own repository. Some is
8 | incomplete or half-baked. Almost all the code here is dedicated to the
9 | public domain.
10 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/aes128ni/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -std=c99 -Wall -Wextra -O3 -maes -march=native
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | all: tests/tests tests/dump
8 |
9 | tests/tests: tests/tests.c aes128ni.h
10 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests/tests.c $(LDLIBS)
11 |
12 | tests/dump: tests/dump.c aes128ni.h
13 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests/dump.c $(LDLIBS)
14 |
15 | check: tests/tests
16 | tests/tests
17 |
18 | clean:
19 | rm -f tests/dump tests/tests
20 |
--------------------------------------------------------------------------------
/aes128ni/README.md:
--------------------------------------------------------------------------------
1 | # AES-128 implemented with AES-NI intrinsics in C
2 |
3 | This is a C header library.
4 |
5 | ```c
6 | void aes128_init(struct aes128 *ctx, const void *key);
7 | void aes128_encrypt(struct aes128 *ctx, void *pt, const void *ct);
8 | void aes128_decrypt(struct aes128 *ctx, void *ct, const void *pt);
9 | ```
10 |
11 | Compile with `-maes` or equivalent.
12 |
--------------------------------------------------------------------------------
/aes128ni/tests/dump.c:
--------------------------------------------------------------------------------
1 | /* AES-NI benchmark
2 | *
3 | * This program dumps AES-NI output as fast as possible to measure its
4 | * speed. The output buffer has been tuned to maximize performance.
5 | */
6 | #define _POSIX_C_SOURCE 200112L
7 | #include "../aes128ni.h"
8 | #include
9 | #include
10 | #include
11 |
12 | int
13 | main(void)
14 | {
15 | struct aes128 ctx[1];
16 | unsigned char buf[1 << 14];
17 | uint64_t counter[2] = {0, 0};
18 | const unsigned char key[AES128_KEYLEN] = {0};
19 |
20 | aes128_init(ctx, key);
21 | for (;;) {
22 | for (size_t i = 0; i < sizeof(buf); i += 16) {
23 | aes128_encrypt(ctx, buf + i, counter);
24 | if (!++counter[0]) counter[1]++;
25 | }
26 | if (write(1, buf, sizeof(buf)) != sizeof(buf))
27 | break;
28 | }
29 | (void)aes128_decrypt; /* unused */
30 | }
31 |
--------------------------------------------------------------------------------
/aes128ni/tests/tests.c:
--------------------------------------------------------------------------------
1 | /* Unit tests for AES-NI implementation.
2 | */
3 | #include "../aes128ni.h"
4 | #include
5 | #include
6 |
7 | #define C_R(s) "\033[91;1m" s "\033[0m"
8 | #define C_G(s) "\033[92;1m" s "\033[0m"
9 |
10 | int
11 | main(void)
12 | {
13 | struct aes128 ctx[1];
14 | const unsigned char key[] = {
15 | 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
16 | 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
17 | };
18 | const unsigned char pt[] = {
19 | 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
20 | 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
21 | };
22 | const unsigned char et[] = {
23 | 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
24 | 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97
25 | };
26 | unsigned char ct[AES128_BLOCKLEN] = {0};
27 | unsigned char xt[AES128_BLOCKLEN] = {0};
28 |
29 | aes128_init(ctx, key);
30 | aes128_encrypt(ctx, ct, pt);
31 | if (memcmp(ct, et, sizeof(ct)))
32 | puts(C_R("FAIL") ": encryption");
33 | else
34 | puts(C_G("PASS") ": encryption");
35 |
36 | aes128_decrypt(ctx, xt, ct);
37 | if (memcmp(xt, pt, sizeof(ct)))
38 | puts(C_R("FAIL") ": decryption");
39 | else
40 | puts(C_G("PASS") ": decryption");
41 | }
42 |
--------------------------------------------------------------------------------
/aidrivers/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -Ofast -fopenmp -g -Wall -Wextra
4 | LDFLAGS =
5 | LDLIBS = -lm
6 |
7 | aidrivers: aidrivers.c
8 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ aidrivers.c $(LDLIBS)
9 |
10 | clean:
11 | rm -f aidrivers
12 |
--------------------------------------------------------------------------------
/aidrivers/README.md:
--------------------------------------------------------------------------------
1 | # AI driving simulation
2 |
3 | Full article: [You might not need machine learning][a]
4 |
5 | [a]: https://nullprogram.com/blog/2020/11/24/
6 |
--------------------------------------------------------------------------------
/aidrivers/loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/aidrivers/loop.png
--------------------------------------------------------------------------------
/aidrivers/loopoverlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/aidrivers/loopoverlay.png
--------------------------------------------------------------------------------
/aidrivers/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/aidrivers/map.png
--------------------------------------------------------------------------------
/animation/4d6drop1.c:
--------------------------------------------------------------------------------
1 | /* Visualization of 4d6-drop-1 distribution
2 | * $ cc -Ofast -o 4d6drop1 4d6drop1.c
3 | * $ ./4d6drop1 | mpv --no-correct-pts --fps=60 -
4 | * $ ./4d6drop1 | x264 --fps=60 --frames=3600 -o 4d6drop1.mp4 /dev/stdin
5 | * Ref: https://redd.it/kgvpj2
6 | * This is free and unencumbered software released into the public domain.
7 | */
8 | #include
9 | #include
10 |
11 | #define W 1920
12 | #define H 1080
13 | #define C 0x5eff7e
14 |
15 | static unsigned long
16 | d6(void)
17 | {
18 | static unsigned long long s = 1;
19 | for (;;) {
20 | s = s*0x2ab97a6e1147dde5ULL + 1;
21 | unsigned long r = s>>32 & 0xffffffff;
22 | r ^= r >> 16;
23 | r *= 0xec03deb7;
24 | r &= 0xffffffff;
25 | r ^= r >> 16;
26 | if (r < 0xfffffffc) return 1 + r%6;
27 | }
28 | }
29 |
30 | int
31 | main(void)
32 | {
33 | #ifdef _WIN32
34 | /* Set stdout to binary mode. */
35 | int _setmode(int, int);
36 | _setmode(1, 0x8000);
37 | #endif
38 |
39 | long long high = 0;
40 | long long hist[1+3*6] = {0};
41 |
42 | for (long long n = 0; ; n++) {
43 | int rolls[4] = {d6(), 0, 0, 0};
44 | for (int j = 1; j < 4; j++) {
45 | int r = d6();
46 | if (rolls[0] > r) {
47 | rolls[j] = rolls[0];
48 | rolls[0] = r;
49 | } else {
50 | rolls[j] = r;
51 | }
52 | }
53 | int i = rolls[1]+rolls[2]+rolls[3];
54 | long long v = ++hist[i];
55 | high = v > high ? v : high;
56 |
57 | /* Render */
58 | if (n & 0x3) continue; // skip frames
59 | static unsigned char im[H][W][3];
60 | memset(im, 0, sizeof(im));
61 | for (int i = 3*1; i <= 3*6; i++) {
62 | int h = 0.98 * H * hist[i] / high;
63 | int w = W/16;
64 | int pad = W/256;
65 | for (int y = 0; y < h; y++) {
66 | for (int x = pad; x < w - pad; x++) {
67 | im[H-y-1][x+(i-3)*w][0] = (unsigned char)(C >> 16);
68 | im[H-y-1][x+(i-3)*w][1] = (unsigned char)(C >> 8);
69 | im[H-y-1][x+(i-3)*w][2] = (unsigned char)(C >> 0);
70 | }
71 | }
72 | }
73 | printf("P6\n%d %d\n255\n", W, H);
74 | if (!fwrite(im, sizeof(im), 1, stdout)) return 1;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/animation/chaosgame.c:
--------------------------------------------------------------------------------
1 | // Chaos Game animation
2 | // $ cc -Ofast -o chaosgame chaosgame.c
3 | // $ ./chaosgame | mpv --no-correct-pts --fps=60 --fs -
4 | // $ ./chaosgame | x264 --frames=900 --fps=60 -o chaosgame.mp4 /dev/stdin
5 | // Ref: https://en.wikipedia.org/wiki/Chaos_game
6 | // This is free and unencumbered software released into the public domain.
7 | #include
8 | #include
9 | #include
10 |
11 | #define S 1080
12 | #define SKIP (1U<<8)
13 |
14 | struct state {
15 | uint64_t s, i;
16 | double x, y;
17 | };
18 |
19 | static struct state
20 | next(struct state s)
21 | {
22 | // 8 edge points of the square
23 | static const float t[] = {
24 | 0.0, 0.0, 0.5, 0.0, 1.0, 0.0, 0.0, 0.5,
25 | 1.0, 0.5, 0.0, 1.0, 0.5, 1.0, 1.0, 1.0,
26 | };
27 | int r = (s.s = s.s*0x3243f6a8885a308dU + 1) >> 61;
28 | s.x += 2.0/3.0 * (t[r*2 + 0] - s.x);
29 | s.y += 2.0/3.0 * (t[r*2 + 1] - s.y);
30 | s.i++;
31 | return s;
32 | }
33 |
34 | static struct state
35 | init(uint64_t seed)
36 | {
37 | seed *= 1111111111111111111U; seed ^= seed >> 33;
38 | seed *= 1111111111111111111U; seed ^= seed >> 33;
39 | struct state s = {
40 | seed, 0,
41 | s.x = (seed & 0xffffffff)/4294967296.0,
42 | s.y = (seed >> 32)/4294967296.0,
43 | };
44 | s = next(s); s = next(s); s = next(s); s = next(s);
45 | s = next(s); s = next(s); s = next(s); s = next(s);
46 | return s;
47 | }
48 |
49 | int
50 | main(void)
51 | {
52 | #ifdef _WIN32
53 | int _setmode(int, int);
54 | _setmode(1, 0x8000); // stdout to binary mode
55 | #endif
56 |
57 | for (struct state s = init(time(0)); ; s = next(s)) {
58 | static unsigned char buf[S][S][3];
59 | buf[(int)(s.y*S)][(int)(s.x*S)][(s.s>>32)%3] = 255;
60 | if (!(s.i % SKIP)) {
61 | #define XSTR(s) STR(s)
62 | #define STR(s) #s
63 | static const char hdr[] = "P6\n" XSTR(S) " " XSTR(S) "\n255\n";
64 | if (!fwrite(hdr, sizeof(hdr)-1, 1, stdout) ||
65 | !fwrite(buf, sizeof(buf), 1, stdout)) {
66 | return 1;
67 | }
68 | s.s += clock();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/animation/fizzlefade.c:
--------------------------------------------------------------------------------
1 | // LCG fizzlefade with randomly-selected parameters
2 | // Shows many obvious patterns resulting from poorly-chosen parameters.
3 | // $ cc -O3 -o fizzlefade fizzlefade.c
4 | // $ ./fizzlefade | mpv --no-correct-pts --fps=60 --fs -
5 | // This is free and unencumbered software released into the public domain.
6 | #include
7 | #include
8 |
9 | int main(void)
10 | {
11 | #if _WIN32
12 | int _setmode(int, int);
13 | _setmode(1, 0x8000);
14 | #endif
15 |
16 | for (unsigned long long rng = time(0);;) {
17 | // Randomly generate LCG parameters
18 | long m, a, c, s;
19 | do {
20 | rng = rng*0x3243f6a8885a308dU + 1;
21 | s = (rng >> 0) & 0xff;
22 | c = (rng >> 8) & 0xffffff;
23 | m = (rng >> 32) % (1920L * 1080);
24 | a = (rng >> 53);
25 | while (!(a%2 && a%3 && a%5)) a++;
26 | } while ((m-1)%2 || (m-1)%3 || (m-1)%4 || (m-1)%5);
27 |
28 | // Use LCG to permute all pixels
29 | static unsigned char image[1920L*1080][3];
30 | for (long i = 0; i < 1920L*1080; i++) {
31 | s = ((long long)s*m + a) % (1920L * 1080);
32 | image[s][0] = c >> 0;
33 | image[s][1] = c >> 8;
34 | image[s][2] = c >> 16;
35 | if (!(i%8100)) {
36 | puts("P6\n1920 1080\n255");
37 | if (!fwrite(image, sizeof(image), 1, stdout)) {
38 | return 1;
39 | }
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/animation/starwars.c:
--------------------------------------------------------------------------------
1 | /* Star Wars cellular automaton (rule 245/2/4)
2 | * $ cc -O3 -fopenmp -o starwars starwars.c
3 | * $ ./starwars | mpv --no-correct-pts --fps=15 --fs -
4 | * $ ./starwars | x264 --frames=900 --fps=15 -o starwars.mp4 /dev/stdin
5 | * Ref: https://www.conwaylife.com/wiki/OCA:Star_Wars
6 | */
7 | #include
8 | #include
9 |
10 | #define W (1920/S)
11 | #define H (1080/S)
12 | #define S 2
13 | static const long colors[] = {0x111111, 0xffffff, 0xff00ff, 0x0000ff};
14 | #define STATES "02300230123001300130013002300230"
15 |
16 | int
17 | main(void)
18 | {
19 | #ifdef _WIN32
20 | /* Set stdout to binary mode. */
21 | int _setmode(int, int);
22 | _setmode(1, 0x8000);
23 | #endif
24 |
25 | static char state[2][H][W];
26 |
27 | unsigned long long s = time(0);
28 | for (int y = 0; y < H; y++) {
29 | for (int x = 0; x < W; x++) {
30 | s = s*0x243f6a8885a308d3 + 1;
31 | state[0][y][x] = (s >> 63) & 1;
32 | }
33 | }
34 |
35 | for (int i = 0; ; i = !i) {
36 | #pragma omp parallel for
37 | for (int y = 0; y < H; y++) {
38 | for (int x = 0; x < W; x++) {
39 | int c0 = state[i][y][x];
40 | int c1 = (state[i][(y+H+0)%H][(x+W+1)%W] == 1) +
41 | (state[i][(y+H+0)%H][(x+W-1)%W] == 1) +
42 | (state[i][(y+H+1)%H][(x+W+1)%W] == 1) +
43 | (state[i][(y+H+1)%H][(x+W+0)%W] == 1) +
44 | (state[i][(y+H+1)%H][(x+W-1)%W] == 1) +
45 | (state[i][(y+H-1)%H][(x+W+1)%W] == 1) +
46 | (state[i][(y+H-1)%H][(x+W+0)%W] == 1) +
47 | (state[i][(y+H-1)%H][(x+W-1)%W] == 1);
48 | state[!i][y][x] = STATES[(c1<<2 | c0)&0x1f] - '0';
49 | }
50 | }
51 |
52 | static unsigned char ppm[H*S][W*S][3];
53 | for (int y = 0; y < H*S; y++) {
54 | for (int x = 0; x < W*S; x++) {
55 | long c = colors[(int)state[!i][y/S][x/S]];
56 | ppm[y][x][0] = c >> 16;
57 | ppm[y][x][1] = c >> 8;
58 | ppm[y][x][2] = c >> 0;
59 | }
60 | }
61 | printf("P6\n%d %d\n255\n", W*S, H*S);
62 | if (!fwrite(ppm, sizeof(ppm), 1, stdout)) return 1;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/animaze/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -std=c11 -Wall -Wextra -O3 -march=native -DENABLE_GL
4 | LDFLAGS =
5 | LDLIBS = -lglfw -lGLEW -lGL
6 |
7 | animaze: animaze.c
8 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ animaze.c $(LDLIBS)
9 |
10 | view: animaze
11 | ./animaze | mpv --no-correct-pts --fps=60 --fs -
12 |
13 | challenge.png: animaze
14 | ./animaze -q -n100000 -w100 -h50 -s18 | gm convert ppm:- $@
15 |
16 | maze.mp4: animaze
17 | ./animaze -n1 | x264 --fps 60 -o $@ /dev/stdin
18 |
19 | clean:
20 | rm -f animaze
21 |
--------------------------------------------------------------------------------
/attractors/.gitignore:
--------------------------------------------------------------------------------
1 | lorenz
2 | sprott
3 | aizawa
4 | halvorsen
5 | dadras
6 | thomas
7 | *.exe
8 | *.mp4
9 | *.mkv
10 | *.y4m
11 |
--------------------------------------------------------------------------------
/attractors/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -Wall -Wextra -Wdouble-promotion -Ofast
4 | LDFLAGS = -s
5 | LDLIBS = -lm
6 |
7 | bins = lorenz$(EXE) sprott$(EXE) aizawa$(EXE) halvorsen$(EXE) dadras$(EXE) \
8 | thomas$(EXE)
9 |
10 | all: $(bins)
11 |
12 | lorenz$(EXE): attractors.c
13 | $(CC) -DLORENZ $(CFLAGS) -o $@ attractors.c $(LDLIBS)
14 |
15 | sprott$(EXE): attractors.c
16 | $(CC) -DSPROTT $(CFLAGS) -o $@ attractors.c $(LDLIBS)
17 |
18 | aizawa$(EXE): attractors.c
19 | $(CC) -DAIZAWA $(CFLAGS) -o $@ attractors.c $(LDLIBS)
20 |
21 | halvorsen$(EXE): attractors.c
22 | $(CC) -DHALVORSEN $(CFLAGS) -o $@ attractors.c $(LDLIBS)
23 |
24 | dadras$(EXE): attractors.c
25 | $(CC) -DDADRAS $(CFLAGS) -o $@ attractors.c $(LDLIBS)
26 |
27 | thomas$(EXE): attractors.c
28 | $(CC) -DTHOMAS $(CFLAGS) -o $@ attractors.c $(LDLIBS)
29 |
30 | clean:
31 | rm -f $(bins)
32 |
--------------------------------------------------------------------------------
/attractors/README.md:
--------------------------------------------------------------------------------
1 | # Strange attractor animator
2 |
3 | This program writes raw video to standard output animating of [various
4 | strange attractors][st] (ODE systems). Pipe it into your favorite video
5 | player or encoder that accepts video data from standard input.
6 |
7 | $ make
8 | $ ./lorenz | mpv --no-correct-pts --fps=60 --fs -
9 | $ ./lorenz | ppmtoy4m -F60:1 | vlc -
10 | $ ./lorenz | x264 --fps 60 --frames 3600 -o lorenz.mp4 /dev/stdin
11 |
12 | Requires a C compiler supporting C99 or later.
13 |
14 |
15 | [st]: https://www.dynamicmath.xyz/strange-attractors/
16 |
--------------------------------------------------------------------------------
/birdgen/.gitattributes:
--------------------------------------------------------------------------------
1 | *.list -crlf
2 |
--------------------------------------------------------------------------------
/birdgen/README.md:
--------------------------------------------------------------------------------
1 | # Bird Species Generator Turing Test
2 |
3 | This program randomly selects a real North American bird species name,
4 | then randomly generates three species that (hopefully) sound real, but
5 | definitely are not real. It shuffles this list and then prints it. Your
6 | job is to guess which is the real species. Hit RET to reveal which item
7 | was the real species.
8 |
9 | ## Build
10 |
11 | The game comes in three flavors: Go, Windows, and WASM.
12 |
13 | $ go build birdgen.go
14 | $ cc -std=gnu23 -nostartfiles -o birdgen.exe birdgen.c
15 | $ clang -std=gnu23 --target=wasm32 -Os -s
16 | -nostdlib -Wl,--no-entry -o birdgen.wasm birdgen.c
17 |
18 | Use `index.html` to run the WASM version. In all cases name lists are
19 | embedded in the binary and unneeded at run time. The C builds accomplish
20 | this with C23's `#embed`.
21 |
--------------------------------------------------------------------------------
/birdgen/colors.list:
--------------------------------------------------------------------------------
1 | azure
2 | black
3 | blue
4 | chestnut
5 | crimson
6 | gold
7 | golden
8 | gray
9 | green
10 | grey
11 | olive
12 | orange
13 | red
14 | rose
15 | ruby
16 | rufous
17 | silver
18 | tawny
19 | topaz
20 | violet
21 | white
22 | yellow
23 |
--------------------------------------------------------------------------------
/birdgen/prefixes.list:
--------------------------------------------------------------------------------
1 | amethyst
2 | ash
3 | ashy
4 | azure
5 | band
6 | bar
7 | bare
8 | bay
9 | black
10 | blue
11 | boat
12 | bran
13 | bright
14 | bristle
15 | broad
16 | bronze
17 | brown
18 | buff
19 | buffy
20 | bushy
21 | channel
22 | checker
23 | chestnut
24 | cinnamon
25 | clay
26 | coppery
27 | crescent
28 | crimson
29 | curve
30 | dark
31 | dot
32 | double
33 | dull
34 | dusky
35 | emerald
36 | eye
37 | fan
38 | fiery
39 | five
40 | flame
41 | flat
42 | flesh
43 | fork
44 | four
45 | fulvous
46 | garnet
47 | glaucous
48 | glow
49 | golden
50 | gray
51 | great
52 | green
53 | grey
54 | groove
55 | gull
56 | hook
57 | ivory
58 | keel
59 | ladder
60 | lance
61 | large
62 | lattice
63 | lemon
64 | light
65 | lilac
66 | long
67 | magenta
68 | maroon
69 | mouse
70 | narrow
71 | ochre
72 | olive
73 | one
74 | orange
75 | paint
76 | pale
77 | pearl
78 | pearly
79 | peg
80 | pied
81 | pin
82 | pink
83 | plain
84 | prong
85 | purple
86 | purplish
87 | red
88 | ring
89 | rose
90 | rosy
91 | rough
92 | ruby
93 | ruddy
94 | rufous
95 | russet
96 | rusty
97 | saffron
98 | sapphire
99 | scale
100 | scaly
101 | scarlet
102 | scissor
103 | sepia
104 | sharp
105 | short
106 | silver
107 | silvery
108 | slate
109 | slaty
110 | slender
111 | smooth
112 | snowy
113 | sooty
114 | spangle
115 | sparkling
116 | spiny
117 | spoon
118 | spot
119 | straight
120 | streak
121 | stripe
122 | strong
123 | stub
124 | sulphur
125 | swallow
126 | tawny
127 | thick
128 | three
129 | tooth
130 | turquoise
131 | two
132 | violet
133 | wedge
134 | white
135 | wine
136 | wing
137 | worm
138 | yellow
139 | zone
140 |
--------------------------------------------------------------------------------
/birdgen/qualifiers.list:
--------------------------------------------------------------------------------
1 | african
2 | alpine
3 | american
4 | antillean
5 | arctic
6 | atlantic
7 | banded
8 | barred
9 | bearded
10 | bicolored
11 | boreal
12 | burrowing
13 | california
14 | canada
15 | carolina
16 | chinese
17 | cinerous
18 | common
19 | eastern
20 | elegant
21 | great
22 | greater
23 | horned
24 | indian
25 | island
26 | kentucky
27 | least
28 | lesser
29 | little
30 | loggerhead
31 | mangrove
32 | marbled
33 | marsh
34 | masked
35 | melodious
36 | mississippi
37 | mottled
38 | mountain
39 | mourning
40 | moustached
41 | mute
42 | northern
43 | ocellated
44 | ochraceous
45 | olivaceous
46 | orchard
47 | oriental
48 | ornate
49 | pacific
50 | painted
51 | pileated
52 | pine
53 | plumbeous
54 | prairie
55 | roadside
56 | royal
57 | savanna
58 | snowy
59 | southern
60 | spectacled
61 | spotted
62 | striped
63 | tiny
64 | tricolored
65 | tropical
66 | tufted
67 | unicolored
68 | unspotted
69 | virginia
70 | western
71 | whiskered
72 | whistling
73 | whooping
74 |
--------------------------------------------------------------------------------
/birdgen/species.list:
--------------------------------------------------------------------------------
1 | anhinga
2 | ani
3 | antbird
4 | antwren
5 | avocet
6 | bananaquit
7 | bentbill
8 | bishop
9 | bittern
10 | blackbird
11 | bluebird
12 | bluethroat
13 | bobolink
14 | bobwhite
15 | boobook
16 | brambling
17 | brant
18 | bufflehead
19 | bullfinch
20 | bushtit
21 | canvasback
22 | cardinal
23 | chat-tanager
24 | chickadee
25 | chukar
26 | coot
27 | crow
28 | dickcissel
29 | dipper
30 | dovekie
31 | duck
32 | dunlin
33 | elaenia
34 | emerald
35 | fieldfare
36 | flamingo
37 | flicker
38 | flycatcher
39 | frigatebird
40 | fulmar
41 | gadwall
42 | gannet
43 | garganey
44 | gnatcatcher
45 | goldfinch
46 | goose
47 | goshawk
48 | grackle
49 | grassquit
50 | grebe
51 | greenlet
52 | ground-cuckoo
53 | grouse
54 | gull
55 | gyrfalcon
56 | harrier
57 | hawfinch
58 | hawk
59 | hawk owl
60 | heron
61 | jabiru
62 | kestrel
63 | killdeer
64 | kingbird
65 | kiskadee
66 | lapwing
67 | lark
68 | limpkin
69 | loon
70 | macaw
71 | mallard
72 | martin
73 | meadowlark
74 | merlin
75 | mockingbird
76 | nighthawk
77 | nightingale-thrush
78 | nightingale-wren
79 | nightjar
80 | oilbird
81 | orangequit
82 | oriole
83 | osprey
84 | ovenbird
85 | owl
86 | oystercatcher
87 | palmchat
88 | parakeet
89 | parrot
90 | pelican
91 | petrel
92 | pewee
93 | phainopepla
94 | phoebe
95 | pintail
96 | plover
97 | potoo
98 | prairie-chicken
99 | pygmy-owl
100 | pyrrhuloxia
101 | quail
102 | razorbill
103 | redhead
104 | redpoll
105 | redstart
106 | redwing
107 | roadrunner
108 | robin
109 | rook
110 | ruff
111 | saltator
112 | sand plover
113 | sanderling
114 | sapayoa
115 | sapsucker
116 | scaup
117 | schiffornis
118 | screamer
119 | screech-owl
120 | sharpbill
121 | shoveler
122 | shrike
123 | smew
124 | snowcap
125 | solitaire
126 | sora
127 | spindalis
128 | stonechat
129 | streamertail
130 | sunbittern
131 | sungrebe
132 | surfbird
133 | swallow
134 | swan
135 | swift
136 | tanager
137 | thrush
138 | tody
139 | toucanet
140 | towhee
141 | trogon
142 | tyrannulet
143 | veery
144 | verdin
145 | violetear
146 | vireo
147 | vulture
148 | wagtail
149 | water-rail
150 | waterthrush
151 | wheatear
152 | whimbrel
153 | whitethroat
154 | wigeon
155 | willet
156 | wood-pewee
157 | woodcock
158 | woodcreeper
159 | woodpecker
160 | wren
161 | wrenthrush
162 | wrentit
163 | yellowlegs
164 |
--------------------------------------------------------------------------------
/birdgen/suffixes.list:
--------------------------------------------------------------------------------
1 | backed
2 | banded
3 | barred
4 | bellied
5 | billed
6 | breasted
7 | browed
8 | capped
9 | cheeked
10 | chested
11 | chevroned
12 | chinned
13 | cockaded
14 | collared
15 | colored
16 | cowled
17 | crested
18 | crowned
19 | eared
20 | eating
21 | eyed
22 | faced
23 | flanked
24 | footed
25 | fringed
26 | fronted
27 | headed
28 | hooded
29 | legged
30 | lined
31 | lored
32 | mantled
33 | margined
34 | naped
35 | necked
36 | nosed
37 | polled
38 | ringed
39 | ruffed
40 | rumped
41 | scaled
42 | shanked
43 | shinned
44 | shouldered
45 | sided
46 | spectacled
47 | streaked
48 | striped
49 | tailed
50 | thighed
51 | throated
52 | tipped
53 | toed
54 | toothed
55 | vented
56 | wattled
57 | whiskered
58 | winged
59 |
--------------------------------------------------------------------------------
/bloom-filter/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -std=c99 -Wall
4 | LDLIBS = -lm
5 | LDLIBS =
6 |
7 | bloom : bloom.o main.o
8 |
9 | main.o : main.c bloom.h
10 | bloom.o : bloom.c bloom.h
11 |
12 | run : bloom
13 | ./$^ -c < google_5000000.txt
14 |
15 | clean :
16 | $(RM) bloom bloom.o main.o filter.bloom
17 |
--------------------------------------------------------------------------------
/bloom-filter/README.md:
--------------------------------------------------------------------------------
1 | # Private Gmail Leak Tester
2 |
3 | This project packs the leaked email database into a [bloom
4 | filter](http://en.wikipedia.org/wiki/Bloom_filter) for safe, private
5 | offline address testing against a list of leaked email addresses. The
6 | filter is 4MB uncompressed and contains no actual e-mail addresses. It has
7 | a false positive rate of less than 4%.
8 |
9 | (Update in 2021: This is for historical preservation. I would not write a
10 | bloom filter this way anymore, but it does capture some lessons learned.)
11 |
--------------------------------------------------------------------------------
/bloom-filter/bloom.h:
--------------------------------------------------------------------------------
1 | #ifndef BLOOM_H
2 | #define BLOOM_H
3 |
4 | #include
5 |
6 | struct bloom {
7 | char *bits;
8 | size_t nbytes;
9 | size_t nbits;
10 | int k;
11 | size_t n;
12 | };
13 |
14 | void bloom_init(struct bloom *f, int n_expected, double p);
15 | void bloom_save(const struct bloom *f, const char *file);
16 | void bloom_load(struct bloom *f, const char *file);
17 | void bloom_destroy(struct bloom *f);
18 |
19 | void bloom_set(struct bloom *f, size_t n);
20 | int bloom_get(const struct bloom *f, size_t n);
21 | int bloom_test(const struct bloom *f, const char *value);
22 | void bloom_insert(struct bloom *f, const char *value);
23 | double bloom_error_rate(const struct bloom *f);
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/checksums/adler32.h:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #include
3 |
4 | /* Append data to an Adler32 checksum. Use 1 for the initial checksum.
5 | */
6 | static unsigned long
7 | adler32_update(unsigned long sum, const void *data, size_t len)
8 | {
9 | size_t i;
10 | const unsigned char *p = data;
11 | unsigned long a = sum & 0xffff;
12 | unsigned long b = sum >> 16;
13 | for (i = 0; i < len; i++) {
14 | a = (a + p[i]) % 0xfff1UL;
15 | b = (b + a) % 0xfff1UL;
16 | }
17 | return (b << 16) | a;
18 | }
19 |
20 | /* Append two separately-computed Adler32 checksums.
21 | * If len2 does not fit in an unsigned long, pass (len2 % 65521).
22 | */
23 | static unsigned long
24 | adler32_combine(unsigned long a1, unsigned long a2, unsigned long len2)
25 | {
26 | static const unsigned long base = 0xfff1UL;
27 | unsigned long sum1;
28 | unsigned long sum2;
29 | unsigned long rem;
30 |
31 | rem = len2 % base;
32 | sum1 = a1 & 0xffffUL;
33 | sum2 = rem * sum1;
34 | sum2 %= base;
35 | sum1 += (a2 & 0xffff) + base - 1;
36 | sum2 += ((a1 >> 16) & 0xffffUL) +
37 | ((a2 >> 16) & 0xffffUL) + base - rem;
38 | if (sum1 >= base)
39 | sum1 -= base;
40 | if (sum1 >= base)
41 | sum1 -= base;
42 | if (sum2 >= (base << 1))
43 | sum2 -= (base << 1);
44 | if (sum2 >= base)
45 | sum2 -= base;
46 | return sum1 | (sum2 << 16);
47 | }
48 |
--------------------------------------------------------------------------------
/checksums/chunky64.c:
--------------------------------------------------------------------------------
1 | /* chunky64: a chunky, fast, 64-bit, portable, keyed hash function
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #include
5 | #include
6 |
7 | static uint64_t
8 | chunky64(const void *buf, size_t len, uint64_t key)
9 | {
10 | size_t nblocks = len / 8;
11 | const unsigned char *p = buf;
12 | uint64_t h = 0x637f6e65916dff18 ^ key;
13 |
14 | for (size_t i = 0; i < nblocks; i++) {
15 | h ^= (uint64_t)p[0] << 0 | (uint64_t)p[1] << 8 |
16 | (uint64_t)p[2] << 16 | (uint64_t)p[3] << 24 |
17 | (uint64_t)p[4] << 32 | (uint64_t)p[5] << 40 |
18 | (uint64_t)p[6] << 48 | (uint64_t)p[7] << 56;
19 | h *= 0xbf58476d1ce4e5b9;
20 | p += 8;
21 | }
22 |
23 | uint64_t last = len & 0xff;
24 | switch (len % 8) {
25 | case 7: last |= (uint64_t)p[6] << 56; /* fallthrough */
26 | case 6: last |= (uint64_t)p[5] << 48; /* fallthrough */
27 | case 5: last |= (uint64_t)p[4] << 40; /* fallthrough */
28 | case 4: last |= (uint64_t)p[3] << 32; /* fallthrough */
29 | case 3: last |= (uint64_t)p[2] << 24; /* fallthrough */
30 | case 2: last |= (uint64_t)p[1] << 16; /* fallthrough */
31 | case 1: last |= (uint64_t)p[0] << 8;
32 | h ^= last;
33 | h *= 0xd6e8feb86659fd93;
34 | }
35 |
36 | h ^= h >> 32;
37 | return h ^ key;
38 | }
39 |
--------------------------------------------------------------------------------
/checksums/crc16x25.h:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #include
3 |
4 | /* Append data to a 16-bit X.25 CRC. Use 0 for the initial CRC.
5 | * Note: MVALink uses bitwise-NOT of X.25 for its checksum.
6 | */
7 | static unsigned
8 | crc16x25_update(unsigned crc, const void *buf, size_t len)
9 | {
10 | size_t i;
11 | const unsigned char *p = buf;
12 | crc ^= 0xffff;
13 | for (i = 0; i < len; i++) {
14 | unsigned t = p[i] ^ (crc & 0xff);
15 | t ^= t<<4 & 0xff;
16 | crc = crc>>8 ^ t<<8 ^ t<<3 ^ t>>4;
17 | }
18 | return crc ^ 0xffff;
19 | }
20 |
--------------------------------------------------------------------------------
/checksums/fletcher64.c:
--------------------------------------------------------------------------------
1 | /* Compute Fletcher-64 checksum
2 | *
3 | * All bytes are processed in little-endian byte order regardless of the
4 | * host systems' native byte order.
5 | *
6 | * This is free and unencumbered software released into the public domain.
7 | */
8 | #include
9 |
10 | #define FLETCHER64_SIZE 8
11 | #define FLETCHER64_INIT {0, 0}
12 |
13 | struct fletcher64 {
14 | unsigned long lo;
15 | unsigned long hi;
16 | };
17 |
18 | /* Append a buffer of input to the checksum. All input buffers except
19 | * for the final one must have a length divisible by four.
20 | */
21 | static void
22 | fletcher64_append(struct fletcher64 *ctx, void *buf, size_t len)
23 | {
24 | unsigned long block;
25 | unsigned long lo = ctx->lo;
26 | unsigned long hi = ctx->hi;
27 | const unsigned char *ptr = buf;
28 | const unsigned char *end = ptr + len / 4 * 4;
29 |
30 | /* Process each 32-bit block */
31 | for (; ptr < end; ptr += 4) {
32 | block = (unsigned long)ptr[0] << 0 |
33 | (unsigned long)ptr[1] << 8 |
34 | (unsigned long)ptr[2] << 16 |
35 | (unsigned long)ptr[3] << 24;
36 | lo += block;
37 | hi += lo;
38 | }
39 |
40 | /* Process any tail bytes */
41 | block = 0;
42 | switch (len % 4) {
43 | case 3: block |= (unsigned long)end[2] << 16; /* FALLTHROUGH */
44 | case 2: block |= (unsigned long)end[1] << 8; /* FALLTHROUGH */
45 | case 1: block |= (unsigned long)end[0] << 0;
46 | lo += block;
47 | hi += lo;
48 | }
49 |
50 | ctx->lo = lo;
51 | ctx->hi = hi;
52 | }
53 |
54 | static void
55 | fletcher64_finish(struct fletcher64 *ctx, void *sum)
56 | {
57 | unsigned long lo = ctx->lo;
58 | unsigned long hi = ctx->hi;
59 | unsigned char *p = sum;
60 | p[0] = lo >> 0;
61 | p[1] = lo >> 8;
62 | p[2] = lo >> 16;
63 | p[3] = lo >> 24;
64 | p[4] = hi >> 0;
65 | p[5] = hi >> 8;
66 | p[6] = hi >> 16;
67 | p[7] = hi >> 24;
68 | }
69 |
--------------------------------------------------------------------------------
/checksums/gimli.c:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #include
3 |
4 | void
5 | gimli(uint32_t s[12])
6 | {
7 | for (int r = 24; r > 0; r--) {
8 | for (int c = 0; c < 4; c++) {
9 | uint32_t x = s[c+0];
10 | uint32_t y = s[c+4];
11 | uint32_t z = s[c+8];
12 | x = x << 24 | x >> 8;
13 | y = y << 9 | y >> 23;
14 | s[c+8] = x ^ z<<1 ^ ((y&z) << 2);
15 | s[c+4] = y ^ x<<0 ^ ((x|z) << 1);
16 | s[c+0] = z ^ y<<0 ^ ((x&y) << 3);
17 | }
18 |
19 | uint32_t t;
20 | if ((r & 3) == 0) {
21 | t = s[0]; s[0] = s[1]; s[1] = t;
22 | t = s[2]; s[2] = s[3]; s[3] = t;
23 | }
24 | if ((r & 3) == 2) {
25 | t = s[0]; s[0] = s[2]; s[2] = t;
26 | t = s[1]; s[1] = s[3]; s[3] = t;
27 | }
28 | if ((r & 3) == 0) {
29 | s[0] ^= 0x9e377900 | r;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/checksums/hash22.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | void
6 | hash22(float *x, float *y)
7 | {
8 | uint32_t hi, lo;
9 | memcpy(&hi, x, sizeof(hi));
10 | memcpy(&lo, y, sizeof(lo));
11 | uint64_t v = ~((uint64_t)hi<<32 | lo);
12 | v *= 0xaddc7c7ef4e6ce37;
13 | v ^= v >> 32;
14 | v *= 0x9e6f287da60cbcad;
15 | v ^= v >> 32;
16 | *x = ldexpf(v>>32, -32);
17 | *y = ldexpf((uint32_t)v, -32);
18 | }
19 |
20 | #include
21 |
22 | int
23 | main(void)
24 | {
25 | float x = 3.1415927;
26 | float y = 1e+06;
27 | printf("%.9g %.9g\n", x, y);
28 | hash22(&x, &y);
29 | printf("%.9g %.9g\n", x, y);
30 | }
31 |
--------------------------------------------------------------------------------
/checksums/hash22.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math"
6 | )
7 |
8 | func hash22(x, y float32) (float32, float32) {
9 | hi, lo := math.Float32bits(x), math.Float32bits(y)
10 | v := ^(uint64(hi)<<32 | uint64(lo))
11 | v *= 0xaddc7c7ef4e6ce37
12 | v ^= v >> 32
13 | v *= 0x9e6f287da60cbcad
14 | v ^= v >> 32
15 | return float32(math.Ldexp(float64(v>>32), -32)),
16 | float32(math.Ldexp(float64(uint32(v)), -32))
17 | }
18 |
19 | func main() {
20 | var x float32 = math.Pi
21 | var y float32 = 1e6
22 | fmt.Println(x, y)
23 | fmt.Println(hash22(x, y))
24 | }
25 |
--------------------------------------------------------------------------------
/checksums/murmurhash3.h:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #include
3 |
4 | static uint32_t
5 | murmurhash3(const void *key, uint32_t len, uint32_t seed)
6 | {
7 | uint32_t hash = seed;
8 | uint32_t nblocks = len / 4;
9 | const unsigned char *p = key;
10 | for (uint32_t i = 0; i < nblocks; i++) {
11 | uint32_t k = (uint32_t)p[i*4+0] << 0 |
12 | (uint32_t)p[i*4+1] << 8 |
13 | (uint32_t)p[i*4+2] << 16 |
14 | (uint32_t)p[i*4+3] << 24;
15 | k *= UINT32_C(0xcc9e2d51);
16 | k = (k << 15) | (k >> 17);
17 | k *= UINT32_C(0x1b873593);
18 | hash ^= k;
19 | hash = ((hash << 13) | (hash >> 19)) * 5 + UINT32_C(0xe6546b64);
20 | }
21 | const unsigned char *tail = p + nblocks*4;
22 | uint32_t k1 = 0;
23 | switch (len & 3) {
24 | case 3:
25 | k1 ^= tail[2] << 16;
26 | case 2:
27 | k1 ^= tail[1] << 8;
28 | case 1:
29 | k1 ^= tail[0];
30 | k1 *= UINT32_C(0xcc9e2d51);
31 | k1 = k1 << 15 | k1 >> 17;
32 | k1 *= UINT32_C(0x1b873593);
33 | hash ^= k1;
34 | }
35 | hash ^= len;
36 | hash ^= hash >> 16;
37 | hash *= UINT32_C(0x85ebca6b);
38 | hash ^= hash >> 13;
39 | hash *= UINT32_C(0xc2b2ae35);
40 | hash ^= hash >> 16;
41 | return hash;
42 | }
43 |
--------------------------------------------------------------------------------
/cols/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -ansi -pedantic -O3 -Wall -Wextra
4 | LDFLAGS = -s
5 | LDLIBS =
6 | PREFIX = /usr/local
7 |
8 | cols$(EXE): cols.c
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ cols.c $(LDLIBS)
10 |
11 | install: cols$(EXE)
12 | mkdir -p $(DESTDIR)$(PREFIX)/bin
13 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
14 | install -m 755 cols$(EXE) $(DESTDIR)$(PREFIX)/bin
15 | gzip $(DESTDIR)$(PREFIX)/share/man/man1/cols.1.gz
16 |
17 | uninstall:
18 | rm -f $(DESTDIR)$(PREFIX)/bin/cols$(EXE)
19 | rm -f $(DESTDIR)$(PREFIX)/share/man/man1/cols.1.gz
20 |
21 | clean:
22 | rm -f cols$(EXE)
23 |
--------------------------------------------------------------------------------
/cp1252/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -Wall -Wextra -Og -g
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | check: tests$(EXE)
8 | ./tests
9 |
10 | test: check
11 |
12 | tests$(EXE): tests.c cp1252.c
13 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ tests.c $(LDLIBS)
14 |
15 | clean:
16 | rm -f tests$(EXE)
17 |
--------------------------------------------------------------------------------
/cp1252/README.md:
--------------------------------------------------------------------------------
1 | # Various CP-1252 encode/decode functions
2 |
3 | Various functions for efficiently encoding and decoding [code page
4 | 1252][wiki]. Includes "best fit" extensions so that all bytes of CP-1252
5 | are mapped.
6 |
7 | ```c
8 | // Decode one byte of CP-1252 to a Unicode code point.
9 | //
10 | // Undefined inputs are mapped to their "best fit" code point.
11 | long cp1252_to_unicode(int c);
12 |
13 | // Encode a Unicode code point into one byte of CP-1252.
14 | //
15 | // The five undefined CP-1252 bytes are mapped to their "best fit" code
16 | // points. Otherwise unrepresentable input is converted to U+001A
17 | // (SUBSTITUTE).
18 | int unicode_to_cp1252(long r);
19 |
20 | // Transcode one UTF-8 code point into one byte of CP-1252.
21 | //
22 | // The five undefined CP-1252 bytes are mapped to their "best fit" code
23 | // points. Otherwise unrepresentable or invalid input is converted to U+001A
24 | // (SUBSTITUTE). Always stores at exactly one byte to the output buffer.
25 | // Returns the number of input bytes consumed (from 1 to 4).
26 | int utf8_to_cp1252(void *cp1252, const void *utf8);
27 |
28 | // Decode one byte of CP-1252 into bytes of UTF-8.
29 | //
30 | // Undefined bytes mapped to their "best bit" code points. Returns the
31 | // number of bytes stored (from 1 to 3).
32 | int cp1252_to_utf8(void *utf8, int c);
33 | ```
34 |
35 |
36 | [wiki]: https://en.wikipedia.org/wiki/Windows-1252
37 |
--------------------------------------------------------------------------------
/cp1252/tests.c:
--------------------------------------------------------------------------------
1 | #include "cp1252.c"
2 | #include
3 |
4 | int
5 | main(void)
6 | {
7 | int fail = 0;
8 |
9 | for (int c = 0; c < 256; c++) {
10 | long r = cp1252_to_unicode(c);
11 | int x = unicode_to_cp1252(r);
12 | if (c != x) {
13 | printf("FAIL: round trip through Unicode, %02x != %02x\n", c, x);
14 | fail++;
15 | }
16 | }
17 |
18 | for (long r = 0; r <= 0x10ffff; r++) {
19 | int c = unicode_to_cp1252(r);
20 | long x = cp1252_to_unicode(c);
21 | if ((r == 0x1a && c != 0x1a) || (c != 0x1a && x != r)) {
22 | printf("FAIL: round trip through CP-1252, %04lx != %04lx [%02x]\n",
23 | r, x, c);
24 | fail++;
25 | }
26 | }
27 |
28 | for (int c = 0; c < 256; c++) {
29 | unsigned char buf[4] = {0, 0, 0, 0};
30 | int ez = cp1252_to_utf8(buf, c);
31 | unsigned char x;
32 | int dz = utf8_to_cp1252(&x, buf);
33 | if (ez != dz || x != c) {
34 | printf("FAIL: round trip through UTF-8, %02x != %02x "
35 | "[%02x %02x %02x]\n", c, x, buf[0], buf[1], buf[2]);
36 | }
37 | }
38 |
39 | if (fail) {
40 | return 1;
41 | }
42 | puts("All tests pass");
43 | return 0;
44 | }
45 |
--------------------------------------------------------------------------------
/csvquote/.gitignore:
--------------------------------------------------------------------------------
1 | csvquote
2 | csvdump
3 | *.exe
4 |
--------------------------------------------------------------------------------
/csvquote/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc -std=c11
3 | CFLAGS = -march=x86-64-v3 -O3 -Wall -Wextra
4 | LDFLAGS = -s
5 | LDLIBS =
6 | PREFIX = /usr/local
7 |
8 | csvquote$(EXE): csvquote.c
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ csvquote.c $(LDLIBS)
10 |
11 | csvdump$(EXE): etc/csvdump.c
12 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ etc/csvdump.c $(LDLIBS)
13 |
14 | install: csvquote$(EXE)
15 | mkdir -p $(DESTDIR)$(PREFIX)/bin
16 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
17 | install -m 755 csvquote$(EXE) $(DESTDIR)$(PREFIX)/bin
18 | gzip $(DESTDIR)$(PREFIX)/share/man/man1/csvquote.1.gz
19 |
20 | uninstall:
21 | rm -f $(DESTDIR)$(PREFIX)/bin/csvquote$(EXE)
22 | rm -f $(DESTDIR)$(PREFIX)/share/man/man1/csvquote.1.gz
23 |
24 | bench: csvquote$(EXE) csvdump$(EXE)
25 | ./csvdump | ./csvquote >/dev/null
26 |
27 | clean:
28 | rm -f csvquote$(EXE) csvdump$(EXE)
29 |
--------------------------------------------------------------------------------
/csvquote/README.md:
--------------------------------------------------------------------------------
1 | # High performance csvquote with SIMD
2 |
3 | Inspired by [the original][orig] ([via][]), this command line tool
4 | converts LINE FEED (LF, U+000A) into RECORD SEPARATOR (RS, U+001E), and
5 | COMMA (U+002C) into UNIT SEPARATOR (US, U+001F) when these characters
6 | appear inside quoted CSV fields, allowing CSV files to be more easily
7 | processed by standard unix command line tools.
8 |
9 | $ csvquote sum.csv
12 |
13 | This version includes an AVX2 implementation that processes CSV at about 4
14 | GiB/s on modern hardware. It operates on 32-byte chunks at a time and uses
15 | a two's complement trick to discover quoted ranges of input. The slower
16 | plain C fallback implementation uses a branchless lookup table, about 2x
17 | faster than the original implementation.
18 |
19 | It's fast enough that stdio becomes a serious bottleneck, so the program
20 | bypasses it if possible.
21 |
22 | ## Benchmark
23 |
24 | To run the live benchmark:
25 |
26 | make bench
27 |
28 | This assumes you're on an x86-64-v3 host. If you're not, or you'd like to
29 | disable SIMD:
30 |
31 | make CFLAGS=-O3 bench
32 |
33 |
34 | [orig]: https://github.com/dbro/csvquote
35 | [via]: https://github.com/adamgordonbell/csvquote
36 |
--------------------------------------------------------------------------------
/csvquote/csvquote.1:
--------------------------------------------------------------------------------
1 | .TH csvquote 1
2 | .SH NAME
3 | csvquote \- temporarily mutate CSV for easier processing by unix tools
4 | .SH SYNOPSIS
5 | .B csvquote
6 | [\-\fBS\fR]
7 | [\-\fBh\fR]
8 | [\-\fBu\fR]
9 | .SH DESCRIPTION
10 | .B csvquote
11 | converts LINE FEED (LF, U+000A) into RECORD SEPARATOR (RS, U+001E), and COMMA (U+002C) into UNIT SEPARATOR (US, U+001F) when these characters appear inside quoted CSV fields.
12 | This allows standard unix command line tools to more easily and correctly process CSV data.
13 | .SH OPTIONS
14 | .TP
15 | \fB\-S\fR
16 | Abort if the encoding would be irreversible (strict mode).
17 | .TP
18 | \fB\-h\fR
19 | Print help information to standard output and exit.
20 | .TP
21 | \fB\-u\fR
22 | Restore the original CSV data (reverse mode).
23 | .SH ENVIRONMENT
24 | .B csvquote
25 | is not affected by environment variables.
26 | .SH FILES
27 | .B csvquote
28 | is not affected by any files.
29 | It only writes to standard output and standard error.
30 | .SH EXAMPLES
31 | .PP
32 | .B awk
33 | field splitting normally cannot handle CSV, but it can when quoted:
34 | .RS 2
35 | .nf
36 | .B $ csvquote sum.csv
39 | .fi
40 | .RE
41 | .SH "SEE ALSO"
42 | .BR awk(1)
43 | .SH HISTORY
44 | This
45 | .B csvquote
46 | is a high performance clone of the original implementation by Dan Brown.
47 | .SH AUTHORS
48 | Chris Wellons
49 | .SH BUGS
50 | No known bugs.
51 |
--------------------------------------------------------------------------------
/csvquote/etc/csvdump.c:
--------------------------------------------------------------------------------
1 | // Benchmark/test for csvquote
2 | // $ cc -O3 -o csvdump csvdump.c
3 | // $ ./csvdump | ./csvquote >/dev/null
4 | // This is free and unencumbered software released into the public domain.
5 | #include
6 | #include
7 |
8 | int rng(int n)
9 | {
10 | static unsigned long long s = 1;
11 | return ((s = s*0x3243f6a8885a308dU + 1) >> 33) % n;
12 | }
13 |
14 | int
15 | main(void)
16 | {
17 | #ifdef _WIN32
18 | int _setmode(int, int);
19 | _setmode(1, 0x8000);
20 | #endif
21 |
22 | static char buf[1L<<17];
23 |
24 | // Fill buf with random CSV content
25 | char *p = buf;
26 | for (int r = 0;; r++) {
27 | for (int i = 0; i < 16; i++) {
28 | int len = 0 + rng(20);
29 |
30 | if (i > 0) *p++ = ',';
31 |
32 | if (rng(10)) {
33 | for (int j = 0; j < len; j++) {
34 | int c = ' ' + rng('~' - ' ' + 1);
35 | switch (c) {
36 | case '"' :
37 | case ',' :
38 | case '\n': break;
39 | default : *p++ = c;
40 | }
41 | }
42 |
43 | } else {
44 | *p++ = '"';
45 | for (int j = 0; j < len; j++) {
46 | int c = ' ' + rng('~' - ' ' + 2);
47 | if (c == 127) c = '\n';
48 | switch (c) {
49 | case '"' : *p++ = c; // fallthrough
50 | default : *p++ = c;
51 | }
52 | }
53 | *p++ = '"';
54 | }
55 | }
56 | *p++ = '\n';
57 |
58 | if ((size_t)(p-buf) > sizeof(buf)/2) {
59 | break;
60 | }
61 | }
62 | size_t len = p - buf;
63 |
64 | // Endlessly repeat the buffer, printing output speed to stderr
65 | long t = 0;
66 | time_t last = time(0);
67 | for (long c = 1; ; c++) {
68 | if (!fwrite(buf, len, 1, stdout)) {
69 | return 1;
70 | }
71 |
72 | time_t now = time(0);
73 | if (now != last) {
74 | if (t++) {
75 | double r = len / 1048576.0 * c;
76 | fprintf(stderr, "%-8.6f MiB/s\n", r / (now - last));
77 | }
78 | last = now;
79 | c = 0;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/elsiefour/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -ansi -pedantic -Wall -Wextra -O3 -g3
4 |
5 | lc4: lc4.c lc4.h
6 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ lc4.c $(LDLIBS)
7 |
8 | check: lc4
9 | ./lc4 -T
10 |
11 | clean:
12 | rm -rf lc4
13 |
--------------------------------------------------------------------------------
/elsiefour/README.md:
--------------------------------------------------------------------------------
1 | # ANSI C implementation of ElsieFour (LC4)
2 |
3 | This is an ANSI C implementation of [ElsieFour][pdf] (LC4), a low-tech
4 | authenticated encryption algorithm that can be computed by hand.
5 |
6 | ## API
7 |
8 | Since LC4 is a plaintext-dependent stream cipher, the context is mutated
9 | as the stream is encrypted and decrypted.
10 |
11 | ```c
12 | /* Return non-zero if KEY is a valid key.
13 | * A valid key is null-terminated and contains each character from the
14 | * valid set exactly once.
15 | */
16 | int lc4_valid(const char *key);
17 |
18 | /* Initialize the LC4 context with the given valid key.
19 | */
20 | void lc4_init(struct lc4 *, const char *key);
21 |
22 | /* Encrypt a single character, modifying the context.
23 | * Returns 0 if the character isn't valid.
24 | */
25 | int lc4_encrypt(struct lc4 *, int);
26 |
27 | /* Decrypt a single character, modifying the context.
28 | * Returns 0 if the character isn't valid.
29 | */
30 | int lc4_decrypt(struct lc4 *, int);
31 | ```
32 |
33 | The nonce and signature are the responsibility of the caller. See the
34 | paper for how to handle this. It's really simple.
35 |
36 | ## Command Line Program
37 |
38 | The `lc4` program is both a test suite for the library as well as a
39 | small encryption, decryption, and key/nonce generation utility. This
40 | isn't seriously intended for securing messages but rather for testing.
41 |
42 | $ lc4 -G | tee key
43 | kidpgvnmybos4haf5628#xcj_uztrlq739ew
44 |
45 | $ echo hello world | ./lc4 -E $(cat key)
46 | 9j#akdcp3fb
47 |
48 | $ echo 9j#akdcp3fb | ./lc4 -D $(cat key)
49 | hello_world
50 |
51 | ## Other implementations
52 |
53 | * (Python)
54 | * (JavaScript)
55 | * (Go)
56 | * (LS47 in Python)
57 |
58 | [pdf]: https://eprint.iacr.org/2017/339.pdf
59 |
--------------------------------------------------------------------------------
/glove/GNUmakefile:
--------------------------------------------------------------------------------
1 | CC = cc
2 | CFLAGS = -g3 -Wall -Wextra -Wno-unused-parameter -Wno-unused-function \
3 | -Wdouble-promotion -Wconversion -Wno-sign-conversion \
4 | -fsanitize=undefined -fsanitize-undefined-trap-on-error
5 | LDFLAGS =
6 | LDLIBS =
7 |
8 | all: glove-convert$(EXE) glove-lookup$(EXE)
9 |
10 | glove-convert.exe: glove-convert_win32.c glove.c
11 | $(CC) -nostartfiles $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
12 |
13 | glove-lookup.exe: glove-lookup_win32.c glove-lookup.c glove.c
14 | $(CC) -nostartfiles $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
15 |
16 | glove-convert: glove-convert_posix.c glove.c
17 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
18 |
19 | glove-lookup: glove-lookup_posix.c glove-lookup.c glove.c
20 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
21 |
22 | clean:
23 | rm -f glove-convert.exe glove-lookup.exe glove-convert glove-lookup
24 |
--------------------------------------------------------------------------------
/glove/glove-convert_posix.c:
--------------------------------------------------------------------------------
1 | #include "glove.c"
2 | #include
3 | #include
4 | #include
5 |
6 | int main(void)
7 | {
8 | struct stat sb;
9 | if (fstat(0, &sb)) {
10 | return 1;
11 | }
12 | size len = sb.st_size;
13 |
14 | void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, 0, 0);
15 | if (data == MAP_FAILED) {
16 | return 1;
17 | }
18 |
19 | glove_specs s;
20 | glove_examine(&s, data, len);
21 |
22 | byte *db = mmap(0, s.db_size, PROT_WRITE, MAP_PRIVATE|MAP_ANON, 1, 0);
23 | if (db == MAP_FAILED) {
24 | return 1;
25 | }
26 | glove_make_db(db, &s, data, len);
27 |
28 | for (size off = 0; off < s.db_size;) {
29 | size r = write(1, db+off, s.db_size-off);
30 | if (r < 1) {
31 | return 1;
32 | }
33 | off += r;
34 | }
35 | return 0;
36 | }
37 |
--------------------------------------------------------------------------------
/glove/glove-convert_win32.c:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #include "glove.c"
3 |
4 | #define W32(r) __declspec(dllimport) r __stdcall
5 | W32(i32) CreateFileMappingA(uptr, uptr, i32, i32, i32, uptr);
6 | W32(void) ExitProcess(i32);
7 | W32(b32) GetFileSizeEx(uptr, i64 *);
8 | W32(i32) GetStdHandle(i32);
9 | W32(void *) MapViewOfFile(uptr, i32, i32, i32, size);
10 | W32(void *) VirtualAlloc(void *, size, i32, i32);
11 | W32(b32) WriteFile(uptr, void *, i32, i32 *, uptr);
12 |
13 | static b32 run(void)
14 | {
15 | enum {
16 | FILE_MAP_READ = 4,
17 | PAGE_READONLY = 2,
18 | PAGE_READWRITE = 4,
19 | MEM_ALLOCATE = 0x3000,
20 | };
21 |
22 | i32 stdin = GetStdHandle(-10);
23 | i32 stdout = GetStdHandle(-11);
24 |
25 | b32 err = 0;
26 | i64 len;
27 | err |= !GetFileSizeEx(stdin, &len);
28 | i32 mapping = CreateFileMappingA(stdin, 0, PAGE_READONLY, 0, 0, 0);
29 | err |= !mapping;
30 | void *data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
31 | err |= !data;
32 |
33 | glove_specs s;
34 | glove_examine(&s, data, len);
35 | byte *db = VirtualAlloc(0, s.db_size, MEM_ALLOCATE, PAGE_READWRITE);
36 | err |= !db;
37 |
38 | if (err) {
39 | return 1;
40 | }
41 |
42 | glove_make_db(db, &s, data, len);
43 | for (size off = 0; !err && off max ? max : (i32)(s.db_size-off);
46 | err |= !WriteFile(stdout, db+off, amt, &amt, 0);
47 | off += amt;
48 | }
49 | return err;
50 | }
51 |
52 | void mainCRTStartup(void)
53 | {
54 | b32 err = run();
55 | ExitProcess(err);
56 | }
57 |
--------------------------------------------------------------------------------
/glove/glove-lookup_posix.c:
--------------------------------------------------------------------------------
1 | #include "glove-lookup.c"
2 | #include
3 | #include
4 | #include
5 |
6 | static b32 fullwrite(u8 *buf, i32 len)
7 | {
8 | for (i32 off = 0; off < len;) {
9 | i32 r = (i32)write(1, buf+off, len-off);
10 | if (r < 1) {
11 | return 0;
12 | }
13 | off += r;
14 | }
15 | return 1;
16 | }
17 |
18 | int main(int argc, char **argv)
19 | {
20 | struct stat sb;
21 | if (fstat(0, &sb)) {
22 | return 1;
23 | }
24 | size len = sb.st_size;
25 |
26 | void *db = mmap(0, len, PROT_READ, MAP_PRIVATE, 0, 0);
27 | if (db == MAP_FAILED) {
28 | return 1;
29 | }
30 |
31 | size cap = 1<<20;
32 | arena scratch = {0};
33 | scratch.beg = mmap(0, cap, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
34 | scratch.end = scratch.beg + cap;
35 |
36 | s8 *args = new(&scratch, s8, argc);
37 | for (int i = 0; i < argc; i++) {
38 | args[i] = s8cstr(argv[i]);
39 | }
40 | return run(argc, args, db, scratch);
41 | }
42 |
--------------------------------------------------------------------------------
/glove/glove-lookup_win32.c:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #include "glove-lookup.c"
3 |
4 | #define W32(r) __declspec(dllimport) r __stdcall
5 | W32(i32) CreateFileMappingA(uptr, uptr, i32, i32, i32, uptr);
6 | W32(void) ExitProcess(i32);
7 | W32(b32) GetFileSizeEx(uptr, i64 *);
8 | W32(i32) GetStdHandle(i32);
9 | W32(void *) MapViewOfFile(uptr, i32, i32, i32, size);
10 | W32(b32) WriteFile(uptr, void *, i32, i32 *, uptr);
11 | W32(u16 *) GetCommandLineW(void);
12 | W32(u16 **) CommandLineToArgvW(u16 *, i32 *);
13 | W32(i32) WideCharToMultiByte(i32, i32, u16 *, i32, u8 *, i32, uptr, uptr);
14 | W32(void *) VirtualAlloc(void *, size, i32, i32);
15 |
16 | static b32 fullwrite(u8 *buf, i32 len)
17 | {
18 | i32 stdout = GetStdHandle(-11);
19 | return WriteFile(stdout, buf, len, &len, 0);
20 | }
21 |
22 | static s8 makes8(u16 *w, arena *perm)
23 | {
24 | enum {
25 | CP_UTF8 = 65001,
26 | };
27 | s8 s = {0};
28 | s.len = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
29 | s.data = new(perm, u8, s.len);
30 | WideCharToMultiByte(CP_UTF8, 0, w, -1, s.data, (i32)s.len, 0, 0);
31 | s.len--;
32 | return s;
33 | }
34 |
35 | static b32 entry(void)
36 | {
37 | enum {
38 | FILE_MAP_READ = 4,
39 | PAGE_READONLY = 2,
40 | PAGE_READWRITE = 4,
41 | MEM_ALLOCATE = 0x3000,
42 | };
43 |
44 | b32 err = 0;
45 | i32 stdin = GetStdHandle(-10);
46 | i32 mapping = CreateFileMappingA(stdin, 0, PAGE_READONLY, 0, 0, 0);
47 | err |= !mapping;
48 | void *idx = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
49 | err |= !idx;
50 | if (err) {
51 | return 1;
52 | }
53 |
54 | size cap = 1<<20;
55 | arena scratch = {0};
56 | scratch.beg = VirtualAlloc(0, cap, MEM_ALLOCATE, PAGE_READWRITE);
57 | scratch.end = scratch.beg + cap;
58 |
59 | u16 *cmdline = GetCommandLineW();
60 | i32 argc;
61 | u16 **argvw = CommandLineToArgvW(cmdline, &argc);
62 |
63 | s8 *argv = new(&scratch, s8, argc);
64 | for (i32 i = 0; i < argc; i++) {
65 | argv[i] = makes8(argvw[i], &scratch);
66 | }
67 | return run(argc, argv, idx, scratch);
68 | }
69 |
70 | void mainCRTStartup(void)
71 | {
72 | b32 err = entry();
73 | ExitProcess(err);
74 | }
75 |
--------------------------------------------------------------------------------
/glove/glove.def:
--------------------------------------------------------------------------------
1 | LIBRARY glove.dll
2 | EXPORTS
3 | glove_examine
4 | glove_make_db
5 | glove_load_db
6 | glove_get_embedding
7 |
--------------------------------------------------------------------------------
/glove/glove.h:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #pragma once
3 | #include
4 | #include
5 |
6 | typedef struct {
7 | size_t db_size;
8 | int32_t num_words;
9 | int32_t num_dims;
10 | int32_t _reserved1[1];
11 | } glove_specs;
12 |
13 | typedef struct {
14 | int32_t num_words;
15 | int32_t num_dims;
16 | int32_t _reserved1[1];
17 | void *_reserved2[4];
18 | } glove;
19 |
20 | // Compute parameters for the dataset, including the database size for
21 | // the caller to allocate. The size is zero if the input is too large
22 | // for a database.
23 | void glove_examine(glove_specs *, const void *txt, size_t len);
24 |
25 | // Populate the database from the dataset. The database is position
26 | // independent, designed to be dumped to a file and memory-mapped for
27 | // lookups.
28 | void glove_make_db(void *db, glove_specs *, const void *txt, size_t len);
29 |
30 | // Prepare a database for lookups by retrieving its parameters.
31 | void glove_load_db(glove *, const void *db);
32 |
33 | // Lookup a word in the database, returning its embedding, or null if
34 | // not found. The returned object is within the database buffer and so
35 | // shares its lifetime.
36 | float *glove_get_embedding(const glove *, const char *word);
37 |
--------------------------------------------------------------------------------
/hexmap/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -std=c99 -pedantic \
4 | -Ofast -march=native \
5 | -ggdb3 -fsanitize=address -fsanitize=undefined \
6 | -Wall -Wextra -Wdouble-promotion
7 | LDFLAGS = -fsanitize=address -fsanitize=undefined
8 | LDLIBS = -lm
9 |
10 | hexmap: hexmap.c bmp.h getopt.h
11 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ hexmap.c $(LDLIBS)
12 |
13 | clean:
14 | rm -f hexmap hexmap.exe
15 |
--------------------------------------------------------------------------------
/hexmap/getopt.h:
--------------------------------------------------------------------------------
1 | /* A minimal POSIX getopt() implementation in ANSI C
2 | *
3 | * This is free and unencumbered software released into the public domain.
4 | *
5 | * This implementation supports the convention of resetting the option
6 | * parser by assigning optind to 0. This resets the internal state
7 | * appropriately.
8 | *
9 | * Ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
10 | */
11 | #ifndef GETOPT_H
12 | #define GETOPT_H
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | static int optind = 1;
19 | static int opterr = 1;
20 | static int optopt;
21 | static char *optarg;
22 |
23 | static int
24 | getopt(int argc, char * const argv[], const char *optstring)
25 | {
26 | static int optpos = 1;
27 | const char *arg;
28 | (void)argc;
29 |
30 | /* Reset? */
31 | if (optind == 0) {
32 | optind = 1;
33 | optpos = 1;
34 | }
35 |
36 | arg = argv[optind];
37 | if (arg && strcmp(arg, "--") == 0) {
38 | optind++;
39 | return -1;
40 | } else if (!arg || arg[0] != '-' || !isalnum(arg[1])) {
41 | return -1;
42 | } else {
43 | const char *opt = strchr(optstring, arg[optpos]);
44 | optopt = arg[optpos];
45 | if (!opt) {
46 | if (opterr && *optstring != ':')
47 | fprintf(stderr, "%s: illegal option: %c\n", argv[0], optopt);
48 | return '?';
49 | } else if (opt[1] == ':') {
50 | if (arg[optpos + 1]) {
51 | optarg = (char *)arg + optpos + 1;
52 | optind++;
53 | optpos = 1;
54 | return optopt;
55 | } else if (argv[optind + 1]) {
56 | optarg = (char *)argv[optind + 1];
57 | optind += 2;
58 | optpos = 1;
59 | return optopt;
60 | } else {
61 | if (opterr && *optstring != ':')
62 | fprintf(stderr,
63 | "%s: option requires an argument: %c\n",
64 | argv[0], optopt);
65 | return *optstring == ':' ? ':' : '?';
66 | }
67 | } else {
68 | if (!arg[++optpos]) {
69 | optind++;
70 | optpos = 1;
71 | }
72 | return optopt;
73 | }
74 | }
75 | }
76 |
77 | #endif
78 |
--------------------------------------------------------------------------------
/int32trie/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -O3 -g -Wall -Wextra -Wno-int-in-bool-context
4 | LDFLAGS = -fsanitize=address -fsanitize=undefined
5 | LDLIBS =
6 | BENCH =
7 |
8 | check: test
9 | $(BENCH) ./test
10 |
11 | test: test.c int32trie.c int32trie.h
12 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test.c int32trie.c $(LDLIBS)
13 |
14 | clean:
15 | rm -f test test.exe
16 |
--------------------------------------------------------------------------------
/int32trie/README.md:
--------------------------------------------------------------------------------
1 | # int32 trie with int32 values
2 |
3 | This C99 library implements a 32-bit trie with a depth of 8 (i.e. one
4 | nibble per node). It stores one non-zero 32-bit value per key. All nodes
5 | are allocated from a single, large allocation.
6 |
7 | ```c
8 | int32_t int32trie_get(const struct int32trie *, int32_t k);
9 | int int32trie_put(struct int32trie *, int32_t k, int32_t v);
10 | void int32trie_reset(struct int32trie *);
11 | int int32trie_visit(const struct int32trie *, int32trie_visitor, void *);
12 | ```
13 |
14 | Full documentation is in the header file.
15 |
--------------------------------------------------------------------------------
/int32trie/int32trie.h:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #ifndef TRIE_H
3 | #define TRIE_H
4 |
5 | #include
6 |
7 | // Initialize to zero.
8 | struct int32trie {
9 | uint32_t len, cap;
10 | struct {
11 | uint32_t child[16];
12 | } *nodes;
13 | };
14 |
15 | // A trie visitor returns non-zero when it wants to stop.
16 | typedef int int32trie_visitor(int32_t k, int32_t v, void *userptr);
17 |
18 | // Return the value for the given integer key, or 0 if not present.
19 | int32_t int32trie_get(const struct int32trie *, int32_t k);
20 |
21 | // Set the stored boolean for the given integer, or 0 to remove.
22 | // Returns 0 if out of memory.
23 | int int32trie_put(struct int32trie *, int32_t k, int32_t v);
24 |
25 | // Free all of the trie's resources and reset to zero.
26 | void int32trie_reset(struct int32trie *);
27 |
28 | // Visit each key-value pair in key order. Returns 0 if the whole trie was
29 | // visited, otherwise the visitor's return value.
30 | int int32trie_visit(const struct int32trie *, int32trie_visitor, void *);
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/int32trie/test.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "int32trie.h"
3 |
4 | static uint32_t
5 | triple32(uint32_t x)
6 | {
7 | x ^= x >> 17; x *= 0xed5ad4bb;
8 | x ^= x >> 11; x *= 0xac4c1b51;
9 | x ^= x >> 15; x *= 0x31848bab;
10 | x ^= x >> 14;
11 | return x;
12 | }
13 |
14 | static uint32_t
15 | triple32_r(uint32_t x)
16 | {
17 | x ^= x >> 14 ^ x >> 28; x *= 0x32b21703;
18 | x ^= x >> 15 ^ x >> 30; x *= 0x469e0db1;
19 | x ^= x >> 11 ^ x >> 22; x *= 0x79a85073;
20 | x ^= x >> 17;
21 | return x;
22 | }
23 |
24 | struct visitor {
25 | long long prev;
26 | uint32_t k;
27 | };
28 |
29 | static int
30 | visit(int32_t k, int32_t v, void *arg)
31 | {
32 | struct visitor *d = arg;
33 |
34 | if (k < d->prev) {
35 | printf("FAIL %ld < %ld\n", (long)k, (long)d->prev);
36 | return 1;
37 | }
38 |
39 | long i = triple32_r(k)^d->k;
40 | int expect = 1 + i%1000;
41 | if (v != expect) {
42 | printf("FAIL %ld != %d (visit)\n", (long)v, expect);
43 | return 1;
44 | }
45 |
46 | d->prev = k;
47 | return 0;
48 | }
49 |
50 | int
51 | main(void)
52 | {
53 | struct int32trie t[] = {{0, 0, 0}};
54 |
55 | for (int j = 0; j < 16; j++) {
56 | long n = 1L << (j + 6);
57 | uint32_t k = triple32(-n);
58 |
59 | for (long i = 0; i < n; i++) {
60 | int32trie_put(t, triple32(i^k), 1 + i%1000);
61 | }
62 |
63 | struct visitor d = {-2147483648LL, k};
64 | if (int32trie_visit(t, visit, &d)) {
65 | return 1;
66 | }
67 |
68 | for (long i = 0; i < n; i++) {
69 | int expect = 1 + i%1000;
70 | if (int32trie_get(t, triple32(i^k)) != expect) {
71 | printf("FAIL %08lx != %d\n", (long)triple32(i), expect);
72 | int32trie_reset(t);
73 | return 1;
74 | }
75 | }
76 |
77 | for (long i = n; i < n*2; i++) {
78 | if (int32trie_get(t, triple32(i))) {
79 | printf("FAIL %08lx != 0\n", (long)triple32(i));
80 | int32trie_reset(t);
81 | return 1;
82 | }
83 | }
84 |
85 | double mb = t->len * sizeof(t->nodes[0]) / 1048576.0;
86 | printf("trie %d\tnodes=%ld\tsize=%.3fMiB\n", j, n, mb);
87 | int32trie_reset(t);
88 | }
89 | puts("PASS");
90 | return 0;
91 | }
92 |
--------------------------------------------------------------------------------
/iseven/README.md:
--------------------------------------------------------------------------------
1 | # An "is even" state machine
2 |
3 | A state machine accepting one byte at a time to determine if a string
4 | contains an even or odd integer (or neither). The initial state is zero.
5 | Input is terminated with a zero byte, rendering a final result. Leading
6 | zeros are invalid except for zero itself, and no whitespace is accepted. A
7 | leading + or - sign is valid.
8 |
9 | ```c
10 | // Returns the next state for most non-zero bytes, or the final result
11 | // for a terminating zero byte. A result of -1 is an error (invalid
12 | // input), 0 means odd, and 1 means even. Any other return value is a
13 | // state (always positive).
14 | int iseven(int state, int c);
15 | ```
16 |
17 | 
18 |
19 | Similar regex: `^[-+]?([1-9][0-9]*)?[0248]$`
20 |
--------------------------------------------------------------------------------
/iseven/iseven.dot:
--------------------------------------------------------------------------------
1 | digraph {
2 | graph [fontname="sans-serif" rankdir=LR];
3 | node [fontname="sans-serif" shape=circle fontsize=20];
4 | edge [fontname="monospace" arrowsize=0.65 fontsize=16];
5 |
6 | s0 [label="s₀" shape=doublecircle];
7 | s2 [label="s₂"];
8 | s3 [label="s₃"];
9 | s4 [label="s₄"];
10 | s5 [label="s₅"];
11 | T [shape=doublecircle];
12 | F [shape=doublecircle];
13 |
14 | s0->s2 [label="0"];
15 | s0->s3 [label="\n2468"];
16 | s0->s4 [label="\n13579"];
17 | s0->s5 [label="\n+-"];
18 |
19 | s2->T [label="EOF"];
20 |
21 | s3->T [label="\nEOF"];
22 | s3->s3 [label="\n02468"];
23 | s3->s4 [label="\n13579"];
24 |
25 | s4->F [label="EOF"];
26 | s4->s3 [label="\n02468"];
27 | s4->s4 [label="\n13579"];
28 |
29 | s5->s2 [label="\n0"];
30 | s5->s3 [label="\n2468"];
31 | s5->s4 [label="\n13579"];
32 | }
33 |
--------------------------------------------------------------------------------
/iseven/iseven.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/iseven/iseven.png
--------------------------------------------------------------------------------
/libwinsane/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CROSS = x86_64-w64-mingw32-
3 | LD = $(CROSS)ld
4 | CC = $(CROSS)gcc
5 | WINDRES = $(CROSS)windres
6 | CFLAGS = -Os -g -Wall -Wextra
7 |
8 | libwinsane.o: init.o manifest.o
9 | $(LD) -relocatable -o $@ init.o manifest.o
10 |
11 | manifest.o: manifest.rc utf8.xml
12 | $(WINDRES) -o $@ manifest.rc
13 |
14 | clean:
15 | rm -f init.o manifest.o libwinsane.o
16 |
--------------------------------------------------------------------------------
/libwinsane/README.md:
--------------------------------------------------------------------------------
1 | # libwinsane: Quick-and-easy sanity for Windows applications
2 |
3 | Build `libwinsane.o` using `make`, then link it into any program to
4 | provide some sanity on Windows. Specifically:
5 |
6 | * All command line arguments (i.e. `argv`) will be encoded with UTF-8.
7 |
8 | * Functions accepting paths (i.e. `fopen`) will support UTF-8, such as
9 | file names passed as command line arguments.
10 |
11 | * All environment variables (i.e. `getenv`) will be encoded with UTF-8.
12 |
13 | * The Windows console will correctly decode the program's UTF-8 output.
14 |
15 | * `stdin` and `stdout` will be in binary mode, no text translation.
16 |
17 | In other words, the C runtime will behave almost as it does on every other
18 | platform. Windows may not need to be a special support case, either for
19 | Unicode or binary handling. Many command line programs not designed for
20 | Windows will simply work correctly when linked with libwinsane.
21 |
22 | Caveat: Despite every indication otherwise, Windows does [not yet support
23 | reading UTF-8 input from a console][in], so programs still cannot accept
24 | UTF-8 keyboard input. For now that continues remaining a special case
25 | requiring [special handling][pw].
26 |
27 | ## FAQ
28 |
29 | Q: Why an object file and not a static library?
30 |
31 | A: Constructors and resources do not work in static libraries because
32 | they're not referenced by the program.
33 |
34 | * * *
35 |
36 | Q: Why not a shared library?
37 |
38 | A: The embedded resource won't work from a shared library.
39 |
40 | * * *
41 |
42 | Q: Why not a C source file, even if it means inline assembly, that users
43 | can `#include`?
44 |
45 | A: Only `windres` can produce the specific, 32-bit static relocation used
46 | to build the resource `.rsrc` tree. Trust me, I tried!
47 |
48 |
49 | [in]: https://github.com/microsoft/terminal/issues/4551#issuecomment-585487802
50 | [pw]: https://nullprogram.com/blog/2020/05/04/
51 |
--------------------------------------------------------------------------------
/libwinsane/init.c:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #include
3 | #include
4 | #include
5 |
6 | __attribute__((constructor))
7 | void
8 | winsane_init(void)
9 | {
10 | _setmode(0, _O_BINARY);
11 | _setmode(1, _O_BINARY);
12 | SetConsoleCP(CP_UTF8); // maybe will work someday
13 | SetConsoleOutputCP(CP_UTF8);
14 | }
15 |
--------------------------------------------------------------------------------
/libwinsane/manifest.rc:
--------------------------------------------------------------------------------
1 | #include
2 | CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "utf8.xml"
3 |
--------------------------------------------------------------------------------
/libwinsane/utf8.xml:
--------------------------------------------------------------------------------
1 | UTF-8
--------------------------------------------------------------------------------
/marvin32/README.md:
--------------------------------------------------------------------------------
1 | # Marvin32 hash function
2 |
3 | A lean C implementation of the [patented][] non-cryptographic, keyed hash
4 | function Marvin32 as used in the .NET implementation of C#.
5 |
6 | ```c
7 | uint32_t marvin32(const void *buf, size_t len, uint64_t key);
8 | ```
9 |
10 | [patented]: https://patents.google.com/patent/US20130262421
11 |
--------------------------------------------------------------------------------
/misc/abacaba.c:
--------------------------------------------------------------------------------
1 | /* ABACABA state machine
2 | * Ref: https://redd.it/njxq95
3 | * This is free and unencumbered software released into the public domain.
4 | */
5 |
6 | /* Compute the next ABACABA state. The initial state is zero, and halt
7 | * is indicated by returning to the zero state.
8 | *
9 | * The state is a 31-bit quantity where bits 0-24 are a bitstack, bits
10 | * 25-29 are the stack size, and bit 30 is the recursion direction.
11 | *
12 | * D IIIII SSSSSSSSSSSSSSSSSSSSSSSSS
13 | */
14 | static long
15 | abacaba(long s)
16 | {
17 | for (;;) {
18 | long stack = s & 0x1ffffff;
19 | int i = s>>25 & 0x1f;
20 | int descending = s>>30;
21 | int middle = s>>i & 1;
22 |
23 | if (i == 25) {
24 | // bottom out, descend to the parent
25 | return 1L<<30 | (i-1L)<<25 | stack;
26 | } else if (descending && !middle) {
27 | // output "middle" character, ascend into right branch
28 | return (i+1L)<<25 | stack | 1L<>25 & 0x1f) + (s>>30 ? -1: +1);
45 | }
46 |
47 | /* Usage example */
48 | #include
49 |
50 | int
51 | main(void)
52 | {
53 | for (long state = abacaba(0); state; state = abacaba(state)) {
54 | putchar(abacaba_letter(state));
55 | }
56 | putchar('\n');
57 | }
58 |
--------------------------------------------------------------------------------
/misc/abacaba.go:
--------------------------------------------------------------------------------
1 | // ABACABA state machine
2 | // Ref: https://redd.it/njxq95
3 | // This is free and unencumbered software released into the public domain.
4 | package main
5 |
6 | import (
7 | "bufio"
8 | "os"
9 | )
10 |
11 | type State uint32
12 |
13 | // Iterate the state matching, returning the next letter of the ABACABA
14 | // sequence, the next state, and whether or not the machine has halted.
15 | // The initial state is zero.
16 | //
17 | // The state is a 32-bit quantity where bits 0-25 are a bitstack, bits
18 | // 26-30 are the stack size, and bit 31 is the recursion direction.
19 | //
20 | // D IIIII SSSSSSSSSSSSSSSSSSSSSSSSSS
21 | func (s State) Next() (rune, State, bool) {
22 | for {
23 | stack := s & 0x3ffffff
24 | i := s >> 26 & 0x1f
25 | descending := s>>31 == 1
26 | middle := s>>i&1 == 1
27 |
28 | if i == 25 {
29 | // Bottom out, descend back to the parent
30 | return 'a', State(1)<<31 | (i-1)<<26 | stack, false
31 | } else if descending && !middle {
32 | // Output "middle" character, ascend into right branch
33 | return 'z' - rune(i), (i+1)<<26 | stack | State(1)< 0
17 | self._n = n - 1
18 | self._count = 0
19 | self._event = asyncio.Event()
20 |
21 | async def wait(self):
22 | """Wait until all other tasks have also waited."""
23 | if self._count == self._n:
24 | self._count = 0
25 | self._event.set()
26 | self._event.clear()
27 | await asyncio.sleep(0) # yield
28 | else:
29 | self._count += 1
30 | await self._event.wait()
31 |
32 | import random
33 | import unittest
34 |
35 | def _reorder(n):
36 | order = [i for i in range(n)]
37 | while True:
38 | random.shuffle(order)
39 | for i in order:
40 | yield i
41 |
42 | async def _test_barrier(self, n):
43 | barrier = Barrier(n)
44 | target = (1 << n) - 1
45 | state = 0
46 | sleeps = _reorder(n)
47 |
48 | async def worker(i):
49 | nonlocal state
50 | for _ in range(256):
51 | # Shuffle the task schedule order
52 | for _ in range(next(sleeps)):
53 | await asyncio.sleep(0)
54 |
55 | state |= 1 << i
56 | await barrier.wait()
57 |
58 | # Check that all tasks are in the same phase
59 | self.assertEqual(state, target)
60 | await barrier.wait()
61 |
62 | state ^= 1 << i
63 | await barrier.wait()
64 |
65 | # Check that all tasks are in the same phase
66 | self.assertEqual(state, 0)
67 | await barrier.wait()
68 |
69 | await asyncio.gather(*[asyncio.create_task(worker(i)) for i in range(n)])
70 |
71 | class _BarrierTestCase(unittest.TestCase):
72 | def test_barrier(self):
73 | for n in range(16):
74 | asyncio.run(_test_barrier(self, n + 1))
75 |
76 | if __name__ == '__main__':
77 | unittest.main()
78 |
--------------------------------------------------------------------------------
/misc/chacha-test.lua:
--------------------------------------------------------------------------------
1 | local chacha = require 'chacha'
2 |
3 | local key = string.char(
4 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
6 | )
7 | local iv = string.char(0, 0, 0, 0, 0, 0, 0, 0)
8 | local expect0 = string.char(
9 | 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
10 | 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
11 | 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
12 | 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
13 | 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
14 | 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
15 | 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
16 | 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
17 | )
18 | local expect1 = string.char(
19 | 0x9f, 0x07, 0xe7, 0xbe, 0x55, 0x51, 0x38, 0x7a,
20 | 0x98, 0xba, 0x97, 0x7c, 0x73, 0x2d, 0x08, 0x0d,
21 | 0xcb, 0x0f, 0x29, 0xa0, 0x48, 0xe3, 0x65, 0x69,
22 | 0x12, 0xc6, 0x53, 0x3e, 0x32, 0xee, 0x7a, 0xed,
23 | 0x29, 0xb7, 0x21, 0x76, 0x9c, 0xe6, 0x4e, 0x43,
24 | 0xd5, 0x71, 0x33, 0xb0, 0x74, 0xd8, 0x39, 0xd5,
25 | 0x31, 0xed, 0x1f, 0x28, 0x51, 0x0a, 0xfb, 0x45,
26 | 0xac, 0xe1, 0x0a, 0x1f, 0x4b, 0x79, 0x4d, 0x6f
27 | )
28 |
29 | local function show(block)
30 | for i = 1, #block do
31 | local byte = string.byte(block, i)
32 | local sep = string.byte('\n ', i % 16 + 1)
33 | local hex = string.format('%02x%c', byte, sep)
34 | io.output():write(hex)
35 | end
36 | end
37 |
38 | local state = chacha.new(key, iv)
39 | local out0 = chacha.generate(state)
40 | local out1 = chacha.generate(state)
41 | local fail = false
42 |
43 | if out0 ~= expect0 then
44 | print('Output 0:')
45 | show(out0)
46 | print('Expect 0:')
47 | show(expect0)
48 | fail = true
49 | end
50 | if out1 ~= expect1 then
51 | print('Output 1:')
52 | show(out1)
53 | print('Expect 1:')
54 | show(expect1)
55 | fail = true
56 | end
57 |
58 | if fail then
59 | print('FAIL')
60 | os.exit(1)
61 | else
62 | print('PASS')
63 | os.exit(0)
64 | end
65 |
--------------------------------------------------------------------------------
/misc/chacha.lua:
--------------------------------------------------------------------------------
1 | -- chacha.lua -- ChaCha stream cipher for Lua 5.3
2 | -- Supports both 32-bit and 64-bit integers
3 | --
4 | -- state = chacha.new(key, iv [, rounds])
5 | -- block = chacha.generate(state)
6 | --
7 | -- This is free and unencumbered software released into the public domain.
8 | local chacha = {}
9 |
10 | function chacha.new(key, iv, rounds)
11 | local s = {workspace = {}, rounds = rounds or 20}
12 | s[1] = 0x61707865 -- "expand 32-byte k"
13 | s[2] = 0x3320646e --
14 | s[3] = 0x79622d32 --
15 | s[4] = 0x6b206574 --
16 | s[5], s[6], s[7], s[8], s[9], s[10], s[11], s[12] =
17 | string.unpack('> (32 - n))) & 0xffffffff
26 | end
27 |
28 | local function quarterround(x, a, b, c, d)
29 | x[a] = (x[a] + x[b]) & 0xffffffff
30 | x[d] = rotate(x[d] ~ x[a], 16)
31 | x[c] = (x[c] + x[d]) & 0xffffffff
32 | x[b] = rotate(x[b] ~ x[c], 12)
33 | x[a] = (x[a] + x[b]) & 0xffffffff
34 | x[d] = rotate(x[d] ~ x[a], 8)
35 | x[c] = (x[c] + x[d]) & 0xffffffff
36 | x[b] = rotate(x[b] ~ x[c], 7)
37 | end
38 |
39 | function chacha.generate(s)
40 | local x = s.workspace
41 | for i = 1, 16 do
42 | x[i] = s[i]
43 | end
44 | for _ = 1, s.rounds, 2 do
45 | quarterround(x, 1, 5, 9, 13)
46 | quarterround(x, 2, 6, 10, 14)
47 | quarterround(x, 3, 7, 11, 15)
48 | quarterround(x, 4, 8, 12, 16)
49 | quarterround(x, 1, 6, 11, 16)
50 | quarterround(x, 2, 7, 12, 13)
51 | quarterround(x, 3, 8, 9, 14)
52 | quarterround(x, 4, 5, 10, 15)
53 | end
54 | for i = 1, 16 do
55 | x[i] = (x[i] + s[i]) & 0xffffffff
56 | end
57 | s[13] = (s[13] + 1) & 0xffffffff
58 | if s[13] == 0 then
59 | s[14] = s[14] + 1
60 | end
61 | return string.pack('
17 |
18 | #define D6GEN_INIT(seed64) {(seed64), 0, 0}
19 | struct d6gen {
20 | uint64_t s;
21 | uint32_t r;
22 | int i;
23 | };
24 |
25 | /* Generate a single high-quality 6-sided die roll (1-6). */
26 | static int
27 | d6gen(struct d6gen *g)
28 | {
29 | static const char t[] = {5, 5, 0, 1, 0, 4, 0, 1, 5, 5, 0, 4};
30 | for (;;) {
31 | if (!g->i) {
32 | /* 64-bit PCG producing a 32-bit result */
33 | g->s = g->s*0x7c3c3267d015ceb5 + 1;
34 | g->r = g->s >> 32;
35 | g->r ^= g->r >> 16;
36 | g->r *= 0x60857ba9;
37 | g->r ^= g->r >> 16;
38 | g->i = sizeof(t) / sizeof(t[0]);
39 | }
40 |
41 | /* Determine valid range for this order of magnitude */
42 | int excess = t[--g->i];
43 | if (g->r < excess) {
44 | /* Out of range: discard and get a fresh 32-bit number */
45 | g->i = 0;
46 | } else {
47 | /* In range: trim unwanted excess and compute roll */
48 | g->r -= excess;
49 | int d = 1 + g->r%6;
50 | g->r /= 6;
51 | return d;
52 | }
53 | }
54 | }
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/misc/dumpdata.s:
--------------------------------------------------------------------------------
1 | ;; Linux x86-64 "hello world" command
2 | ;;
3 | ;; $ nasm dumpdata.s
4 | ;; $ echo hello world >>dumpdata
5 | ;; $ chmod +x dumpdata
6 | ;;
7 | ;; Outputs whatever data has been concatenated to the program, though its
8 | ;; size must be provided at assembly-time (DATA_SIZE).
9 | ;;
10 | ;; This is free and unencumbered software released into the public domain.
11 |
12 | bits 64
13 |
14 | %define ET_EXEC 2
15 | %define EM_X86_64 62
16 | %define PT_LOAD 1
17 | %define PF_X 1
18 | %define PF_R 4
19 | %define SYS_write 1
20 | %define SYS_exit 60
21 |
22 | %define VADDR 0x0000000040000000
23 | %define DATA_VADDR 0x0000000080000000
24 | %define DATA_SIZE 12
25 |
26 | db 0x7f, "ELF", 0x02, 0x01, 0x01, 0x00 ; e_ident
27 | dq 0 ; "
28 | dw ET_EXEC ; e_type
29 | dw EM_X86_64 ; e_machine
30 | dd 1 ; e_version
31 | dq VADDR + _start ; e_entry
32 | dq 64 ; e_phoff
33 | dq 0 ; e_shoff
34 | dd 0 ; e_flags
35 | dw 64 ; e_ehsize
36 | dw 56 ; e_phentsize
37 | dw 2 ; e_phnum
38 | dw 64 ; e_shentsize
39 | dw 0 ; e_shnum
40 | dw 0 ; e_shstrndx
41 |
42 | ;; like .text
43 | dd PT_LOAD ; p_type
44 | dd PF_X|PF_R ; p_flags
45 | dq _start ; p_offset
46 | dq _start + VADDR ; p_vaddr
47 | dq 0 ; p_paddr
48 | dq _end - _start ; p_filesz
49 | dq _end - _start ; p_memsz
50 | dq 0 ; p_align
51 |
52 | ;; like .data
53 | dd PT_LOAD ; p_type
54 | dd PF_R ; p_flags
55 | dq _end ; p_offset
56 | dq _end + DATA_VADDR ; p_vaddr
57 | dq 0 ; p_paddr
58 | dq DATA_SIZE ; p_filesz
59 | dq DATA_SIZE ; p_memsz
60 | dq 0 ; p_align
61 |
62 | _start:
63 | mov edi, 1
64 | mov rsi, DATA_VADDR+_end
65 | mov rdx, DATA_SIZE
66 | mov eax, SYS_write
67 | syscall
68 | cmp rax, DATA_SIZE
69 | setne cl
70 | mov edi, ecx
71 | mov eax, SYS_exit
72 | syscall
73 | _end:
74 |
--------------------------------------------------------------------------------
/misc/fivefive.c:
--------------------------------------------------------------------------------
1 | // Five five-letter words with 25 unique letters
2 | // $ cc -fopenmp -O3 -o fivefive fivefive.c
3 | // $ ./fivefive
6 | #include
7 | #include
8 |
9 | #define MAX (1<<16)
10 |
11 | int main(void)
12 | {
13 | char word[8];
14 | int nwords = 0;
15 | static int32_t sets[MAX];
16 | static char words[MAX][5];
17 | static uint32_t seen[1<<21] = {0};
18 |
19 | while (nwords>5] & ((uint32_t)1 << (c&31)))) {
31 | seen[c>>5] |= (uint32_t)1 << (c&31);
32 | sets[nwords] = c;
33 | memcpy(words[nwords++], word, 5);
34 | }
35 | }
36 |
37 | #pragma omp parallel for schedule(dynamic)
38 | for (int i = 0; i < nwords; i++) {
39 | int n = 0;
40 | int32_t c = 0;
41 | int stack[5] = {i};
42 |
43 | for (;;) {
44 | if (n == 5) {
45 | // Solution found
46 | #pragma omp critical
47 | printf("%.5s %.5s %.5s %.5s %.5s\n",
48 | words[stack[0]], words[stack[1]],
49 | words[stack[2]], words[stack[3]],
50 | words[stack[4]]);
51 | c ^= sets[stack[--n]++];
52 |
53 | } else if (stack[n] == nwords) {
54 | // This cursor is exhausted, pop
55 | if (!--n) {
56 | break; // bottomed out
57 | }
58 | c ^= sets[stack[n]];
59 | stack[n]++;
60 |
61 | } else if ((c & sets[stack[n]])) {
62 | // This word is invalid, advance
63 | stack[n]++;
64 |
65 | } else {
66 | // Keep this word and push
67 | c |= sets[stack[n]];
68 | if (++n < 5) {
69 | stack[n] = stack[n-1]+1;
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/misc/glitch.c:
--------------------------------------------------------------------------------
1 | /* Glitch video generator
2 | * $ cc -O3 -o glitch glitch.c
3 | * $ convert in.png ppm:- | ./glitch | x264 --fps 6 -o out.mp4 /dev/stdin
4 | */
5 | #include
6 | #include
7 | #include
8 |
9 | #define VSHIFT 12
10 | #define HSHIFT 30
11 | #define HRATE 30
12 | #define NFRAMES 60
13 |
14 | #define RANGE(s, min, max) (rnd(s) % ((max) - (min)) + (min))
15 | static unsigned long
16 | rnd(unsigned long long *s)
17 | {
18 | *s = *s*0x9acb883ba7dad0ad + 1;
19 | return *s>>32 & 0xffffffff;
20 | }
21 |
22 | int
23 | main(void)
24 | {
25 | #ifdef _WIN32
26 | /* Set stdin/stdout to binary mode. */
27 | int _setmode(int, int);
28 | _setmode(0, 0x8000);
29 | _setmode(1, 0x8000);
30 | #endif
31 |
32 | int w, h;
33 | scanf("P6%d%d 255%*c", &w, &h);
34 | unsigned char *bufi = malloc(w*3L*h*2);
35 | unsigned char *bufo = bufi + w*3L*h;
36 | fread(bufi, w*3, h, stdin);
37 | unsigned long long s = time(0);
38 |
39 | for (int i = 0; i < NFRAMES; i++) {
40 | int rshift = h + RANGE(&s, -VSHIFT, +VSHIFT);
41 | int gshift = h + RANGE(&s, -VSHIFT, +VSHIFT);
42 | int bshift = h + RANGE(&s, -VSHIFT, +VSHIFT);
43 | for (int y = 0; y < h; y++) {
44 | for (int x = 0; x < w; x++) {
45 | bufo[y*w*3 + x*3 + 0] = bufi[(y+rshift)%h*w*3 + x*3 + 0];
46 | bufo[y*w*3 + x*3 + 1] = bufi[(y+gshift)%h*w*3 + x*3 + 1];
47 | bufo[y*w*3 + x*3 + 2] = bufi[(y+bshift)%h*w*3 + x*3 + 2];
48 | }
49 | }
50 |
51 | for (int y = 0; y < h; y++) {
52 | if (y == 0 || rnd(&s) % HRATE == 0) {
53 | rshift = RANGE(&s, -HSHIFT, +HSHIFT);
54 | gshift = RANGE(&s, -HSHIFT, +HSHIFT);
55 | bshift = RANGE(&s, -HSHIFT, +HSHIFT);
56 | }
57 | for (int x = 0; x < w; x++) {
58 | int ri = y*w*3 + (x+rshift+w)%w*3 + 0, rj = y*w*3 + x*3 + 0;
59 | int gi = y*w*3 + (x+gshift+w)%w*3 + 1, gj = y*w*3 + x*3 + 1;
60 | int bi = y*w*3 + (x+bshift+w)%w*3 + 2, bj = y*w*3 + x*3 + 2;
61 | bufo[ri < rj ? ri : rj] = bufo[ri < rj ? rj : ri];
62 | bufo[gi < gj ? gi : gj] = bufo[gi < gj ? gj : gi];
63 | bufo[bi < bj ? bi : bj] = bufo[bi < bj ? bj : bi];
64 | }
65 | }
66 |
67 | printf("P6\n%d %d\n255\n", w, h);
68 | fwrite(rnd(&s)&3 ? bufi : bufo, w*3, h, stdout);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/misc/int32len.c:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 |
3 | // Return the printed decimal length for any signed 32-bit integer.
4 | int int32len(long n)
5 | {
6 | unsigned long b = n < 0;
7 | unsigned long u = (n ^ -b) + b;
8 | return (u >= 0x0000000a) + (u >= 0x00000064) + (u >= 0x000003e8) +
9 | (u >= 0x00002710) + (u >= 0x000186a0) + (u >= 0x000f4240) +
10 | (u >= 0x00989680) + (u >= 0x05f5e100) + (u >= 0x3b9aca00) + b + 1;
11 | }
12 |
--------------------------------------------------------------------------------
/misc/interpenv.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | // Interpolate environment variables from the source string into the
4 | // destination. Returns the length including null terinator, or zero if
5 | // the destination is too short. Undefined variables are treated as
6 | // empty, and $$ produces a single $. A variable is composed of the
7 | // character set [0-9A-Z_a-z].
8 | size_t interpenv(char *dst, size_t len, char *src, char **env)
9 | {
10 | if (!len) {
11 | return 0;
12 | }
13 |
14 | char *c = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
15 | char *d = dst;
16 | char *e = dst + len - 1; // reserve byte for terminator
17 | while (*src) {
18 | if (*src == '$') {
19 | size_t varlen = strspn(++src, c);
20 | if (!varlen) {
21 | if (e == d) {
22 | return 0;
23 | }
24 | src += *src == '$'; // "$$" => "$"
25 | *d++ = '$';
26 | } else {
27 | for (char **k = env; *k; k++) {
28 | char *ke = strchr(*k, '=');
29 | size_t kn = ke ? ke-*k : 0;
30 | if (kn==varlen && !memcmp(*k, src, kn)) {
31 | size_t vn = strlen(ke+1);
32 | if (vn > (size_t)(e - d)) {
33 | return 0;
34 | }
35 | memcpy(d, ke+1, vn);
36 | d += vn;
37 | break;
38 | }
39 | }
40 | src += varlen;
41 | }
42 | }
43 |
44 | // Skip to text variable, or the end
45 | size_t clen = strcspn(src, "$");
46 | if (clen > (size_t)(e - d)) {
47 | return 0;
48 | }
49 | memcpy(d, src, clen);
50 | d += clen;
51 | src += clen;
52 | }
53 | *d++ = 0;
54 | return d - dst;
55 | }
56 |
57 |
58 | #if TEST
59 | #include
60 |
61 | int main(int argc, char **argv, char **env)
62 | {
63 | char buf[256];
64 | for (int i = 1; i < argc; i++) {
65 | size_t len = interpenv(buf, sizeof(buf), argv[i], env);
66 | if (len) {
67 | buf[len-1] = '\n';
68 | fwrite(buf, len, 1, stdout);
69 | }
70 | }
71 | }
72 | #endif
73 |
--------------------------------------------------------------------------------
/misc/list-github.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | # List each of the clone URLs of a given user's public, non-fork repositories.
4 | # Example usage:
5 | # $ sh list-github.sh skeeto | xargs -n1 git clone
6 |
7 | if [ -z "$1" ]; then
8 | echo 'usage: list-github.sh '
9 | exit 1
10 | fi
11 |
12 | pagenum=1
13 | while true; do
14 | repos="$(curl -s "https://api.github.com/users/$1/repos?page=$pagenum&per_page=100" |
15 | jq -r '.[] | select(.fork | not) | .clone_url')"
16 | if [ -z "$repos" ]; then
17 | break
18 | fi
19 | printf '%s\n' "$repos"
20 | pagenum=$((pagenum+1))
21 | done
22 |
--------------------------------------------------------------------------------
/misc/mandelbrot.f90:
--------------------------------------------------------------------------------
1 | ! Mandelbrot set renderer in Fortran 2003
2 | ! $ gfortran -std=f2003 -O3 -ffast-math mandelbrot.f90
3 | ! $ ./a.out >mandelbrot.pgm
4 | program mandelbrot
5 | implicit none
6 |
7 | real, parameter :: xmin = -2.5, xmax = +1.5
8 | real, parameter :: ymin = -1.5, ymax = +1.5
9 | real, parameter :: step = 0.0025
10 | integer, parameter :: width = int((xmax - xmin) / step)
11 | integer, parameter :: height = int((ymax - ymin) / step)
12 | integer, parameter :: iterations = 255
13 |
14 | integer :: i, x, y
15 | integer, allocatable :: k(:, :)
16 | complex, allocatable :: z(:, :)
17 | complex, allocatable :: c(:, :)
18 |
19 | allocate(k(width, height))
20 | k = 0
21 | allocate(z(width, height))
22 | z = 0
23 | allocate(c(width, height))
24 | forall (x = 1:width, y = 1:height)
25 | c(x, y) = cmplx((x - 1)*step + xmin, (y - 1)*step + ymin)
26 | end forall
27 |
28 | ! Compute the Mandelbrot set
29 | do i = 1, iterations
30 | z = z**2 + c
31 | where (abs(z) < 2) k = k + 1
32 | end do
33 |
34 | ! Render Netpbm grayscale image
35 | print '(a/2i10/i4)', 'P2', width, height, iterations
36 | print *, int(((real(k) / iterations) ** 0.5) * iterations)
37 | end program
38 |
--------------------------------------------------------------------------------
/misc/matchn.c:
--------------------------------------------------------------------------------
1 | // State machine matching words within a length range
2 | // $ cc -o matchn matchn.c
3 | // $ ./matchn
6 |
7 | // Matches words between MIN and MAX characters beginning with a letter.
8 | // If C completes a match, the buffer will contain the match, and the
9 | // match length is returned. Otherise it returns a non-positive next
10 | // state. Initialize the state to any non-negative value, including a
11 | // previously-returned length. A zero C indicates end of input.
12 | static int matchn(int state, char *match, int min, int max, unsigned char c)
13 | {
14 | static const uint32_t alpha[8] = {0x0000,0x00000000,0x07fffffe,0x07fffffe};
15 | static const uint32_t alnum[8] = {0x0000,0x03ff0000,0x07fffffe,0x07fffffe};
16 | static const uint32_t split[8] = {0x3e01,0xfc00ffff,0xf8000001,0x78000001};
17 | int i = c >> 5;
18 | uint32_t b = (uint32_t)1 << (c&31);
19 | if (state == -1) { // middle of a non-match
20 | return split[i]&b ? 0 : -1;
21 | } else if (state >= 0) { // may begin a match
22 | if (alpha[i]&b) {
23 | match[0] = c;
24 | return -2; // begin matching
25 | }
26 | return split[i]&b ? 0 : -1;
27 | } else if (split[i]&b) { // end of a match
28 | return (-state-1)>=min ? -state-1 : 0;
29 | } else if ((-state-1) >= max) { // too long, reject
30 | return -1;
31 | } else if (alnum[i]&b) { // keep matching
32 | match[-state-1] = c;
33 | return state - 1;
34 | }
35 | return -1;
36 | }
37 |
38 |
39 | // Demo / Test : prints all words 3 to 7 characters in length
40 | #include
41 |
42 | int main(void)
43 | {
44 | char buf[8];
45 | int c, state=0, min=3, max=7;
46 | do {
47 | c = getchar();
48 | state = matchn(state, buf, min, max, c==EOF?0:c);
49 | if (state > 0) {
50 | buf[state] = '\n';
51 | fwrite(buf, state+1, 1, stdout);
52 | }
53 | } while (c != EOF);
54 | fflush(stdout);
55 | return ferror(stdout) || ferror(stdin);
56 | }
57 |
--------------------------------------------------------------------------------
/misc/mcpi.c:
--------------------------------------------------------------------------------
1 | // Monte Carlo method pi estimator, multi-threaded and SIMD
2 | // $ cc -Ofast -fopenmp -march=x86-64-v3 -o mcpi mcpi.c -lm
3 | // $ cl /O2 /fp:fast /openmp /arch:AVX2 mcpi.c
4 | //
5 | // Runs four truncated LCGs side-by-side in parallel SIMD, with each thread
6 | // running independent trials, all merged for the final result. Reports the
7 | // total number of trials, the trial rate (benchmark), and the pi estimate.
8 | //
9 | // This is free and unencumbered software released into the public domain.
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #define M 0x3243f6a8885a308dU
16 | #define D 9223372036854775808.
17 | #define N0 (1L << 12)
18 | #define N1 (1L << 23)
19 |
20 | int main(void)
21 | {
22 | long n; // for MSVC OpenMP
23 | double total = 0.0;
24 | clock_t start = clock();
25 | uint64_t seed = time(0);
26 |
27 | seed *= 1111111111111111111;
28 | seed ^= seed >> 33;
29 | #pragma omp parallel for reduction(+:total)
30 | for (n = 0; n < N0; n++) {
31 | // Expect e and s to be AVX registers
32 | double e[4], r = 0.0;
33 | uint64_t s[4] = {seed+n*4+0, seed+n*4+1, seed+n*4+2, seed+n*4+3};
34 | for (long i = 0; i < N1; i++) {
35 | s[0] = s[0]*M + 7; e[0] = (s[0]>>1)/D; r += sqrt(1 - e[0]*e[0]);
36 | s[1] = s[1]*M + 5; e[1] = (s[1]>>1)/D; r += sqrt(1 - e[1]*e[1]);
37 | s[2] = s[2]*M + 3; e[2] = (s[2]>>1)/D; r += sqrt(1 - e[2]*e[2]);
38 | s[3] = s[3]*M + 1; e[3] = (s[3]>>1)/D; r += sqrt(1 - e[3]*e[3]);
39 | }
40 | total += r / N1 / N0;
41 | }
42 |
43 | double elapsed = (double)(clock() - start)/CLOCKS_PER_SEC;
44 | long rate = 4.0*N0*N1 / elapsed / 1e6;
45 | printf("%lld trials, %ldMt/s, %.17g\n", 4LL*N0*N1, rate, total);
46 | }
47 |
--------------------------------------------------------------------------------
/misc/msws.c:
--------------------------------------------------------------------------------
1 | /* Middle Square Weyl Sequence (PRNG)
2 | * Generator state may be seeded to any value.
3 | * Ref: https://arxiv.org/abs/1704.00358
4 | * This is free and unencumbered software released into the public domain.
5 | */
6 | #include
7 |
8 | static uint32_t
9 | msws32(uint64_t s[2])
10 | {
11 | s[0] *= s[0];
12 | s[1] += 0xdc6b2b45361498ad;
13 | s[0] += s[1];
14 | s[0] = s[0]<<32 | s[0]>>32;
15 | return s[0];
16 | }
17 |
18 | static uint64_t
19 | msws64(uint64_t s[4])
20 | {
21 | unsigned __int128 x = (unsigned __int128)s[1]<<64 | s[0];
22 | unsigned __int128 w = (unsigned __int128)s[3]<<64 | s[2];
23 | x *= x;
24 | w += (unsigned __int128)0x918fba1eff8e67e1<<64 | 0x8367589d496e8afd;
25 | x += w;
26 | s[0] = x >> 64; s[1] = x >> 0;
27 | s[2] = w >> 0; s[3] = w >> 64;
28 | return s[0];
29 | }
30 |
--------------------------------------------------------------------------------
/misc/openbsd.py:
--------------------------------------------------------------------------------
1 | # Python interface to pledge(2) and unveil(2)
2 | # Ref: https://nullprogram.com/blog/2021/09/15/
3 | # This is free and unencumbered software released into the public domain.
4 | import ctypes
5 | import os
6 | from typing import Optional, Union
7 |
8 | _pledge = None
9 | try:
10 | _pledge = ctypes.CDLL(None, use_errno=True).pledge
11 | _pledge.restype = ctypes.c_int
12 | _pledge.argtypes = ctypes.c_char_p, ctypes.c_char_p
13 | except Exception:
14 | _pledge = None
15 |
16 | def pledge(promises: Optional[str], execpromises: Optional[str]):
17 | if not _pledge:
18 | return # unimplemented
19 |
20 | r = _pledge(None if promises is None else promises.encode(),
21 | None if execpromises is None else execpromises.encode())
22 | if r == -1:
23 | errno = ctypes.get_errno()
24 | raise OSError(errno, os.strerror(errno))
25 |
26 | _unveil = None
27 | try:
28 | _unveil = ctypes.CDLL(None, use_errno=True).unveil
29 | _unveil.restype = ctypes.c_int
30 | _unveil.argtypes = ctypes.c_char_p, ctypes.c_char_p
31 | except Exception:
32 | _unveil = None
33 |
34 | def unveil(path: Union[str, bytes, None], permissions: Optional[str]):
35 | if not _unveil:
36 | return # unimplemented
37 |
38 | r = _unveil(path.encode() if isinstance(path, str) else path,
39 | None if permissions is None else permissions.encode())
40 | if r == -1:
41 | errno = ctypes.get_errno()
42 | raise OSError(errno, os.strerror(errno))
43 |
--------------------------------------------------------------------------------
/misc/pi.c:
--------------------------------------------------------------------------------
1 | /* Monte Carlo Method pi estimate via 128-bit integer math
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define NTHREADS 8
10 | #define REPORT 0x10000000
11 |
12 | static uint64_t
13 | xoshiro256ss(uint64_t s[4])
14 | {
15 | uint64_t x = s[1] * 5;
16 | uint64_t r = ((x << 7) | (x >> 57)) * 9;
17 | uint64_t t = s[1] << 17;
18 | s[2] ^= s[0];
19 | s[3] ^= s[1];
20 | s[1] ^= s[2];
21 | s[0] ^= s[3];
22 | s[2] ^= t;
23 | s[3] = (s[3] << 45) | (s[3] >> 19);
24 | return r;
25 | }
26 |
27 | static uint64_t
28 | splittable64(uint64_t x)
29 | {
30 | x += 0x9e3779b97f4a7c15U; x ^= x >> 30;
31 | x *= 0xbf58476d1ce4e5b9U; x ^= x >> 27;
32 | x *= 0x94d049bb133111ebU; x ^= x >> 31;
33 | return x;
34 | }
35 |
36 | static void
37 | accum(long i)
38 | {
39 | static uint64_t inside, total;
40 | static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
41 | pthread_mutex_lock(&lock);
42 | inside += i;
43 | total += REPORT;
44 | printf("%-20.17g %16.9f %16.9f\n",
45 | inside*4.0/total, inside/1e9, total/1e9);
46 | fflush(stdout);
47 | pthread_mutex_unlock(&lock);
48 | }
49 |
50 | static void *
51 | worker(void *n)
52 | {
53 | uint64_t seed = splittable64(time(0)) + (uintptr_t)n*8;
54 | uint64_t s0[] = {
55 | splittable64(seed+0), splittable64(seed+1),
56 | splittable64(seed+2), splittable64(seed+3),
57 | };
58 | uint64_t s1[] = {
59 | splittable64(seed+4), splittable64(seed+5),
60 | splittable64(seed+6), splittable64(seed+7),
61 | };
62 | for (;;) {
63 | long inside = 0;
64 | for (long i = 0; i < REPORT; i++) {
65 | unsigned __int128 x = xoshiro256ss(s0) >> 1;
66 | unsigned __int128 y = xoshiro256ss(s1) >> 1;
67 | unsigned __int128 r = (1ULL<<63) - 1;
68 | inside += x*x + y*y <= r*r;
69 | }
70 | accum(inside);
71 | }
72 | return 0;
73 | }
74 |
75 | int
76 | main(void)
77 | {
78 | for (int i = 1; i < NTHREADS; i++) {
79 | pthread_t thr;
80 | pthread_create(&thr, 0, worker, (void *)(uintptr_t)i);
81 | }
82 | worker((void *)(uintptr_t)NTHREADS);
83 | }
84 |
--------------------------------------------------------------------------------
/misc/pi.go:
--------------------------------------------------------------------------------
1 | // Monte Carlo Method pi estimate via multi-precision integers
2 | // This is free and unencumbered software released into the public domain.
3 | package main
4 |
5 | import (
6 | "fmt"
7 | "math/big"
8 | "math/bits"
9 | "math/rand"
10 | "runtime"
11 | "sync"
12 | "time"
13 | )
14 |
15 | // Unit square size is 2^precision.
16 | const precision = 256
17 |
18 | type Pcg64x struct{ Hi, Lo uint64 }
19 |
20 | func (s *Pcg64x) Seed(seed int64) {
21 | s.Lo = 0xe1cf322879493bf1
22 | s.Hi = uint64(seed)
23 | }
24 |
25 | func (s *Pcg64x) Uint64() uint64 {
26 | const m = 0xb47d5ba190fb0fa5
27 | var c uint64
28 | c, s.Lo = bits.Mul64(s.Lo, m)
29 | s.Hi = s.Hi*m + c
30 | s.Lo, c = bits.Add64(s.Lo, 1, 0)
31 | s.Hi += c
32 | r := s.Hi
33 | r ^= r >> 32
34 | r *= m
35 | return r
36 | }
37 |
38 | func (s *Pcg64x) Int63() int64 {
39 | return int64(s.Uint64() >> 1)
40 | }
41 |
42 | type Report struct {
43 | total, inside int64
44 | sync.Mutex
45 | }
46 |
47 | func (r *Report) Accum(total, inside int64) {
48 | r.Lock()
49 | r.total += total
50 | r.inside += inside
51 | fmt.Printf("%-20v%16.9f%16.9f\n",
52 | float64(r.inside)*4/float64(r.total),
53 | float64(r.inside)/1e9,
54 | float64(r.total)/1e9)
55 | r.Unlock()
56 | }
57 |
58 | func worker(seed uint64, r, r2 *big.Int, report *Report) {
59 | var (
60 | total, inside int64
61 | src Pcg64x
62 | x, y big.Int
63 | )
64 | src.Seed(int64(seed))
65 | rng := rand.New(&src)
66 | for {
67 | x.Rand(rng, r)
68 | y.Rand(rng, r)
69 | x.Mul(&x, &x)
70 | y.Mul(&y, &y)
71 | x.Add(&x, &y)
72 | if x.Cmp(r2) <= 0 {
73 | inside++
74 | }
75 | total++
76 | if total&0x3ffff == 0 {
77 | report.Accum(total, inside)
78 | total = 0
79 | inside = 0
80 | }
81 | }
82 | }
83 |
84 | func hash64(x uint64) uint64 {
85 | x ^= x >> 30
86 | x *= 0xbf58476d1ce4e5b9
87 | x ^= x >> 27
88 | x *= 0x94d049bb133111eb
89 | x ^= x >> 31
90 | return x
91 | }
92 |
93 | func main() {
94 | var (
95 | report Report
96 | r, r2, m big.Int
97 | )
98 | r.Exp(big.NewInt(2), big.NewInt(precision-1), nil)
99 | m.Sub(&r, big.NewInt(1))
100 | r2.Mul(&m, &m)
101 |
102 | seed := hash64(uint64(time.Now().UnixNano()))
103 | procs := runtime.GOMAXPROCS(0)
104 | for i := 0; i < procs; i++ {
105 | go worker(hash64(seed+uint64(i)), &r, &r2, &report)
106 | }
107 | worker(hash64(seed+uint64(procs)), &r, &r2, &report)
108 | }
109 |
--------------------------------------------------------------------------------
/misc/pink.c:
--------------------------------------------------------------------------------
1 | // Pink noise generator
2 | // $ cc -O -o pink pink.c
3 | // $ ./pink | mpv -
4 | // This is free and unencumbered software released into the public domain.
5 | #include
6 |
7 | static int u32le(unsigned long v)
8 | {
9 | unsigned char b[] = {v, v>>8, v>>16, v>>24};
10 | return fwrite(b, 4, 1, stdout);
11 | }
12 |
13 | static int u16le(unsigned v)
14 | {
15 | unsigned char b[] = {v, v>>8};
16 | return fwrite(b, 2, 1, stdout);
17 | }
18 |
19 | int main(void)
20 | {
21 | #if _WIN32
22 | int _setmode(int, int);
23 | _setmode(1, 0x8000);
24 | #endif
25 |
26 | u32le(0x46464952); // "RIFF"
27 | u32le(0xffffffff); // file length
28 | u32le(0x45564157); // "WAVE"
29 | u32le(0x20746d66); // "fmt "
30 | u32le(16 ); // struct size
31 | u16le(1 ); // PCM
32 | u16le(2 ); // stereo
33 | u32le(44100 ); // sample rate
34 | u32le(44100*4 ); // byte rate
35 | u16le(2*2 ); // block size
36 | u16le(16 ); // bits per sample
37 | u32le(0x61746164); // "data"
38 | u32le(0xffffffff); // byte length
39 |
40 | unsigned long sum = 0;
41 | unsigned long long rng[16] = {0};
42 | for (unsigned c = 0; u16le((sum>>4) - 0x7fff); c++) {
43 | int i = __builtin_ffsl(c&0x7fff);
44 | sum -= rng[i]>>48 & 0xffff;
45 | rng[i] = rng[i]*0x3243f6a8885a308d + (i<<1) + 1;
46 | sum += rng[i]>>48 & 0xffff;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/misc/prng32.c:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 |
3 | /* Must be seeded well! */
4 | uint32_t
5 | jsf32(uint32_t s[4])
6 | {
7 | uint32_t t = s[0] - (s[1]<<27 | s[1]>>5);
8 | s[0] = s[1] ^ (s[2]<<17 | s[2]>>15);
9 | s[1] = s[2] + s[3];
10 | s[2] = s[3] + t;
11 | s[3] = s[0] + t;
12 | return s[3];
13 | }
14 |
15 | /* Must be seeded well! */
16 | uint32_t
17 | sfc32(uint32_t s[4])
18 | {
19 | uint32_t t = s[0] + s[1] + s[3];
20 | s[3] = s[3] + 1;
21 | s[0] = s[1] ^ s[1]>>9;
22 | s[1] = s[2] + (s[2] << 3);
23 | s[2] = s[2]<<21 | s[2]>>11;
24 | s[2] = s[2] + t;
25 | return t;
26 | }
27 |
28 | /* Seed to anything. This is one of my own designs, though it's slow! */
29 | uint32_t
30 | dioscuri32(uint32_t s[2])
31 | {
32 | uint32_t p = s[0], c = s[1];
33 | p ^= p >> 17; c ^= c >> 16;
34 | p *= 0x9e485565; c *= 0xa812d533;
35 | p ^= p >> 16; c ^= c >> 15;
36 | p *= 0xef1d6b47; c *= 0xb278e4ad;
37 | p ^= p >> 16; c ^= c >> 17;
38 | s[0] = p + c;
39 | s[1]++;
40 | return p ^ c;
41 | }
42 |
--------------------------------------------------------------------------------
/misc/ptr.cpp:
--------------------------------------------------------------------------------
1 | // Compressed relative pointers (experiment)
2 | // Ref: https://www.youtube.com/watch?v=Z0tsNFZLxSU
3 | // This is free and unencumbered software released into the public domain.
4 | #include
5 |
6 | #define assert(c) while (!(c)) __builtin_unreachable()
7 |
8 | template
9 | struct ptr {
10 | I rel;
11 |
12 | ptr() { rel = 0; }
13 | ptr(T *p) { *this = p; }
14 | ptr(ptr &p) { *this = p; }
15 |
16 | T *operator->()
17 | {
18 | assert(rel);
19 | return (T *)((uintptr_t)this + rel);
20 | }
21 |
22 | T &operator*()
23 | {
24 | assert(rel);
25 | return *(T *)((uintptr_t)this + rel);
26 | }
27 |
28 | operator T*()
29 | {
30 | return rel ? (T *)((uintptr_t)this + rel) : 0;
31 | }
32 |
33 | void operator=(T *p)
34 | {
35 | rel = 0;
36 | if (p) {
37 | intptr_t delta = (uintptr_t)p - (uintptr_t)this;
38 | assert((I)delta == delta);
39 | rel = (I)delta;
40 | }
41 | }
42 |
43 | void operator=(ptr &p)
44 | {
45 | rel = 0;
46 | if (p.rel) {
47 | *this = &*p;
48 | }
49 | }
50 | };
51 |
52 | template using ptr8 = ptr;
53 | template using ptr16 = ptr;
54 | template using ptr32 = ptr;
55 |
56 |
57 | // Demo/test
58 | #include
59 |
60 | struct node {
61 | ptr16 next;
62 | int16_t value;
63 | };
64 |
65 | int main()
66 | {
67 | enum { N = 8 };
68 | node nodes[N] = {};
69 | for (int16_t i = 0; i < N; i++) {
70 | nodes[i].next = nodes + i + 1;
71 | nodes[i].value = -i-1;
72 | }
73 | nodes[N-1].next = 0;
74 |
75 | // Alternative first element (test relative copying)
76 | node altfirst = nodes[0];
77 | altfirst.value = 100;
78 |
79 | for (node *p = &altfirst; p; p = p->next) {
80 | printf("%p %d\n", p, p->value);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/misc/recip.c:
--------------------------------------------------------------------------------
1 | // Shanks Reciprocals of Prime Numbers (number of figures in the period)
2 | // $ cc -fopenmp -Wl,--stack,16777216 -O3 -o recip recip.c
3 | // $ ./recip >recip.txt
4 | // Ref: https://www.youtube.com/watch?v=DmfxIhmGPP4
5 | #include
6 | #include
7 |
8 | #define MAXN 1000000
9 |
10 | static int32_t
11 | recip_len(int32_t n)
12 | {
13 | int32_t r = 1;
14 | while (r < n) r *= 10; // skip leading zeros
15 |
16 | int32_t len = 0;
17 | uint32_t seen[(MAXN*10 + 31)/32] = {0};
18 | for (; r; len++) {
19 | while (r < n) {
20 | r *= 10;
21 | len++;
22 | }
23 |
24 | if (seen[r>>5] & (1 << (r&31))) {
25 | break;
26 | }
27 | seen[r>>5] |= 1 << (r&31);
28 |
29 | r = 10*(r - n*(r / n));
30 | }
31 | return len;
32 | }
33 |
34 | int main(void)
35 | {
36 | uint32_t sieve[(MAXN + 31)/32] = {0};
37 | for (int32_t n = 2; n < MAXN; n++) {
38 | if (!(sieve[n>>5] & (UINT32_C(1) << (n&31)))) {
39 | for (int32_t i = 2*n; i < MAXN; i += n) {
40 | sieve[i>>5] |= UINT32_C(1) << (i&31);
41 | }
42 | }
43 | }
44 |
45 | int32_t lens[MAXN];
46 | #pragma omp parallel for schedule(dynamic)
47 | for (int32_t n = 2; n < MAXN; n++) {
48 | if (!(sieve[n>>5] & (UINT32_C(1) << (n&31)))) {
49 | lens[n] = recip_len(n);
50 | }
51 | }
52 |
53 | int32_t c = 0;
54 | for (int32_t n = 2; n < MAXN; n++) {
55 | if (!(sieve[n>>5] & (UINT32_C(1) << (n&31)))) {
56 | printf("%6ld%7ld %s", (long)n, (long)lens[n],
57 | c++%5 == 4 ? "\n" : "| ");
58 | }
59 | }
60 | putchar('\n');
61 | }
62 |
--------------------------------------------------------------------------------
/misc/rfc1035encode.c:
--------------------------------------------------------------------------------
1 | // Branchless RFC 1035 domain name encoder
2 | // This is free and unencumbered software released into the public domain.
3 |
4 | // Encode a domain name using length-prefixed labels (RFC 1035). The
5 | // destination length will be one byte longer than the source length,
6 | // and buffers may overlap only if dst < src.
7 | void rfc1035encode(unsigned char *dst, unsigned char *src, int len)
8 | {
9 | int c = -1;
10 | *dst++ = 0;
11 | for (int i = 0; i < len; i++) {
12 | unsigned char copy = src[i];
13 | unsigned char keep = copy != '.';
14 | dst[i] = copy - (-!keep & '.');
15 | dst[c] += keep;
16 | c &= -keep;
17 | c |= -!keep & i;
18 | }
19 | }
20 |
21 |
22 | #ifdef TEST
23 | // $ cc -DTEST -o rfc1035encode rfc1035encode.c
24 | // $ gdb -ex run ./rfc1035encode
25 | int main(void)
26 | {
27 | #define ASSERT(c) if (!(c)) *(volatile int *)0 = 0
28 | unsigned char test[] = "$cdn.example.nullprogram.com";
29 | unsigned char expect[] = "\3cdn\7example\13nullprogram\3com";
30 | unsigned char *src = test + 1;
31 | int srclen = sizeof(test) - 2;
32 | unsigned char *dst = test;
33 | int dstlen = srclen + 1;
34 | rfc1035encode(dst, src, srclen);
35 | for (int i = 0; i < dstlen; i++) {
36 | ASSERT(dst[i] == expect[i]);
37 | }
38 | }
39 | #endif
40 |
41 |
42 | #ifdef DEMO
43 | // $ cc -DDEMO -o rfc1035encode rfc1035encode.c
44 | // $ ./rfc1035encode cdn.example.nullprogram.com
45 | #include
46 | #include
47 |
48 | int main(int argc, char **argv)
49 | {
50 | for (int i = 1; i < argc; i++) {
51 | int len = strlen(argv[i]);
52 | memmove(argv[i]+1, argv[i], len);
53 | rfc1035encode(argv[i], argv[i]+1, len);
54 | fwrite(argv[i], len+1, 1, stdout);
55 | putchar('\n');
56 | }
57 | fflush(stdout);
58 | return ferror(stdout);
59 | }
60 | #endif
61 |
--------------------------------------------------------------------------------
/misc/riskattack.c:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 |
3 | #include
4 | #include
5 |
6 | // Simulate a Risk attack roll and return the number of attackers lost.
7 | // Attack dice count must be from 1 to 3, and defense from 1 to 2. Defender
8 | // loss can be computed from attacker loss: dloss = min(att, def) - aloss
9 | //
10 | // Seed the PRNG *state to any value.
11 | int risk_attack(uint64_t *state, int attack, int defense)
12 | {
13 | for (;;) {
14 | // Custom 64-bit PCG producing a high-quality 32-bit result
15 | uint32_t r = *state >> 32;
16 | *state = *state*0x7c3c3267d015ceb5 + 1;
17 | r ^= r >> 16;
18 | r *= 0x60857ba9;
19 | r ^= r >> 16;
20 | // Rather than generate individual rolls, draw from the result
21 | // distribution, without biases (rejection sampling).
22 | switch ((attack - 1)<<1 | (defense - 1)) {
23 | case 0: if (r >= 0xfffffffc) continue; /* 1v1 */
24 | return r%12 >= 5;
25 | case 1: if (r >= 0xffffff48) continue; /* 1v2 */
26 | return r%216 >= 55;
27 | case 2: if (r >= 0xffffff48) continue; /* 2v1 */
28 | return r%216 >= 125;
29 | case 3: if (r >= 0xfffffb10) continue; /* 2v2 */
30 | return (r%1296 >= 295) + (r%1296 >= 715);
31 | case 4: if (r >= 0xffffff90) continue; /* 3v1 */
32 | return r%144 >= 95;
33 | case 5: if (r >= 0xfffff600) continue; /* 3v2 */
34 | return (r%7776 >= 2890) + (r%7776 >= 5501);
35 | }
36 | abort();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/misc/rule30.c:
--------------------------------------------------------------------------------
1 | /* Efficiently compute the center column of Rule 30
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #include
5 | #include
6 |
7 | #define RULE 30
8 |
9 | #define GEN_INIT {0, 0, 0}
10 | struct gen { uint64_t len, cap, *bits; };
11 |
12 | /* Return the next bit in the center column, or -1 when out of memory. */
13 | static int
14 | gen_next(struct gen *g)
15 | {
16 | if (g->len == 0) {
17 | g->len = 1;
18 | g->cap = 64;
19 | g->bits = malloc(g->cap/8);
20 | if (!g->bits) {
21 | g->len = g->cap = 0;
22 | return -1;
23 | }
24 | g->bits[0] = 1;
25 | return 1;
26 | }
27 |
28 | /* Append two zero bits */
29 | if (g->cap < g->len + 2) {
30 | void *p = realloc(g->bits, g->cap*2/8);
31 | if (!p) {
32 | return -1;
33 | }
34 | g->cap *= 2;
35 | g->bits = p;
36 | }
37 | g->bits[g->len/64] &= ~(UINT64_C(1) << (g->len % 64));
38 | g->len++;
39 | g->bits[g->len/64] &= ~(UINT64_C(1) << (g->len % 64));
40 | g->len++;
41 |
42 | /* Slide window across bit array updating to the next line */
43 | int window = 0; /* prefill sliding window with two zero bits */
44 | uint64_t len = g->len;
45 | uint64_t *bits = g->bits;
46 | for (uint64_t i = 0; i < len; i++) {
47 | int nextbit = (int)(bits[i/64] >> (i % 64)) & 1;
48 | window = (window<<1 | nextbit) & 7;
49 | bits[i/64] &= ~(UINT64_C(1) << (i % 64)); /* clear */
50 | bits[i/64] |= ((RULE >> window) & UINT64_C(1)) << (i % 64);
51 | }
52 | return (bits[len/2/64] >> (len/2 % 64)) & 1;
53 | }
54 |
55 | #include
56 |
57 | int
58 | main(void)
59 | {
60 | struct gen g = GEN_INIT;
61 | static unsigned char buf[1<<12];
62 | long long count = 0;
63 | for (;;) {
64 | for (int i = 0; i < (int)sizeof(buf); i++) {
65 | unsigned acc = 0;
66 | for (int b = 0; b < 8; b++) {
67 | acc |= (unsigned)gen_next(&g) << b;
68 | }
69 | if (acc >> 8) {
70 | /* At least one result was -1 (OOM) */
71 | fwrite(buf, i, 1, stdout);
72 | return 0;
73 | }
74 | buf[i] = acc;
75 | }
76 | if (!fwrite(buf, sizeof(buf), 1, stdout)) { return 1; }
77 | if (fflush(stdout)) { return 1; }
78 | count += (int)sizeof(buf) * 8;
79 | fprintf(stderr, "%lld %.3fMB\n", count, g.cap/8388608.0);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/misc/sleep.s:
--------------------------------------------------------------------------------
1 | ; 186-byte POSIX sleep(1) utility in Linux x86-64 assembly
2 | ; Usage: nasm sleep.s && chmod +x sleep
3 | ; Ref: https://redd.it/l4wfoo
4 | ; Ref: https://nullprogram.com/blog/2016/11/17/
5 | ; This is free and unencumbered software released into the public domain.
6 | bits 64
7 | db 0x7F, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00
8 | db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
9 | db 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00
10 | db 0x78, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00
11 | db 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
12 | db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
13 | db 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00
14 | db 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
15 | db 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
16 | db 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
17 | db 0x78, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00
18 | db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
19 | db flen, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
20 | db flen, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
21 | db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
22 | _start: mov edi, [rsp] ; edi = argc
23 | cmp edi, 2 ; argc == 2?
24 | je .parse
25 | mov edi, 1 ; exit(1)
26 | jmp .exit
27 | .parse: mov edx, 10 ; assume ecx = eax = 0
28 | mov rsi, [rsp+16] ; rsi = argv[1]
29 | .loop: mov cl, [rsi]
30 | sub ecx, '0'
31 | jl .sleep
32 | imul eax, edx
33 | add eax, ecx
34 | inc rsi
35 | jmp .loop
36 | .sleep: push qword 0 ; req.tv_nsec
37 | push rax ; req.tv_sec
38 | mov rdi, rsp ; &req
39 | xor esi, esi ; rem = 0
40 | mov eax, 35 ; SYS_nanosleep
41 | syscall
42 | xor edi, edi ; exit(0)
43 | .exit: mov eax, 60 ; SYS_exit
44 | syscall
45 | flen: equ $-_start
46 |
--------------------------------------------------------------------------------
/misc/thuemorse.c:
--------------------------------------------------------------------------------
1 | // Thue-Morse sequence, base-N expansion digit histogram
2 | //
3 | // This program computes the Thue-Morse sequence to a given length, interpets
4 | // it in a chosen base, and computes the exact digit distribution.
5 | //
6 | // Usage:
7 | // $ cc -O3 -o thuemorse thuemorse.c -lm
8 | // $ ./thuemorse
9 | //
10 | // Ref: https://mathworld.wolfram.com/Thue-MorseConstant.html
11 | // Ref: https://old.reddit.com/r/math/comments/pkvqy4
12 | //
13 | // This is free and unencumbered software released into the public domain.
14 | #include
15 | #include
16 | #include
17 |
18 | #define NBITS 100000L
19 | #define BASE 10
20 |
21 | int main(void)
22 | {
23 | long ndigits = 1;
24 | unsigned char *digits = calloc(1, ceil(NBITS * log(2) / log(BASE)));
25 |
26 | for (long i = 0; i < NBITS; i++) {
27 | // Multiply by 2
28 | int carry = 0;
29 | for (long j = 0; carry || (j < ndigits); j++) {
30 | ndigits = j+1 > ndigits ? j+1 : ndigits;
31 | digits[j] = 2*digits[j] + carry;
32 | carry = digits[j] >= BASE;
33 | digits[j] %= BASE;
34 | }
35 |
36 | // Add the new bit
37 | digits[0] += __builtin_popcountl(i) & 1;
38 | for (long j = 0; digits[j] >= BASE; j++) {
39 | digits[j] %= BASE;
40 | digits[j+1]++;
41 | ndigits = j+1 > ndigits ? j+1 : ndigits;
42 | }
43 | }
44 |
45 | long hist[BASE] = {0};
46 | for (long j = 0; j < ndigits; j++) {
47 | hist[digits[j]]++;
48 | }
49 | for (int i = 0; i < BASE; i++) {
50 | printf("%3x%8ld\n", i, hist[i]);
51 | }
52 |
53 | free(digits);
54 | }
55 |
--------------------------------------------------------------------------------
/misc/tiles.c:
--------------------------------------------------------------------------------
1 | /* Unique tile renderer
2 | * $ cc tiles.c && ./a.out
3 | * $ ls tile-*.svg | xargs -P$(nproc) -n1 mogrify -density 32 -format png
4 | * $ montage -tile 15x8 -geometry +10+10 tile-*.png tiles.png
5 | * Ref: https://redd.it/km1gfh
6 | * Ref: https://i.imgur.com/H6yV2Be.png
7 | * This is free and unencumbered software released into the public domain.
8 | */
9 | #include
10 | #include
11 |
12 | static int
13 | flipv(int v)
14 | {
15 | return (v<<6 & 0700) |
16 | (v & 0070) |
17 | (v>>6 & 0007);
18 | }
19 |
20 | static int
21 | transpose(int v)
22 | {
23 | return (v>>2 & 0042) |
24 | (v>>4 & 0004) |
25 | (v & 0421) |
26 | (v<<2 & 0210) |
27 | (v<<4 & 0100);
28 | }
29 |
30 | static void
31 | render(int v)
32 | {
33 | char name[16];
34 | snprintf(name, sizeof(name), "tile-%03d.svg", v);
35 | FILE *f = fopen(name, "wb");
36 | if (!f) {
37 | printf("fatal: count not open %s\n", name);
38 | exit(EXIT_FAILURE);
39 | }
40 |
41 | int scale = 100;
42 | fprintf(f, "\n");
56 |
57 | fclose(f);
58 | }
59 |
60 | int
61 | main(void)
62 | {
63 | int t;
64 | char seen[512] = {0};
65 | for (int i = 0; i < 512; i++) {
66 | if (seen[i]) continue; else seen[i] = 1;
67 | t = transpose(flipv(i));
68 | if (seen[t]) continue; else seen[t] = 1;
69 | t = transpose(flipv(t));
70 | if (seen[t]) continue; else seen[t] = 1;
71 | t = transpose(flipv(t));
72 | if (seen[t]) continue; else seen[t] = 1;
73 | render(i);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/misc/true.s:
--------------------------------------------------------------------------------
1 | ;; Linux x86-64 "true" command in 129 bytes
2 | ;; $ nasm true.s
3 | ;; $ chmod +x true
4 | ;; This is free and unencumbered software released into the public domain.
5 | bits 64
6 |
7 | %define ET_EXEC 2
8 | %define EM_X86_64 62
9 | %define PT_LOAD 1
10 | %define PF_X 1
11 | %define PF_R 4
12 | %define SYS_exit 60
13 |
14 | %define VADDR 0x0000000040000000
15 |
16 | db 0x7f, "ELF", 0x02, 0x01, 0x01, 0x00 ; e_ident
17 | dq 0 ; "
18 | dw ET_EXEC ; e_type
19 | dw EM_X86_64 ; e_machine
20 | dd 1 ; e_version
21 | dq VADDR + _start ; e_entry
22 | dq 64 ; e_phoff
23 | dq 0 ; e_shoff
24 | dd 0 ; e_flags
25 | dw 64 ; e_ehsize
26 | dw 56 ; e_phentsize
27 | dw 1 ; e_phnum
28 | dw 64 ; e_shentsize
29 | dw 0 ; e_shnum
30 | dw 0 ; e_shstrndx
31 |
32 | dd PT_LOAD ; p_type
33 | dd PF_X|PF_R ; p_flags
34 | dq _start ; p_offset
35 | dq _start + VADDR ; p_vaddr
36 | dq 0 ; p_paddr
37 | dq _end - _start ; p_filesz
38 | dq _end - _start ; p_memsz
39 | dq 0 ; p_align
40 |
41 | _start:
42 | xor edi, edi
43 | mov eax, SYS_exit
44 | syscall
45 | _end:
46 |
--------------------------------------------------------------------------------
/misc/uwords.go:
--------------------------------------------------------------------------------
1 | // uwords: count unique words on standard input
2 | // Same as uwords.c, but written in Go.
3 | // This is free and unencumbered software released into the public domain.
4 | package main
5 |
6 | import (
7 | "bufio"
8 | "fmt"
9 | "io"
10 | "os"
11 | "unicode"
12 | )
13 |
14 | func shouldSkip(r rune) bool {
15 | return unicode.IsControl(r) ||
16 | unicode.IsSpace(r) ||
17 | unicode.IsPunct(r)
18 | }
19 |
20 | func run() error {
21 | b := bufio.NewReader(os.Stdin)
22 | seen := make(map[string]struct{})
23 | var runes []rune
24 | var count int64
25 |
26 | for eof := false; !eof; {
27 | r, _, err := b.ReadRune()
28 | if err != nil {
29 | if err != io.EOF {
30 | return err
31 | }
32 | eof = true
33 | r = ' '
34 | }
35 |
36 | if !shouldSkip(r) {
37 | runes = append(runes, r)
38 | } else if len(runes) != 0 {
39 | word := string(runes)
40 | if _, ok := seen[word]; !ok {
41 | count++
42 | seen[word] = struct{}{}
43 | }
44 | runes = runes[:0]
45 | }
46 | }
47 |
48 | _, err := fmt.Println(count)
49 | return err
50 | }
51 |
52 | func main() {
53 | if err := run(); err != nil {
54 | fmt.Fprintf(os.Stderr, "count: %s", err)
55 | os.Exit(1)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/misc/wc.go:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | package main
3 |
4 | import (
5 | "bufio"
6 | "fmt"
7 | "io"
8 | "os"
9 | )
10 |
11 | func process(f *os.File) (int64, int64, int64, error) {
12 | var ws = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
13 | var lf = [256]uint8{'\n': 1}
14 | var c, w, n, s int64
15 | var r = bufio.NewReader(f)
16 | for {
17 | b, err := r.ReadByte()
18 | if err != nil {
19 | if err == io.EOF {
20 | return c, w + s, n, nil
21 | }
22 | return 0, 0, 0, err
23 | }
24 | c++
25 | n += int64(lf[b])
26 | w += int64(ws[b]) & s
27 | s = int64(ws[b]) ^ 1
28 | }
29 | }
30 |
31 | func run() error {
32 | c, w, n, err := process(os.Stdin)
33 | if err != nil {
34 | return err
35 | }
36 | _, err = fmt.Printf("%d\t%d\t%d\n", n, w, c)
37 | return err
38 | }
39 |
40 | func main() {
41 | if err := run(); err != nil {
42 | fmt.Fprintf(os.Stderr, "wc: %s\n", err)
43 | os.Exit(1)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/misc/xgetdelim.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "xgetdelim.h"
4 |
5 | size_t
6 | xgetdelim(char **lineptr, size_t *n, int delim, FILE *stream)
7 | {
8 | int c;
9 | char *line = *lineptr;
10 | size_t len = *n;
11 | size_t nread = 0;
12 |
13 | if (len < 2) {
14 | if (len)
15 | line[0] = 0;
16 | len = 256;
17 | if (!(line = realloc(line, len)))
18 | return 0;
19 | *lineptr = line;
20 | *n = len;
21 | }
22 |
23 | for (;;) {
24 | if (nread == len - 2) {
25 | /* Need space for at least two characters before fgetc(). */
26 | line[nread] = 0;
27 | if (len * 2 < len)
28 | return 0;
29 | if (!(line = realloc(line, len *= 2)))
30 | return 0;
31 | *lineptr = line;
32 | *n = len;
33 | }
34 |
35 | c = fgetc(stream);
36 | if (c == EOF) {
37 | line[nread] = 0;
38 | return nread;
39 | }
40 | line[nread++] = c;
41 | if (c == delim) {
42 | line[nread] = 0;
43 | return nread;
44 | }
45 | }
46 | }
47 |
48 | size_t
49 | xgetline(char **lineptr, size_t *n, FILE *stream)
50 | {
51 | return xgetdelim(lineptr, n, '\n', stream);
52 | }
53 |
--------------------------------------------------------------------------------
/misc/xgetdelim.h:
--------------------------------------------------------------------------------
1 | /* ANSI C implementation of getline(3) and getdelim(3) */
2 | #include
3 |
4 | /**
5 | * Returns the number of bytes read, or 0 on error or EOF.
6 | *
7 | * The two kinds of errors: input error, out of memory. To distinguish
8 | * between EOF, input error, and out of memory use ferror() and feof()
9 | * on the stream. If an out of memory error occurs, the buffer contains
10 | * the entire NUL-terminated stream, though with a possibly ambiguous
11 | * length.
12 | *
13 | * This function properly handles inputs containing NUL bytes. It is the
14 | * caller's responsibility to free the buffer when done.
15 | */
16 | size_t xgetdelim(char **lineptr, size_t *n, int delim, FILE *stream);
17 |
18 | /**
19 | * Same as xgetdelim(lineptr, n, '\n', stream).
20 | */
21 | size_t xgetline(char **lineptr, size_t *n, FILE *stream);
--------------------------------------------------------------------------------
/misc/xstrtok.h:
--------------------------------------------------------------------------------
1 | /* xstrtok: drop-in, portable strtok_r(3)
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #include
5 |
6 | static char *
7 | xstrtok(char *str, const char *delim, char **saveptr)
8 | {
9 | char *r, *p = str ? str : *saveptr;
10 |
11 | r = p += strspn(p, delim);
12 | if (!*p) {
13 | return (*saveptr = 0);
14 | }
15 |
16 | *saveptr = p += strcspn(p, delim);
17 | if (*p) {
18 | *p = 0;
19 | (*saveptr)++;
20 | }
21 |
22 | return r;
23 | }
24 |
--------------------------------------------------------------------------------
/mmlfg/Mmlfg.java:
--------------------------------------------------------------------------------
1 | // Middle Multiplicative Lagged Fibonacci Generator
2 | // This is free and unencumbered software released into the public domain.
3 | public class Mmlfg {
4 | public int i = 14;
5 | public int j = 12;
6 | public final long[] s = new long[15];
7 |
8 | public Mmlfg(long seed) {
9 | for (int n = 0; n < 15; n++) {
10 | seed = seed*0x3243f6a8885a308dL + 1111111111111111111L;
11 | s[n] = seed ^ seed>>>31 | 1;
12 | }
13 | }
14 |
15 | public long next() {
16 | long lo = s[i] * s[j];
17 | long hi = Math.multiplyHigh(s[i], s[j]);
18 | hi += s[i]>>63 & s[j];
19 | hi += s[j]>>63 & s[i];
20 | s[i] = lo;
21 | i = i == 0 ? 14 : i-1;
22 | j = j == 0 ? 14 : j-1;
23 | return hi<<32 | lo>>>32;
24 | }
25 |
26 | public static void main(String[] args) {
27 | Mmlfg[] r = {new Mmlfg(0), new Mmlfg(1), new Mmlfg(2), new Mmlfg(3)};
28 | for (int i = 0; i < 40; i++) {
29 | System.out.printf("%016x %016x %016x %016x\n",
30 | r[0].next(), r[1].next(),
31 | r[2].next(), r[3].next());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mmlfg/README.md:
--------------------------------------------------------------------------------
1 | # Middle Multiplicative Lagged Fibonacci Generator (MMLFG)
2 |
3 | An enhanced, two-tap Multiplicative Lagged Fibonacci Generator (MLFG)
4 | where the yield is the "middle" 64 bits of a 128-bit product, much like
5 | the middle of the middle-square algorithm. The low 64 bits are still used
6 | in the usual fashion for the MLFG state. Below, `f` iterates the internal
7 | state and `g` computes, in parallel, output.
8 |
9 | f(n) = (f(n-j) * f(n-k)) % (1 << N)
10 | g(n) = ((f(n-j) * f(n-k)) >> N/2) % (1 << N)
11 |
12 | For the generators in this repository: `N=64`, `j=13`, `k=15`, making for
13 | a period of `2**76 - 2**61` and, in practice, 128-byte state. They pass
14 | BigCrush, and PractRand to at least to 8TB.
15 |
16 | The Go implementation is, on gc, the fastest pure-Go PRNG of which I'm
17 | aware that passes BigCrush and PractRand.
18 |
19 | ## Canonical seeding
20 |
21 | The generator's 15-element state must be seeded to all odd numbers, must
22 | not be all 1, and must not eventually result in all 1. For the sake of
23 | testing, the canonical algorithm for seeding an MMLFG from a 64-bit seed
24 | is a full-period 64-bit Linear Congruential Generator (LCG):
25 |
26 | f(n) = (f(n-1)*0x3243f6a8885a308d + 1111111111111111111) % (1 << 64)
27 |
28 | Where f(0) is the seed and f(1) is used to compute the first state
29 | element. The multiplier is the digits of pi as a 64-bit integer (easily
30 | computed with unix `bc`), and the increment is a memorable prime (nineteen
31 | ones). The LCG output is xorshifted by 31 and the lowest bit is locked to
32 | 1, making the result odd:
33 |
34 | e(n) = (f(n) ^ (f(n) >> 31)) | 1
35 |
36 | Seeded with zero, the first 40 MMLFG outputs are:
37 |
38 | 1573aa52f814bda8 3aeaac28b52676e2 8f1b6491309e5792 25bca26e169f58cd
39 | ee13266f6d5bad81 d688681022995579 c227f64fffc6967a 3d06e4f91995745f
40 | 4077b1108d5150b1 41deb8bcf496aac3 def5ecadb01c5527 42be0306aca9476d
41 | cc40df9abc49fae2 d6fab4fe6f2c8373 ad02822ecc846c6d 602b2201cc7bf7b7
42 | ded4343bd0724597 fcbcd8d91b8f65f4 fc76214430f94e44 4c7fc6e9f4291294
43 | fca3ad5722cee412 e3383e408585396a fbafa05b7c2faecf e684088050284b8c
44 | 8bbb114ed18162a0 0bbde9b2d192d39b b403be5f2fb967e5 c60ea291e01fe627
45 | 1790ba5d87432edc 598bdded3fe137d9 0dba6bcb0e9e17ef 748d4dac10754ca0
46 | a212d97e7982de85 975ea1c76b0f0a7e ad0170d0b44d8673 a3d8fb24e994e7cf
47 | 5ecef8bd9f6e7279 c3a57186c73c6a98 7f3ad93171dfdff9 0c16dcd911bee1a9
48 |
49 |
50 | [mlfg]: http://www.cs.fsu.edu/~asriniva/papers/mlfg.ps
51 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.c:
--------------------------------------------------------------------------------
1 | // Middle Multiplicative Lagged Fibonacci Generator
2 | // This is free and unencumbered software released into the public domain.
3 | #include
4 |
5 | struct mmlfg {
6 | uint64_t s[15];
7 | int i, j;
8 | };
9 |
10 | void
11 | mlfg_seed(struct mmlfg *s, uint64_t seed)
12 | {
13 | for (int i = 0; i < 15; i++) {
14 | seed = seed*0x3243f6a8885a308d + 1111111111111111111;
15 | s->s[i] = (seed ^ seed>>31) | 1;
16 | }
17 | s->i = 14;
18 | s->j = 12;
19 | }
20 |
21 | uint64_t
22 | mlfg_next(struct mmlfg *s)
23 | {
24 | uint64_t lo, mi;
25 | #if defined(__GNUC__) || defined(__clang__)
26 | __uint128_t m = (__uint128_t)s->s[s->i] * s->s[s->j];
27 | mi = m >> 32;
28 | lo = m;
29 | #elif defined(_MSC_VER)
30 | uint64_t hi;
31 | lo = _umul128(s->s[s->i], s->s[s->j], &hi);
32 | mi = hi<<32 | lo>>32;
33 | #else
34 | uint64_t a = s->s[s->i], b = s->s[s->j];
35 | uint64_t r00 = (a & 0xffffffff) * (b & 0xffffffff);
36 | uint64_t r10 = (a >> 32 ) * (b & 0xffffffff);
37 | uint64_t r01 = (a & 0xffffffff) * (b >> 32 );
38 | uint64_t r11 = (a >> 32 ) * (b >> 32 );
39 | uint64_t cr = (r00 >> 32) + (r10 & 0xffffffff) + r01;
40 | uint64_t hi = (r10 >> 32) + (cr >> 32 ) + r11;
41 | lo = (cr << 32) | (r00 & 0xffffffff);
42 | mi = hi<<32 | lo>>32;
43 | #endif
44 | s->s[s->i] = lo;
45 | s->i = s->i ? s->i-1 : 14;
46 | s->j = s->j ? s->j-1 : 14;
47 | return mi;
48 | }
49 |
50 |
51 | // Example
52 | #include
53 |
54 | int
55 | main(void)
56 | {
57 | struct mmlfg s[4];
58 | for (int i = 0; i < 4; i++) {
59 | mlfg_seed(s+i, i);
60 | }
61 |
62 | for (int i = 0; i < 40; i++) {
63 | printf("%016llx %016llx %016llx %016llx\n",
64 | (unsigned long long)mlfg_next(s+0),
65 | (unsigned long long)mlfg_next(s+1),
66 | (unsigned long long)mlfg_next(s+2),
67 | (unsigned long long)mlfg_next(s+3));
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.el:
--------------------------------------------------------------------------------
1 | ;; Middle Multiplicative Lagged Fibonacci PRNG -*- lexical-binding: t; -*-
2 | ;; This is free and unencumbered software released into the public domain.
3 |
4 | (defun mmlfg (seed)
5 | "Returns a closure that generates a 64-bit result each invocation."
6 | (let ((state (make-vector 15 0))
7 | (i 14)
8 | (j 12))
9 | (dotimes (k 15)
10 | (setf seed (logand (+ (* seed #x3243f6a8885a308d)
11 | 1111111111111111111)
12 | #xffffffffffffffff)
13 | (aref state k) (logior 1 (logxor seed (lsh seed -31)))))
14 | (lambda ()
15 | (let ((r (* (aref state i) (aref state j))))
16 | (prog1 (logand (lsh r -32) #xffffffffffffffff)
17 | (setf (aref state i) (logand r #xffffffffffffffff)
18 | i (% (+ i 14) 15)
19 | j (% (+ j 14) 15)))))))
20 |
21 |
22 | ;; Example
23 | (let ((a (mmlfg 0)) (b (mmlfg 1)) (c (mmlfg 2)) (d (mmlfg 3)))
24 | (dotimes (_ 40)
25 | (princ (format "%016x %016x %016x %016x\n"
26 | (funcall a) (funcall b) (funcall c) (funcall d)))))
27 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.go:
--------------------------------------------------------------------------------
1 | // Middle Multiplicative Lagged Fibonacci Generator
2 | // This is free and unencumbered software released into the public domain.
3 | package main
4 |
5 | import (
6 | "fmt"
7 | "math/bits"
8 | "math/rand"
9 | )
10 |
11 | // A Mmlfg is a Middle Multiplicative Lagged Fibonacci generator. The
12 | // output is the middle 64 bits of a 128-bit product. A larger state is
13 | // required to pass statistical tests. Must be seeded carefully with
14 | // good random values, and all state elements must be odd, so the Seed()
15 | // method is highly recommended.
16 | type Mmlfg struct {
17 | s [15]uint64
18 | i, j int32
19 | }
20 |
21 | var _ rand.Source = (*Mmlfg)(nil)
22 |
23 | func (m *Mmlfg) Seed(seed int64) {
24 | s := uint64(seed)
25 | for i := 0; i < 15; i++ {
26 | s = s*0x3243f6a8885a308d + 1111111111111111111
27 | m.s[i] = s ^ s>>31 | 1
28 | }
29 | m.i = 14
30 | m.j = 12
31 | }
32 |
33 | func (m *Mmlfg) Int63() int64 {
34 | return int64(m.Uint64() >> 1)
35 | }
36 |
37 | func (m *Mmlfg) Uint64() uint64 {
38 | hi, lo := bits.Mul64(m.s[m.i], m.s[m.j])
39 | m.s[m.i] = lo
40 | m.i--
41 | if m.i < 0 {
42 | m.i = 14
43 | }
44 | m.j--
45 | if m.j < 0 {
46 | m.j = 14
47 | }
48 | return hi<<32 | lo>>32
49 | }
50 |
51 | // Example
52 | func main() {
53 | var m [4]Mmlfg
54 | for i := 0; i < 4; i++ {
55 | m[i].Seed(int64(i))
56 | }
57 | for i := 0; i < 40; i++ {
58 | fmt.Printf("%016x %016x %016x %016x\n",
59 | m[0].Uint64(), m[1].Uint64(), m[2].Uint64(), m[3].Uint64())
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.js:
--------------------------------------------------------------------------------
1 | function mmlfg(seed) {
2 | let i = 14
3 | let j = 12
4 | let s = new Array(15).fill(0)
5 |
6 | seed = BigInt(seed)
7 | for (let i = 0; i < 15; i++) {
8 | seed *= 0x3243f6a8885a308dn
9 | seed += 1111111111111111111n
10 | seed &= 0xffffffffffffffffn
11 | s[i] = seed ^ seed>>31n | 1n
12 | }
13 |
14 | return function() {
15 | let r = s[i] * s[j]
16 | s[i] = r & 0xffffffffffffffffn
17 | i = (i + 14) % 15
18 | j = (j + 14) % 15
19 | return (r >> 32n) & 0xffffffffffffffffn
20 | }
21 | }
22 |
23 |
24 | // Example
25 | let g = [mmlfg(0), mmlfg(1), mmlfg(2), mmlfg(3)]
26 | for (let i = 0; i < 40; i++) {
27 | function f(x) { return ("0000000000000000" + x.toString(16)).slice(-16) }
28 | console.log(f(g[0]()), f(g[1]()), f(g[2]()), f(g[3]()))
29 | }
30 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.lua:
--------------------------------------------------------------------------------
1 | -- Middle Multiplicative Lagged Fibonacci Generator
2 | -- This is free and unencumbered software released into the public domain.
3 |
4 | -- Returns a function generating a 64-bit result on each call.
5 | function mmlfg(seed)
6 | local i = 15
7 | local j = 13
8 | local s = {}
9 | for i = 1, 15 do
10 | seed = seed*0x3243f6a8885a308d + 1111111111111111111
11 | s[i] = seed ~ seed>>31 | 1
12 | end
13 |
14 | return function()
15 | -- Update internal state
16 | local a, b = s[i], s[j]
17 | s[i] = a * b
18 | i = i > 1 and i-1 or 15
19 | j = j > 1 and j-1 or 15
20 |
21 | -- 128-bit multiply for result
22 | local r00 = (a & 0xffffffff) * (b & 0xffffffff)
23 | local r10 = (a >> 32 ) * (b & 0xffffffff)
24 | local r01 = (a & 0xffffffff) * (b >> 32 )
25 | local r11 = (a >> 32 ) * (b >> 32 )
26 | local mid = (r00 >> 32) + (r10 & 0xffffffff) + r01
27 | local hi = (r10 >> 32) + (mid >> 32 ) + r11
28 | local lo = (mid << 32) | (r00 & 0xffffffff)
29 |
30 | -- Return middle of 128-bit product
31 | return hi<<32 | lo>>32
32 | end
33 | end
34 |
35 | -- Example
36 | local r = {}
37 | local v = {}
38 | for i = 1, 4 do
39 | r[i] = mmlfg(i - 1)
40 | end
41 | for i = 1, 40 do
42 | for i = 1, #r do
43 | v[i] = string.format("%016x", r[i]())
44 | end
45 | print(table.concat(v, " "))
46 | end
47 |
--------------------------------------------------------------------------------
/mmlfg/mmlfg.py:
--------------------------------------------------------------------------------
1 | # Middle Multiplicative Lagged Fibonacci PRNG
2 | # This is free and unencumbered software released into the public domain.
3 | import array
4 |
5 | def mmlfg(seed):
6 | """Yields 64-bit random numbers."""
7 | i = 14
8 | j = 12
9 | s = array.array("Q", (0,) * 15)
10 |
11 | for i in range(15):
12 | seed *= 0x3243f6a8885a308d
13 | seed += 1111111111111111111
14 | seed &= 0xffffffffffffffff
15 | s[i] = seed ^ seed>>31 | 1
16 |
17 | while True:
18 | r = s[i] * s[j]
19 | s[i] = r & 0xffffffffffffffff
20 | i = (i + 14) % 15
21 | j = (j + 14) % 15
22 | yield r>>32 & 0xffffffffffffffff
23 |
24 |
25 | # Example
26 | r = tuple(mmlfg(i) for i in range(4))
27 | for _ in range(40):
28 | print(*(f"{next(r[i]):016x}" for i in range(4)))
29 |
--------------------------------------------------------------------------------
/monocrypt/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -O3 -g -Wall -Wextra -D__USE_MINGW_ANSI_STDIO=0
4 | LDFLAGS = -flto
5 | LDLIBS =
6 |
7 | sources = monocrypt.c platform.c monocypher.c
8 |
9 | monocrypt$(EXE): $(sources)
10 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(sources) $(LDLIBS)
11 |
12 | clean:
13 | rm -f monocrypt$(EXE)
14 |
--------------------------------------------------------------------------------
/monocrypt/README.md:
--------------------------------------------------------------------------------
1 | # Monocrypt
2 |
3 | Monocrypt is a minimalistic password-based authenticated encryption tool
4 | that encrypts files/pipes with XChacha20/Poly1305 as defined in [RFC
5 | 8439][rfc]. Keys are derived using Argon2i. Data are encrypted in chunks,
6 | so arbitrarily large ciphertexts are supported with fixed memory.
7 |
8 | Supported on unix-likes and Windows.
9 |
10 | ## Usage
11 |
12 | usage: monocrypt <-E|-D> [-h] [-o FILE] [-p PASSWORD] [FILE]
13 |
14 | The two modes of operation are `-E` (encrypt) or `-D` (decrypt).
15 |
16 | Without `-o` (output file), output is written to standard output. Without
17 | the positional argument, input is read from standard input. Without `-p`
18 | (password), `monocrypt` interactively prompts for a password.
19 |
20 | Upon failure, `monocrypt` will try to delete the output file.
21 |
22 | ### Examples
23 |
24 | $ ./monocrypt -E -o message.txt.enc message.txt
25 |
26 | On the other end, this prints the decrypted message to the terminal:
27 |
28 | $ ./monocrypt -D message.txt.enc
29 |
30 | ## Details
31 |
32 | The first 24 bytes of the format are the nonce, followed by 64MiB chunks
33 | of ciphertext encrypted with XChacha20/Poly1305. The nonce is incremented
34 | (little endian) after each chunk. A short chunk, possibly just the 16-byte
35 | MAC, indicates end of file.
36 |
37 |
38 | [rfc]: https://tools.ietf.org/html/rfc8439
39 |
40 |
--------------------------------------------------------------------------------
/monocrypt/platform.h:
--------------------------------------------------------------------------------
1 | #ifndef PASSWORD_H
2 | #define PASSWORD_H
3 |
4 | #include
5 |
6 | /* Set standard input and output to binary. */
7 | void binary_stdio(void);
8 |
9 | /* Fill buf with system entropy. */
10 | int fillrand(void *buf, int len);
11 |
12 | /* Display prompt then read zero-terminated, UTF-8 password.
13 | * Return password length with terminator, zero on input error, negative if
14 | * the buffer was too small.
15 | */
16 | int read_password(uint8_t *buf, int len, char *prompt);
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/mt19937/README.md:
--------------------------------------------------------------------------------
1 | # Mersenne Twister (MT19937) public domain C99 header library
2 |
3 | ```c
4 | void mt19937_init(struct mt19937 *, uint32_t seed);
5 | uint32_t mt19937_next(struct mt19937 *);
6 |
7 | void mt19937_64_init(struct mt19937_64 *, uint64_t seed);
8 | uint64_t mt19937_64_next(struct mt19937_64 *);
9 | ```
10 |
11 | ## Usage example
12 |
13 | ```c
14 | #include
15 |
16 | #define MT19937_IMPLEMENTATION
17 | #include "mt19937.h"
18 |
19 | int main(void)
20 | {
21 | struct mt19937 mt[1];
22 | mt19937_init(mt, 12345);
23 | printf("%f\n", mt19937_next(mt) / 4294967296.0); // 0.929616
24 | printf("%f\n", mt19937_next(mt) / 4294967296.0); // 0.890155
25 | printf("%f\n", mt19937_next(mt) / 4294967296.0); // 0.316376
26 | }
27 | ```
28 |
29 | ## Tests and benchmark
30 |
31 | $ cc -O3 -o test test.c
32 | $ ./test
33 | $ ./test 32 | RNG_test stdin32
34 | $ ./test 64 | RNG_test stdin64
35 |
--------------------------------------------------------------------------------
/mt19937/mt19937.h:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #ifndef MT19937_H
3 | #define MT19937_H
4 |
5 | #ifndef MT19937_API
6 | # define MT19937_API static
7 | #endif
8 |
9 | #include
10 |
11 | struct mt19937 {
12 | uint32_t v[624];
13 | int i;
14 | };
15 |
16 | MT19937_API void mt19937_init(struct mt19937 *, uint32_t seed);
17 | MT19937_API uint32_t mt19937_next(struct mt19937 *);
18 |
19 |
20 | #ifdef MT19937_IMPLEMENTATION
21 |
22 | MT19937_API
23 | void
24 | mt19937_init(struct mt19937 *mt, uint32_t seed)
25 | {
26 | mt->i = 624;
27 | mt->v[0] = seed;
28 | for (int i = 1; i < 624; i++) {
29 | mt->v[i] = 0x6c078965U * (mt->v[i-1] ^ (mt->v[i-1] >> 30)) + i;
30 | }
31 | }
32 |
33 | MT19937_API
34 | uint32_t
35 | mt19937_next(struct mt19937 *mt)
36 | {
37 | if (mt->i >= 624) {
38 | for (int i = 0; i < 624; i++) {
39 | uint32_t x = (mt->v[ i ] & 0x80000000U) +
40 | (mt->v[(i+1)%624] & 0x7fffffffU);
41 | uint32_t a = (x >> 1) ^ ((x & 1) * 0x9908b0dfU);
42 | mt->v[i] = mt->v[(i+397)%624] ^ a;
43 | }
44 | mt->i = 0;
45 | }
46 | uint32_t y = mt->v[mt->i++];
47 | y = y ^ (y >> 11 );
48 | y = y ^ (y << 7 & 0x9d2c5680U);
49 | y = y ^ (y << 15 & 0xefc60000U);
50 | y = y ^ (y >> 18 );
51 | return y;
52 | }
53 |
54 | #endif // MT19937_IMPLEMENTATION
55 | #endif // MT19937_H
56 |
--------------------------------------------------------------------------------
/mt19937/mt19937_64.h:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #ifndef MT19937_64_H
3 | #define MT19937_64_H
4 |
5 | #ifndef MT19937_64_API
6 | # define MT19937_64_API static
7 | #endif
8 |
9 | #include
10 |
11 | struct mt19937_64 {
12 | uint64_t v[312];
13 | int i;
14 | };
15 |
16 | MT19937_64_API void mt19937_64_init(struct mt19937_64 *, uint64_t seed);
17 | MT19937_64_API uint64_t mt19937_64_next(struct mt19937_64 *);
18 |
19 |
20 | #ifdef MT19937_64_IMPLEMENTATION
21 |
22 | MT19937_64_API
23 | void
24 | mt19937_64_init(struct mt19937_64 *mt, uint64_t seed)
25 | {
26 | mt->i = 312;
27 | mt->v[0] = seed;
28 | for (int i = 1; i < 312; i++) {
29 | mt->v[i] = 0x5851f42d4c957f2dU * (mt->v[i-1] ^ (mt->v[i-1] >> 62)) + i;
30 | }
31 | }
32 |
33 | MT19937_64_API
34 | uint64_t
35 | mt19937_64_next(struct mt19937_64 *mt)
36 | {
37 | if (mt->i >= 312) {
38 | for (int i = 0; i < 312; i++) {
39 | uint64_t x = (mt->v[ i ] & 0xffffffff80000000U) +
40 | (mt->v[(i+1)%312] & 0x000000007fffffffU);
41 | uint64_t a = (x >> 1) ^ ((x & 1) * 0xb5026f5aa96619e9U);
42 | mt->v[i] = mt->v[(i+156)%312] ^ a;
43 | }
44 | mt->i = 0;
45 | }
46 | uint64_t y = mt->v[mt->i++];
47 | y = y ^ (y >> 29 & 0x5555555555555555U);
48 | y = y ^ (y << 17 & 0x71d67fffeda60000U);
49 | y = y ^ (y << 37 & 0xfff7eee000000000U);
50 | y = y ^ (y >> 43 );
51 | return y;
52 | }
53 |
54 | #endif // MT19937_64_IMPLEMENTATION
55 | #endif // MT19937_64_H
56 |
--------------------------------------------------------------------------------
/parsers/README.md:
--------------------------------------------------------------------------------
1 | # Parsers for various formats
2 |
3 | These parsers have a theme: minimalistic, robust, fast, and compact. They
4 | don't allocate, and in most cases don't even require libc.
5 |
--------------------------------------------------------------------------------
/parsers/chars.dot:
--------------------------------------------------------------------------------
1 | // State machine diagram for chars.c
2 | // This is free and unencumbered software released into the public domain.
3 |
4 | digraph {
5 | graph [fontname="sans-serif" rankdir=LR nodesep=0.2]
6 | node [fontname="sans-serif" shape=circle fontsize=16]
7 | edge [fontname="monospace" arrowsize=0.65 fontsize=14]
8 |
9 | 2 [shape=doublecircle]
10 | 2 -> 0 [label="*"]
11 | 2 -> 1 [label="0d"]
12 | 2 -> 3 [label="ef"]
13 | 2 -> 4 [label="fe"]
14 | 2 -> 5 [label="ff"]
15 |
16 | subgraph cluster {
17 | graph [style=filled color=lightgray]
18 |
19 | 0 -> 1 [label="0d"]
20 | 0 -> 0 [label="*"]
21 |
22 | 1 -> 0 [label="*"]
23 | 1 -> 1 [label="0d"]
24 | }
25 |
26 | subgraph cluster8 {
27 | graph [style=invis]
28 |
29 | 3 -> 0 [label="*"]
30 | 3 -> 1 [label="0d"]
31 | 3 -> 6 [label="bb"]
32 |
33 |
34 | 6 -> 0 [label="*"]
35 | 6 -> 1 [label="0d"]
36 | 6 -> 0 [label="bf:UTF-8"]
37 | }
38 |
39 | subgraph cluster16 {
40 | graph [style=invis]
41 |
42 | 4 -> 0 [label="*"]
43 | 4 -> 1 [label="0d"]
44 | 4 -> 0 [label="ff:16BE"]
45 |
46 | 5 -> 0 [label="*"]
47 | 5 -> 1 [label="0d"]
48 | 5 -> 1 [label="fe:16LE"]
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/parsers/urldecode.c:
--------------------------------------------------------------------------------
1 | // Small, in-place URL decoder state machine
2 | // This is free and unencumbered software released into the public domain.
3 |
4 | // Decode a URL in place, returning the new length.
5 | int urldecode(char *buf, int len)
6 | {
7 | static const char values[256] = {
8 | ['0']= 1, ['1']= 2, ['2']= 3, ['3']= 4, ['4']= 5,
9 | ['5']= 6, ['6']= 7, ['7']= 8, ['8']= 9, ['9']=10,
10 | ['A']=11, ['B']=12, ['C']=13, ['D']=14, ['E']=15, ['F']=16,
11 | ['a']=11, ['b']=12, ['c']=13, ['d']=14, ['e']=15, ['f']=16,
12 | };
13 |
14 | int out = 0;
15 | int state = 0;
16 | int accum = 0;
17 | for (int i = 0; i < len; i++) {
18 | char c = buf[i];
19 | int v = values[c&255] - 1;
20 | switch (state) {
21 | case 0: state = c == '%';
22 | break;
23 | case 1: switch (v) {
24 | case -1: state = c == '%';
25 | break;
26 | default: state = 2;
27 | accum = v << 4;
28 | } break;
29 | case 2: switch (v) {
30 | case -1: state = c == '%';
31 | break;
32 | default: state = 0;
33 | out -= 2; // rewind
34 | c = (char)(accum | v);
35 | } break;
36 | }
37 | buf[out++] = c;
38 | }
39 | return out;
40 | }
41 |
42 |
43 | #ifdef DEMO
44 | #include
45 |
46 | int main(void)
47 | {
48 | char url[] = "Let%27s%20make%20%cf%80!";
49 | int len = urldecode(url, sizeof(url)-1);
50 | printf("%.*s\n", len, url);
51 | }
52 | #endif
53 |
--------------------------------------------------------------------------------
/pbmview/.gitignore:
--------------------------------------------------------------------------------
1 | icon.o
2 | icon.rc
3 | icon.res
4 | pbmview.exe
5 | pbmview.obj
6 |
--------------------------------------------------------------------------------
/pbmview/GNUmakefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CROSS =
3 | CC = $(CROSS)gcc -std=c99
4 | CFLAGS = -DNDEBUG -Os -fno-asynchronous-unwind-tables
5 | LDFLAGS = -s -nostdlib -Wl,--gc-sections
6 | LDLIBS = -lkernel32 -lshell32 -luser32 -lgdi32 -lshlwapi
7 | WINDRES = $(CROSS)windres
8 |
9 | pbmview.exe: pbmview.c icon.o
10 | $(CC) $(CFLAGS) -mwindows $(LDFLAGS) -o $@ pbmview.c icon.o $(LDLIBS)
11 |
12 | icon.o: pbmview.ico
13 | echo '1 ICON "pbmview.ico"' | $(WINDRES) -o $@
14 |
15 | clean:
16 | rm -f pbmview.exe icon.o
17 |
--------------------------------------------------------------------------------
/pbmview/Makefile:
--------------------------------------------------------------------------------
1 | CC = cl /nologo
2 | RC = rc /nologo
3 | CFLAGS = /O2 /Oi /GS-
4 |
5 | pbmview.exe: pbmview.c icon.res
6 | $(CC) $(CFLAGS) pbmview.c icon.res
7 |
8 | icon.rc:
9 | echo 1 ICON "pbmview.ico" >$@
10 |
11 | clean:
12 | if exist icon.rc del icon.rc
13 | if exist icon.res del icon.res
14 | if exist pbmview.exe del pbmview.exe
15 | if exist pbmview.obj del pbmview.obj
16 |
--------------------------------------------------------------------------------
/pbmview/README.md:
--------------------------------------------------------------------------------
1 | # Netpbm Viewer for Windows
2 |
3 | Fast. Lightweight. Minimalistic. Supports [P2, P3, P5, and P6][pbm] at 255
4 | maxdepth, [farbfeld][], and [QOI][]. Monitors for changes and
5 | automatically refreshes. Drag-and-drop. Windows XP and later.
6 |
7 | * f: toggle fullscreen
8 | * q / ESC: exit the program
9 | * s: toggle exact vs. smoothed filtering (default: auto)
10 | * z: reset window to image size (or approximate)
11 |
12 | If the input is unreadable for any reason, it does nothing — not even
13 | reporting errors — until the image file is updated with useful image
14 | contents. Only displays one image at a time and cannot navigate an image
15 | gallery.
16 |
17 | ## Usage
18 |
19 | Pass the image path as an argument, or supply no arguments and instead use
20 | drag-and-drop. This interface works well as a file association for Netpbm
21 | file extensions.
22 |
23 | Automatic reload is particularly useful when writing programs that output
24 | Netpbm images. For example, when developing a program that outputs Netpbm
25 | on standard output, in GDB use `run` like so:
26 |
27 | gdb> run >output.ppm
28 |
29 | Then open `output.ppm` in `pbmview` and leave it open. Each time you run
30 | the program (`r`), the viewer will automatically display the new image.
31 | The viewer will actively watch for the image file to be created if it does
32 | not yet exist.
33 |
34 | ## Build
35 |
36 | Grab [w64devkit][] and run `make`. With MSVC, run `nmake`. When cross
37 | compiling, set `CROSS`.
38 |
39 | make CROSS=x86_64-w64-mingw32-
40 |
41 | ## Known issues
42 |
43 | Uses `StretchDIBits` with `HALFTONE` scaling, a naive algorithm that is
44 | not [gamma-aware][] and produces artifacts, especially in older versions
45 | of Windows.
46 |
47 |
48 | [farbfeld]: https://tools.suckless.org/farbfeld/
49 | [gamma-aware]: https://web.archive.org/web/20190419162041/http://www.ericbrasseur.org/gamma.html
50 | [pbm]: http://netpbm.sourceforge.net/doc/ppm.html
51 | [QOI]: https://qoiformat.org/
52 | [w64devkit]: https://github.com/skeeto/w64devkit
53 |
--------------------------------------------------------------------------------
/pbmview/pbmview.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/pbmview/pbmview.ico
--------------------------------------------------------------------------------
/place-2022/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -Wall -Wextra -O3 -march=native -g
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | all: convert$(EXE) render$(EXE)
8 |
9 | convert$(EXE): convert.c
10 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ convert.c $(LDLIBS)
11 |
12 | render$(EXE): render.c
13 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ render.c $(LDLIBS)
14 |
15 | clean:
16 | rm -f convert$(EXE) render$(EXE)
17 |
--------------------------------------------------------------------------------
/place-2022/render.c:
--------------------------------------------------------------------------------
1 | // Place 2022 video renderer
2 | // $ cc -O3 -o render render.c
3 | // $ unxz
7 | #include
8 | #include
9 |
10 | #define STEP 30000 // real-time milliseconds per frame
11 |
12 | static const char hdr[17] = "P6\n2000 2000\n255\n";
13 | static const unsigned colors[] = {
14 | 0x000000,0x00756f,0x009eaa,0x00a368,0x00cc78,0x00ccc0,0x2450a4,0x3690ea,
15 | 0x493ac1,0x515252,0x51e9f4,0x6a5cff,0x6d001a,0x6d482f,0x7eed56,0x811e9f,
16 | 0x898d90,0x94b3ff,0x9c6926,0xb44ac0,0xbe0039,0xd4d7d9,0xde107f,0xe4abff,
17 | 0xff3881,0xff4500,0xff99aa,0xffa800,0xffb470,0xffd635,0xfff8b8,0xffffff,
18 | };
19 |
20 | int main(void)
21 | {
22 | static unsigned char buf[2000][2000][3];
23 | memset(buf, 0xff, sizeof(buf));
24 |
25 | #if _WIN32
26 | int _setmode(int, int);
27 | _setmode(1, 0x8000);
28 | #endif
29 |
30 | int last = 0;
31 | char line[32];
32 | fgets(line, sizeof(line), stdin); // skip header
33 | while (fgets(line, sizeof(line), stdin) && !ferror(stdout)) {
34 | int t = atoi(strtok(line, ","));
35 | int u = atoi(strtok(0, ",")); (void)u;
36 | int i = atoi(strtok(0, ","));
37 | int x = atoi(strtok(0, ","));
38 | int y = atoi(strtok(0, ","));
39 | if (t > last+STEP) {
40 | fwrite(hdr, sizeof(hdr), 1, stdout);
41 | fwrite(buf, sizeof(buf), 1, stdout);
42 | last = last ? last+STEP : t;
43 | }
44 | buf[y][x][0] = colors[i] >> 16;
45 | buf[y][x][1] = colors[i] >> 8;
46 | buf[y][x][2] = colors[i] >> 0;
47 | }
48 | fwrite(hdr, sizeof(hdr), 1, stdout);
49 | fwrite(buf, sizeof(buf), 1, stdout);
50 | return ferror(stdout);
51 | }
52 |
--------------------------------------------------------------------------------
/pngattach/.gitignore:
--------------------------------------------------------------------------------
1 | pngattach
2 | pngattach.exe
3 |
--------------------------------------------------------------------------------
/pngattach/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -Wall -Wextra -Os
4 | LDFLAGS = -s
5 | LDLIBS = -lz
6 | PREFIX = /usr/local
7 |
8 | pngattach$(EXE): pngattach.c
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ pngattach.c $(LDLIBS)
10 |
11 | install: pngattach$(EXE)
12 | mkdir -p $(DESTDIR)$(PREFIX)/bin
13 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
14 | install -m 755 pngattach$(EXE) $(DESTDIR)$(PREFIX)/bin
15 | gzip $(DESTDIR)$(PREFIX)/share/man/man1/pngattach.1.gz
16 |
17 | uninstall:
18 | rm -f $(DESTDIR)$(PREFIX)/bin/pngattach$(EXE)
19 | rm -f $(DESTDIR)$(PREFIX)/share/man/man1/pngattach.1.gz
20 |
21 | clean:
22 | rm -f pngattach$(EXE)
23 |
--------------------------------------------------------------------------------
/pngattach/README.md:
--------------------------------------------------------------------------------
1 | # pngattach: attach files to a PNG image as metadata
2 |
3 | The intended use is for attaching the source script(s) from which the
4 | image was rendered. Attachments take the form of private "atCh" PNG
5 | chunks, documented below, since none of the pre-defined chunks quite
6 | captured what was needed.
7 |
8 | PNG data is always transmitted on standard input and output. Example
9 | usage:
10 |
11 | $ dot -Tpng graph.dot | pngattach graph.dot >graph.png
12 |
13 | Which embeds the original source script into the PNG. It can be recovered
14 | later with:
15 |
16 | $ pngattach -x graph.dot
21 |
22 | ## Dependencies
23 |
24 | The tool only depends on zlib, used to compress and decompress
25 | attachments. This dependency is optional if attachments are not
26 | compressed.
27 |
28 | ## Usage
29 |
30 | usage: pngattach -c PNG [FILE]...
31 | pngattach -d PNG [FILE]...
32 | pngattach -t \fIpng\fR [\fIfile\fR]...
7 | .br
8 | .B pngattach
9 | \fB-d\fR <\fIpng\fR >\fIpng\fR [\fIfile\fR]...
10 | .br
11 | .B pngattach
12 | \fB-t\fR <\fIpng\fR
13 | .br
14 | .B pngattach
15 | \fB-x\fR <\fIpng\fR
16 | .SH DESCRIPTION
17 | .B pngattach
18 | attaches an arbitrary file to a PNG as metadata.
19 | It is intended for attaching the source scripts from which the image was rendered.
20 | Attachments take the form of private "atCh" PNG chunks.
21 | PNG data is always read and written on standard input and output.
22 | .SH OPTIONS
23 | .TP
24 | \fB\-c\fR
25 | Create or update attachments.
26 | [default mode]
27 | .TP
28 | \fB\-d\fR
29 | Delete attachments by name
30 | .TP
31 | \fB\-t\fR
32 | List all attached files.
33 | .TP
34 | \fB\-x\fR
35 | Extract all attached files.
36 | .TP
37 | \fB\-h\fR
38 | Print usage information to standard output and exit.
39 | .TP
40 | \fB\-O\fR
41 | Write/concatenate attachments to standard output rather than to their individual file names.
42 | .TP
43 | \fB\-u\fR
44 | Do not compress attachments.
45 | .TP
46 | \fB\-v\fR
47 | Print file names while extracting them (i.e. verbose).
48 | .SH ENVIRONMENT
49 | .B pngattach
50 | is not affected by environment variables.
51 | .SH FILES
52 | .B pngattach
53 | is not affected by any files.
54 | .SH EXAMPLES
55 | .PP
56 | Attach the input source to a PNG just as it's being rendered.
57 | .RS 2
58 | .nf
59 | .B $ dot -Tpng graph.dot | pngattach graph.dot >graph.png
60 | .fi
61 | .RE
62 | .PP
63 | Recovering the source file later:
64 | .RS 2
65 | .nf
66 | .B $ pngattach -x graph.dot
74 | .fi
75 | .RE
76 | .SH "SEE ALSO"
77 | .BR tar(1),
78 | .BR dot(1)
79 | .SH AUTHORS
80 | Chris Wellons
81 | .SH BUGS
82 | No known bugs.
83 |
--------------------------------------------------------------------------------
/primesieve/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -O3 -march=native -Wall -Wextra
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | primes: main.c primesieve.c
8 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ main.c $(LDLIBS)
9 |
10 | clean:
11 | rm -f primes
12 |
--------------------------------------------------------------------------------
/primesieve/main.c:
--------------------------------------------------------------------------------
1 | #define __USE_MINGW_ANSI_STDIO
2 | #include
3 | #include
4 | #include "primesieve.c"
5 |
6 | int
7 | main(int argc, char *argv[])
8 | {
9 | unsigned long long n = strtoull(argv[argc - 1], 0, 10);
10 | struct primesieve *ps = primesieve_create(n);
11 | for (;;) {
12 | unsigned long long x = primesieve_next(ps);
13 | if (!x)
14 | break;
15 | printf("%lld\n", x);
16 | }
17 | free(ps);
18 | }
19 |
--------------------------------------------------------------------------------
/primesieve/primesieve.c:
--------------------------------------------------------------------------------
1 | /* Bitset Sieve of Eratosthenes
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #include
5 | #include
6 |
7 | #define LLONG_BIT (sizeof(unsigned long long) * CHAR_BIT)
8 | #define GET(a, i) (a[(i) / LLONG_BIT] >> ((i) % LLONG_BIT) & 1ULL)
9 | #define SET(a, i) (a[(i) / LLONG_BIT] |= 1ULL << ((i) % LLONG_BIT))
10 |
11 | struct primesieve {
12 | unsigned long long n;
13 | unsigned long long max;
14 | unsigned long long sieve[];
15 | };
16 |
17 | static struct primesieve *
18 | primesieve_create(unsigned long long max)
19 | {
20 | struct primesieve *ps;
21 | size_t size = (max / 2 + LLONG_BIT - 1) / LLONG_BIT * sizeof(ps->sieve[0]);
22 | ps = calloc(1, sizeof(*ps) + size);
23 | if (ps) {
24 | ps->n = 0;
25 | ps->max = max;
26 | }
27 | return ps;
28 | }
29 |
30 | static unsigned long long
31 | primesieve_next(struct primesieve *ps)
32 | {
33 | if (!ps->n++)
34 | return 2;
35 | for (; ps->n * 2 - 1 < ps->max; ps->n++) {
36 | unsigned long long x = ps->n * 2 - 1;
37 | if (!GET(ps->sieve, x / 2)) {
38 | for (unsigned long long i = x * 3; i < ps->max; i += x * 2)
39 | SET(ps->sieve, i / 2);
40 | return x;
41 | }
42 | }
43 | return 0;
44 | }
45 |
--------------------------------------------------------------------------------
/prips/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -ansi -pedantic -Os -Wall -Wextra
4 | LDFLAGS = -s
5 | LDLIBS =
6 | PREFIX = /usr/local
7 |
8 | prips$(EXE): prips.c
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ prips.c $(LDLIBS)
10 |
11 | install: prips$(EXE)
12 | mkdir -p $(DESTDIR)$(PREFIX)/bin
13 | mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
14 | install -m 755 prips$(EXE) $(DESTDIR)$(PREFIX)/bin
15 | gzip $(DESTDIR)$(PREFIX)/share/man/man1/prips.1.gz
16 |
17 | uninstall:
18 | rm -f $(DESTDIR)$(PREFIX)/bin/prips$(EXE)
19 | rm -f $(DESTDIR)$(PREFIX)/share/man/man1/prips.1.gz
20 |
21 | clean:
22 | rm -f prips$(EXE)
23 |
--------------------------------------------------------------------------------
/regex-wrap/GNUmakefile:
--------------------------------------------------------------------------------
1 | CROSS =
2 | CPPFLAGS = -Wall -Wextra -g3 -fsanitize=undefined -fsanitize-trap
3 | LDFLAGS =
4 |
5 | all: regex.dll main.exe
6 |
7 | regex.dll: regex.cpp regex.def
8 | $(CROSS)g++ -std=c++17 -shared $(CPPFLAGS) $(LDFLAGS) -o $@ $^
9 |
10 | regex.lib: regex.def
11 | $(CROSS)dlltool -d regex.def -l regex.lib
12 |
13 | main.exe: main.c regex.lib regex.h
14 | $(CROSS)gcc $(CPPFLAGS) $(LDFLAGS) -o main.exe main.c regex.lib
15 |
16 | clean:
17 | rm -f regex.dll regex.lib main.exe
18 |
--------------------------------------------------------------------------------
/regex-wrap/Makefile:
--------------------------------------------------------------------------------
1 | CXX = cl /nologo
2 | CPPFLAGS = /W4 /Z7
3 |
4 | all: regex.dll main.exe
5 |
6 | regex.dll regex.lib: regex.cpp regex.def
7 | $(CXX) /LD /std:c++17 /EHsc $(CPPFLAGS) regex.cpp /link /def:regex.def
8 |
9 | main.exe: main.c regex.lib regex.h
10 | $(CXX) $(CPPFLAGS) main.c regex.lib
11 |
12 | clean:
13 | if exist regex.dll del regex.dll
14 | if exist regex.lib del regex.lib
15 | if exist regex.obj del regex.obj
16 | if exist regex.pdb del regex.pdb
17 | if exist regex.ilk del regex.ilk
18 | if exist regex.exp del regex.exp
19 | if exist main.exe del main.exe
20 | if exist main.obj del main.obj
21 | if exist main.pdb del main.pdb
22 | if exist main.ilk del main.ilk
23 |
--------------------------------------------------------------------------------
/regex-wrap/README.md:
--------------------------------------------------------------------------------
1 | # std::regex wrapped in a minimalist C interface
2 |
3 | Demonstration of [Giving C++ std::regex a C makeover][txt].
4 |
5 | ## Build
6 |
7 | With w64devkit:
8 |
9 | $ make
10 |
11 | With MSVC:
12 |
13 | $ nmake
14 |
15 | With Clang:
16 |
17 | $ nmake CXX=clang-cl
18 |
19 |
20 | [txt]: https://nullprogram.com/blog/2024/09/04/
21 |
--------------------------------------------------------------------------------
/regex-wrap/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "regex.h"
4 |
5 | int main(void)
6 | {
7 | int cap = 1<<21;
8 | char *mem = malloc(cap);
9 | arena a = {mem, mem+cap};
10 |
11 | regex *re = regex_new(S("(\\w+)"), &a);
12 | str s = S("Hello, world! This is a test.");
13 | strlist m = regex_match(re, s, &a);
14 | for (ptrdiff_t i = 0; i < m.len; i++) {
15 | printf("%2td = %.*s\n", i, (int)m.data[i].len, m.data[i].data);
16 | }
17 |
18 | #if 0
19 | for (int i = 0; i < 30000; i++) {
20 | arena scratch = a;
21 | regex_match(re, s, &scratch);
22 | }
23 | #endif
24 | }
25 |
--------------------------------------------------------------------------------
/regex-wrap/regex.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | struct str {
6 | char *data;
7 | ptrdiff_t len;
8 | };
9 |
10 | struct arena {
11 | char *beg;
12 | char *end;
13 | };
14 |
15 | struct strlist {
16 | str *data;
17 | ptrdiff_t len;
18 | };
19 |
20 |
21 | // Allocation
22 |
23 | static thread_local arena *perm;
24 |
25 | void *operator new(size_t size, std::align_val_t align)
26 | {
27 | arena *a = perm;
28 | ptrdiff_t ssize = size;
29 | ptrdiff_t pad = (uintptr_t)a->end & ((int)align - 1);
30 | if (ssize < 0 || ssize > a->end - a->beg - pad) {
31 | throw std::bad_alloc{};
32 | }
33 | return a->end -= size + pad;
34 | }
35 |
36 | void *operator new(size_t size)
37 | {
38 | return operator new(
39 | size,
40 | std::align_val_t(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
41 | );
42 | }
43 |
44 | void operator delete(void *) noexcept {}
45 | void operator delete(void *, std::align_val_t) noexcept {}
46 |
47 | void operator delete(void *p, size_t size) noexcept
48 | {
49 | arena *a = perm;
50 | if (a->end == (char *)p) {
51 | a->end += size;
52 | }
53 | }
54 |
55 |
56 | // Implementation
57 |
58 | extern "C" std::regex *regex_new(str re, arena *a)
59 | {
60 | perm = a;
61 | try {
62 | return new std::regex(re.data, re.data+re.len);
63 | } catch (...) {
64 | return {};
65 | }
66 | }
67 |
68 | extern "C" strlist regex_match(std::regex *re, str s, arena *a)
69 | {
70 | perm = a;
71 | try {
72 | std::cregex_iterator it(s.data, s.data+s.len, *re);
73 | std::cregex_iterator end;
74 |
75 | strlist r = {};
76 | r.len = std::distance(it, end);
77 | r.data = new str[r.len]();
78 | for (ptrdiff_t i = 0; it != end; it++, i++) {
79 | r.data[i].data = s.data + it->position();
80 | r.data[i].len = it->length();
81 | }
82 | return r;
83 |
84 | } catch (...) {
85 | return {};
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/regex-wrap/regex.def:
--------------------------------------------------------------------------------
1 | LIBRARY regex
2 | EXPORTS
3 | regex_new
4 | regex_match
5 |
--------------------------------------------------------------------------------
/regex-wrap/regex.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #define S(s) (str){s, sizeof(s)-1}
5 |
6 | typedef struct {
7 | char *data;
8 | ptrdiff_t len;
9 | } str;
10 |
11 | typedef struct {
12 | char *beg;
13 | char *end;
14 | } arena;
15 |
16 | typedef struct regex regex;
17 |
18 | typedef struct {
19 | str *data;
20 | ptrdiff_t len;
21 | } strlist;
22 |
23 | regex *regex_new(str, arena *);
24 | strlist regex_match(regex *, str, arena *);
25 |
--------------------------------------------------------------------------------
/set32/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc -std=c99
3 | CFLAGS = -Wall -Wextra -O3
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | test: test.c set32.h
8 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test.c $(LDLIBS)
9 |
10 | clean:
11 | rm -f test
12 |
--------------------------------------------------------------------------------
/set32/README.md:
--------------------------------------------------------------------------------
1 | # C99 32-bit integer hash set header library
2 |
3 | This is a public domain header library defining a fast, lightweight
4 | integer hash set. It uses closed hashing and makes no allocations of its
5 | own. The API is dead simple:
6 |
7 | ~~~c
8 | int set32_z(uint32_t max);
9 | uint32_t set32_hash(uint32_t);
10 | void set32_insert(uint32_t *table, int z, uint32_t v);
11 | void set32_remove(uint32_t *table, int z, uint32_t v);
12 | int set32_contains(uint32_t *table, int z, uint32_t v);
13 | ~~~
14 |
15 | The `set32_z()` function returns the appropriate power-of-two table size
16 | for the given maximum number of set elements. It's up to the caller to
17 | allocate and zero-initialize this buffer. The hash set is unable to
18 | store the value 0.
19 |
--------------------------------------------------------------------------------
/set32/test.c:
--------------------------------------------------------------------------------
1 | #define _POSIX_C_SOURCE 200112L
2 | #define SET32_IMPLEMENTATION
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "set32.h"
8 |
9 | static uint32_t
10 | rand32(void)
11 | {
12 | static uint32_t x = UINT32_C(0x9f41f6af);
13 | x ^= x << 13;
14 | x ^= x >> 17;
15 | x ^= x << 5;
16 | return x;
17 | }
18 |
19 | int
20 | main(void)
21 | {
22 | static uint32_t data[100000];
23 | uint32_t n = sizeof(data) / sizeof(*data);
24 |
25 | int z = set32_z(n);
26 | uint32_t *table = calloc(sizeof(*table), UINT32_C(1) << z);
27 | printf("table size %12zu kB [%lu slots]\n",
28 | sizeof(*table) * (UINT32_C(1) << z) / 1024,
29 | (unsigned long)(UINT32_C(1) << z));
30 |
31 | struct timespec ts[2];
32 | clock_gettime(CLOCK_MONOTONIC, ts + 0);
33 |
34 | for (uint32_t i = 0; i < n; i++) {
35 | data[i] = rand32();
36 | assert(!set32_contains(table, z, data[i]));
37 | set32_insert(table, z, data[i]);
38 | }
39 |
40 | /* shuffle */
41 | for (uint32_t i = n - 1; i > 1; i--) {
42 | uint32_t j = rand32() % (i + 1);
43 | uint32_t tmp = data[j];
44 | data[j] = data[i];
45 | data[i] = tmp;
46 | }
47 |
48 | for (uint32_t i = 0; i < n; i++) {
49 | set32_remove(table, z, data[i]);
50 | for (uint32_t j = i + 1; j < n; j++)
51 | assert(set32_contains(table, z, data[j]));
52 | }
53 |
54 | clock_gettime(CLOCK_MONOTONIC, ts + 1);
55 |
56 | for (uint32_t i = 0; i < UINT32_C(1) << z; i++)
57 | assert(!table[i]);
58 |
59 | double seconds;
60 | if ((ts[1].tv_nsec - ts[0].tv_nsec) < 0) {
61 | seconds = ts[1].tv_sec - ts[0].tv_sec - 1 +
62 | (1e9 + ts[1].tv_nsec - ts[0].tv_nsec) / 1e9;
63 | } else {
64 | seconds = ts[1].tv_sec - ts[0].tv_sec +
65 | (ts[1].tv_nsec - ts[0].tv_nsec) / 1e9;
66 | }
67 |
68 | unsigned long long ninsert = n;
69 | unsigned long long nmember = ninsert + ninsert * (ninsert + 1) / 2;
70 | printf("time % 16.3fs\n", seconds);
71 | printf("insert % 16.3f / ms [%lu]\n",
72 | n / seconds / 1000, (unsigned long)n);
73 | printf("delete % 16.3f / ms [%lu]\n",
74 | n / seconds / 1000, (unsigned long)n);
75 | printf("member % 16.3f / us [%llu]\n",
76 | nmember / seconds / 1000000, nmember);
77 |
78 | free(table);
79 | }
80 |
--------------------------------------------------------------------------------
/sfcw/GNUmakefile:
--------------------------------------------------------------------------------
1 | CROSS = i686-w64-mingw32-
2 | CC = $(CROSS)gcc -ansi -pedantic
3 | WINDRES = $(CROSS)windres
4 | CFLAGS = -Os -march=i486 -mtune=generic -mno-stack-arg-probe \
5 | -fno-asynchronous-unwind-tables
6 | LDFLAGS = -s -Wl,--gc-sections -mwindows -nostdlib
7 | LDLIBS = -lkernel32 -luser32 -lgdi32 -lcomctl32
8 | sfcw.exe: sfcw.c resource.o
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ sfcw.c resource.o $(LDLIBS)
10 | resource.o: resource.rc sfcw.ico sfcw.exe.manifest
11 | $(WINDRES) -o $@ resource.rc
12 | clean:
13 | rm -f resource.o sfcw.exe
14 |
--------------------------------------------------------------------------------
/sfcw/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS = /O2
2 | sfcw.exe: sfcw.c resource.res
3 | $(CC) $(CFLAGS) sfcw.c resource.res
4 | clean:
5 | if exist resource.res del resource.res
6 | if exist sfcw.exe del sfcw.exe
7 | if exist sfcw.obj del sfcw.obj
8 |
--------------------------------------------------------------------------------
/sfcw/README.md:
--------------------------------------------------------------------------------
1 | # Starflight Code Wheel
2 |
3 | A digital code wheel for [Starflight][], a 1986 game by Binary Systems.
4 | This is the game's copy protection system and is needed when leaving the
5 | space station. This is essentially a clone of [Pat Shearon's program][r],
6 | but without the hefty .NET requirement. If built using the 32-bit variant
7 | of [w64devkit][], or a very old MSVC, it should run on computers as old as
8 | Windows 95.
9 |
10 | [Starflight]: https://en.wikipedia.org/wiki/Starflight
11 | [r]: http://www.starflt.com/tables/
12 | [w64devkit]: https://github.com/skeeto/w64devkit
13 |
--------------------------------------------------------------------------------
/sfcw/resource.rc:
--------------------------------------------------------------------------------
1 | 1 ICON "sfcw.ico"
2 | CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "sfcw.exe.manifest"
3 |
--------------------------------------------------------------------------------
/sfcw/sfcw.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sfcw/sfcw.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/sfcw/sfcw.ico
--------------------------------------------------------------------------------
/siphash/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -g -Og -fsanitize=address -fsanitize=undefined -Wall -Wextra
4 | LDFLAGS = -fsanitize=address -fsanitize=undefined
5 | LDLIBS =
6 |
7 | test: test.c siphash.c siphash.h
8 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test.c siphash.c $(LDLIBS)
9 |
10 | check: test
11 | ./test
12 |
13 | clean:
14 | rm -f test test.exe
15 |
--------------------------------------------------------------------------------
/siphash/README.md:
--------------------------------------------------------------------------------
1 | # Incremental SipHash in C
2 |
3 | Incremental, public domain, portable C implementation of [SipHash][sh], a
4 | keyed hash function. It has [a minimalist interface][min] and makes no
5 | allocations. It defines no extraneous macros or functions, making it perfect
6 | for embedding and amalgamation.
7 |
8 | ```c
9 | void siphash_init(struct siphash *, const void *key);
10 | void siphash_update(struct siphash *, const void *, size_t);
11 | uint64_t siphash_final(const struct siphash *);
12 |
13 | void siphash_init128(struct siphash *, const void *key);
14 | void siphash_final128(const struct siphash *, void *digest);
15 | ```
16 |
17 | In Go style, finalization function does not modify the context, allowing more
18 | input to be appended after the digest is computed. To clone the context, copy
19 | it.
20 |
21 | For a non-incremental, header library of SipHash: [**siphash-embed.h**][hdr].
22 |
23 |
24 | [hdr]: siphash-embed.h
25 | [min]: https://nullprogram.com/blog/2018/06/10/
26 | [sh]: https://cr.yp.to/siphash/siphash-20120620.pdf
27 |
--------------------------------------------------------------------------------
/siphash/siphash.h:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 | #include
3 | #include
4 |
5 | #define SIPHASH_KEYLEN 16
6 | #define SIPHASH_OUTLEN 16
7 |
8 | struct siphash {
9 | uint64_t v0, v1, v2, v3;
10 | uint64_t m;
11 | };
12 |
13 | void siphash_init(struct siphash *, const void *key);
14 | void siphash_update(struct siphash *, const void *, size_t);
15 | uint64_t siphash_final(const struct siphash *);
16 |
17 | void siphash_init128(struct siphash *, const void *key);
18 | void siphash_final128(const struct siphash *, void *digest);
19 |
--------------------------------------------------------------------------------
/skipjack/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -ansi -pedantic -g -O3 -march=native
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | all: tests/dump tests/test
8 |
9 | check: tests/test
10 | tests/test
11 |
12 | clean:
13 | rm -rf tests/dump tests/test
14 |
15 | tests/dump: tests/dump.c skipjack.h
16 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests/dump.c $(LDLIBS)
17 |
18 | tests/test: tests/test.c skipjack.h
19 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests/test.c $(LDLIBS)
20 |
--------------------------------------------------------------------------------
/skipjack/README.md:
--------------------------------------------------------------------------------
1 | # Skipjack C89 header file library
2 |
3 | This is a strictly conforming C89 implementation of the [Skipjack
4 | cipher][w] ([PDF][p], [HTML][h]) as an embeddable, single-file header
5 | library. Keys are 80 bits long, blocks are 64 bits wide, 31 of 32 rounds
6 | have long been broken, and there is no key setup. Only the encryption
7 | function is implemented since that's sufficient for analysis, it's
8 | enough to operate in CTR mode, and I really didn't feel like working out
9 | decryption. The library is optimized for compactness and correctness,
10 | not performance.
11 |
12 | ```c
13 | void skipjack_encrypt(const void *key, void *block);
14 | ```
15 |
16 | [h]: https://cryptome.org/jya/skipjack-spec.htm
17 | [p]: https://web.archive.org/web/20010603000755/http://csrc.nist.gov/encryption/skipjack/skipjack.pdf
18 | [w]: https://en.wikipedia.org/wiki/Skipjack_(cipher)
19 |
--------------------------------------------------------------------------------
/skipjack/tests/dump.c:
--------------------------------------------------------------------------------
1 | #include "../skipjack.h"
2 | #include
3 |
4 | int
5 | main(void)
6 | {
7 | int i;
8 | unsigned long c[2] = {0, 0};
9 | static unsigned char buf[1<<9][8];
10 | unsigned char key[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
11 | do {
12 | for (i = 0; i < (int)(sizeof(buf)/sizeof(buf[0])); i++) {
13 | buf[i][0] = c[1] >> 24;
14 | buf[i][1] = c[1] >> 26;
15 | buf[i][2] = c[1] >> 8;
16 | buf[i][3] = c[1] >> 0;
17 | buf[i][4] = c[0] >> 24;
18 | buf[i][5] = c[0] >> 16;
19 | buf[i][6] = c[0] >> 8;
20 | buf[i][7] = c[0] >> 0;
21 | c[0] = (c[0] + 1) & 0xffffffffUL;
22 | c[0] += !c[0];
23 | skipjack_encrypt(key, buf + i);
24 | }
25 | } while (fwrite(buf, sizeof(buf), 1, stdout));
26 | return 0;
27 | }
28 |
--------------------------------------------------------------------------------
/skipjack/tests/test.c:
--------------------------------------------------------------------------------
1 | #include "../skipjack.h"
2 | #include
3 | #include
4 |
5 | static void
6 | print(unsigned char *a)
7 | {
8 | printf("%02x%02x%02x%02x%02x%02x%02x%02x",
9 | a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
10 | }
11 |
12 | int
13 | main(void)
14 | {
15 | unsigned char key[] = {
16 | 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
17 | };
18 | unsigned char b[] = {0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa};
19 | unsigned char e[] = {0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00};
20 | skipjack_encrypt(key, b);
21 | if (!memcmp(b, e, sizeof(b))) {
22 | fputs("\x1b[92;1mPASS\x1b[0m: ", stdout);
23 | print(e);
24 | fputs(" == ", stdout);
25 | print(b);
26 | putchar('\n');
27 | } else {
28 | fputs("\x1b[91;1mFAIL\x1b[0m: ", stdout);
29 | print(e);
30 | fputs(" == ", stdout);
31 | print(b);
32 | putchar('\n');
33 | }
34 | return 0;
35 | }
36 |
--------------------------------------------------------------------------------
/sp4/sp4.c:
--------------------------------------------------------------------------------
1 | /* Sponge4 sponge-like hash function
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 |
5 | void
6 | sp4_absorb(unsigned char s[259], int byte)
7 | {
8 | int t;
9 |
10 | /* Initialize? */
11 | if (s[0] == s[1])
12 | for (t = 0; t < 256; t++)
13 | s[t] = t;
14 |
15 | /* Absorb using key schedule */
16 | s[257] += s[s[256]] + byte;
17 | /* swap s[i] and s[j] */
18 | t = s[s[256]];
19 | s[s[256]] = s[s[257]];
20 | s[s[257]] = t;
21 |
22 | /* Increment counters */
23 | s[256]++; /* i */
24 | s[258]++; /* k */
25 | }
26 |
27 | void
28 | sp4_absorb_stop(unsigned char s[259])
29 | {
30 | s[257]++;
31 | }
32 |
33 | int
34 | sp4_squeeze(unsigned char s[259])
35 | {
36 | int t;
37 |
38 | /* Pad input? */
39 | if (s[258]) {
40 | /* Insert a stop between input and padding */
41 | sp4_absorb_stop(s);
42 | /* Pad with the count of remaining pad bytes */
43 | do sp4_absorb(s, s[258]); while (s[258]);
44 | }
45 |
46 | /* Run a single iteration of the generator */
47 | s[257] += s[256]++;
48 | /* swap s[i] and s[j] */
49 | t = s[s[256]];
50 | s[s[256]] = s[s[257]];
51 | s[s[257]] = t;
52 | return s[(s[s[256]] + s[s[257]]) % 256];
53 | }
54 |
--------------------------------------------------------------------------------
/sp4/sponge4.lua:
--------------------------------------------------------------------------------
1 | -- Sponge4: a simple sponge based on RC4
2 | -- https://redd.it/a9k8yj
3 | --
4 | -- sponge4 = require('sponge4')
5 | -- local input = 'hello world'
6 | -- local s = sponge4.new()
7 | -- for i = 1, #input do
8 | -- s:absorb(input:byte(i))
9 | -- end
10 | -- s:squeeze() -- 103
11 | -- s:squeeze() -- 239
12 | -- s:squeeze() -- 169
13 |
14 | local sponge4 = {}
15 | sponge4.__index = sponge4
16 |
17 | local init = {}
18 | for i = 1, 256 do
19 | init[i] = i - 1
20 | end
21 |
22 | -- Create a new sponge in the default state.
23 | function sponge4.new()
24 | return setmetatable({i = 0, j = 0, k = 0, table.unpack(init)}, sponge4)
25 | end
26 |
27 | -- Absorb a single byte (0-255) into the sponge.
28 | function sponge4:absorb(byte)
29 | self.j = (self.j + self[self.i + 1] + byte) % 256
30 | self[self.i + 1], self[self.j + 1] = self[self.j + 1], self[self.i + 1]
31 | self.j = (self.j + 1) % 256
32 | self.k = (self.k + 1) % 256
33 | end
34 |
35 | -- Absorb the special "stop" symbol into the sponge.
36 | function sponge4:stop()
37 | self.j = (self.j + 1) % 256
38 | end
39 |
40 | -- Squeeze a single byte (0-255) of output from the sponge.
41 | function sponge4:squeeze()
42 | if self.k > 0 then
43 | self:stop(self)
44 | repeat
45 | self:absorb(self.k)
46 | until self.k == 0
47 | end
48 |
49 | self.j = (self.j + self.i) % 256
50 | self.i = (self.i + 1) % 256
51 | self[self.i + 1], self[self.j + 1] = self[self.j + 1], self[self.i + 1]
52 | return self[1 + (self[self.i + 1] + self[self.j + 1]) % 256]
53 | end
54 |
55 | return sponge4
56 |
--------------------------------------------------------------------------------
/spaceship/README.md:
--------------------------------------------------------------------------------
1 | # Procedurally-generated pixel spaceship renderer
2 |
3 | Based on [Dave Bollinger's Pixel Spaceships][db].
4 |
5 | 
6 |
7 | [db]: http://davebollinger.org/works/pixelspaceships/
8 |
--------------------------------------------------------------------------------
/spaceship/examples.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skeeto/scratch/d0023e733a45b4ce7758467ca7b79f82584d2272/spaceship/examples.png
--------------------------------------------------------------------------------
/speck/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc -std=c99
3 | CFLAGS = -Wall -Wextra -O3 -march=native -g3
4 | LDFLAGS =
5 | LDLIBS =
6 |
7 | all: tests speckcrypt
8 | speckcrypt: speckcrypt.c speck.h
9 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ speckcrypt.c $(LDLIBS)
10 | tests: tests.c speck.h
11 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests.c $(LDLIBS)
12 | test: check
13 | check: tests
14 | ./tests
15 | clean:
16 | rm -f tests speckcrypt
17 |
--------------------------------------------------------------------------------
/speck/README.md:
--------------------------------------------------------------------------------
1 | # C99 implementation of Speck128/128
2 |
3 | This is a public domain implementation of [NSA's Speck cipher][spec]
4 | ([update][update]), specificially the 128-bit block, 128-bit key
5 | variant. It's provided as a header library with three functions:
6 |
7 | ~~~c
8 | void speck_init(struct speck *, uint64_t, uint64_t);
9 | void speck_encrypt(const struct speck *, uint64_t *, uint64_t *);
10 | void speck_decrypt(const struct speck *, uint64_t *, uint64_t *);
11 | ~~~
12 |
13 | [spec]: http://eprint.iacr.org/2013/404.pdf
14 | [update]: https://eprint.iacr.org/2017/560.pdf
15 |
--------------------------------------------------------------------------------
/speck/speck.h:
--------------------------------------------------------------------------------
1 | /* C99 implementation of Speck128/128
2 | * This is free and unencumbered software released into the public domain.
3 | */
4 | #ifndef SPECK_H
5 | #define SPECK_H
6 |
7 | #include
8 |
9 | struct speck {
10 | uint64_t k[32];
11 | };
12 |
13 | static void
14 | speck_init(struct speck *ctx, uint64_t x, uint64_t y)
15 | {
16 | ctx->k[0] = y;
17 | for (uint64_t i = 0; i < 31; i++) {
18 | x = x>>8 | x<<56;
19 | x += y;
20 | x ^= i;
21 | y = y<<3 | y>>61;
22 | y ^= x;
23 | ctx->k[i+1] = y;
24 | }
25 | }
26 |
27 | static void
28 | speck_encrypt(const struct speck *ctx, uint64_t *px, uint64_t *py)
29 | {
30 | uint64_t x = *px;
31 | uint64_t y = *py;
32 | for (int i = 0; i < 32; i++) {
33 | x = x>>8 | x<<56;
34 | x += y;
35 | x ^= ctx->k[i];
36 | y = y<<3 | y>>61;
37 | y ^= x;
38 | }
39 | *px = x;
40 | *py = y;
41 | }
42 |
43 | static void
44 | speck_decrypt(const struct speck *ctx, uint64_t *px, uint64_t *py)
45 | {
46 | uint64_t x = *px;
47 | uint64_t y = *py;
48 | for (int i = 31; i >= 0; i--) {
49 | y ^= x;
50 | y = y>>3 | y<<61;
51 | x ^= ctx->k[i];
52 | x -= y;
53 | x = x<<8 | x>>56;
54 | }
55 | *px = x;
56 | *py = y;
57 | }
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/speck/tests.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "speck.h"
4 |
5 | static int tests = 0;
6 | static int failures = 0;
7 |
8 | #define ASSERT(s, a, b) \
9 | do { \
10 | tests++; \
11 | if (a[0] != b[0] || a[1] != b[1]) { \
12 | failures++; \
13 | puts("FAIL: " s); \
14 | } \
15 | } while (0)
16 |
17 | int
18 | main(void)
19 | {
20 | /* Official test vector for Speck128/128 */
21 | uint64_t k[2] = {0x0f0e0d0c0b0a0908, 0x0706050403020100};
22 | uint64_t p[2] = {0x6c61766975716520, 0x7469206564616d20};
23 | uint64_t c[2] = {0xa65d985179783265, 0x7860fedf5c570d18};
24 |
25 | struct speck ctx[1];
26 | uint64_t t[2] = {p[0], p[1]};
27 | speck_init(ctx, k[0], k[1]);
28 | speck_encrypt(ctx, t + 0, t + 1);
29 | ASSERT("Speck128/128 encrypt", c, t);
30 | speck_decrypt(ctx, t + 0, t + 1);
31 | ASSERT("Speck128/128 decrypt", p, t);
32 |
33 | printf("RESULTS: %d / %d tests pass\n", tests - failures, tests);
34 | return !!failures;
35 | }
36 |
--------------------------------------------------------------------------------
/splitxix33/README.md:
--------------------------------------------------------------------------------
1 | # splitxix33: a splitmix64 with memorable constants
2 |
3 | An alternate, memorable set of constants for [splitmix64][] which pass
4 | BigCrush ~~and PractRand as well as the original constants~~(update: see
5 | [issue #2][issue]). Unlike the originals, these constants are trivial to
6 | memorize:
7 |
8 | * `1111111111111111111`: gamma and multipliers. That's 19 ones in a row,
9 | *in decimal*, which is the source of "xix" in the name — roman numerals
10 | for 19. It's a 60-bit prime number you'll never forget.
11 |
12 | * `33` for all shifts. That's more repeated digits, also easy to remember.
13 |
14 | As with splitmix64, the state is a 64-bit number seeded to any value. To
15 | generate a number:
16 |
17 | 1. Increment the state by the gamma.
18 | 2. Compute the output by permuting the state with xorshift-multiply: three
19 | xorshifts and two multiplications.
20 |
21 | An implementation of the above in C with parallel structure aligned:
22 |
23 | ```c
24 | uint64_t splitxix33(uint64_t *s)
25 | {
26 | uint64_t r = (*s += 1111111111111111111U);
27 | r ^= r >> 33; r *= 1111111111111111111U;
28 | r ^= r >> 33; r *= 1111111111111111111U;
29 | r ^= r >> 33;
30 | return r;
31 | }
32 | ```
33 |
34 | Seeded with zero, the first 40 outputs:
35 |
36 | 08ec1e74558178c5 947f9aa19cb7c821 1555b23290711f92 a288720b099045ac
37 | 334a218b8c7a05ac 11117b240349bbc0 4b88f7f61d21a04b ea5e92a52842224b
38 | da034f3f12489228 cb960f1884c43120 2d28d34a979bbec4 c2d03f5d348b8d25
39 | 2e4bb4f76a8e60a4 a67d6597ceae9bec e88421bd490fbabf 6aa9dcde0194f95a
40 | 8cfaab261b46a636 284acfc4201747ae abaa3de698b72836 7d2506cfad9308f5
41 | 23ac00d48e99cc25 8fcf0837b498207b 9fe3f976325613db 7c7fc562afc29e12
42 | add603a1bec84981 46ea2435b7ff13bc b440df05e70d1ba9 68e36431de0dc0b4
43 | 0a94f0882dc7f970 22217ee019d136e3 1a67957cfe4023cf a9570d249f16eddd
44 | e49c275cdf63a031 1715cd7997c8691a be73943982f5d575 910429556a34d2f5
45 | bfeb360427b31d93 fca22a5c38d9ca7f 51a22288913ba6ac 63006e51981b9c23
46 |
47 |
48 | [issue]: https://github.com/skeeto/scratch/issues/2
49 | [splitmix64]: http://gee.cs.oswego.edu/dl/papers/oopsla14.pdf
50 |
--------------------------------------------------------------------------------
/splitxix33/Splitxix33.java:
--------------------------------------------------------------------------------
1 | // splitxix33: a splitmix64 with memorable constants
2 | // This is free and unencumbered software released into the public domain.
3 | public class Splitxix33 {
4 | public long s;
5 | public Splitxix33 (long seed) { s = seed; }
6 |
7 | public long next() {
8 | long r = (this.s += 1111111111111111111L);
9 | r ^= r >>> 33; r *= 1111111111111111111L;
10 | r ^= r >>> 33; r *= 1111111111111111111L;
11 | r ^= r >>> 33;
12 | return r;
13 | }
14 |
15 | public static void main(String[] args) {
16 | Splitxix33 g[] = {
17 | new Splitxix33(0), new Splitxix33(1),
18 | new Splitxix33(2), new Splitxix33(3),
19 | };
20 | for (int i = 0; i < 40; i++) {
21 | System.out.printf("%016x %016x %016x %016x\n",
22 | g[0].next(), g[1].next(),
23 | g[2].next(), g[3].next());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.c:
--------------------------------------------------------------------------------
1 | // splitxix33: a splitmix64 with memorable constants
2 | // This is free and unencumbered software released into the public domain.
3 | #include
4 |
5 | uint64_t
6 | splitxix33(uint64_t s[1])
7 | {
8 | uint64_t r = (*s += 1111111111111111111U);
9 | r ^= r >> 33; r *= 1111111111111111111U;
10 | r ^= r >> 33; r *= 1111111111111111111U;
11 | r ^= r >> 33;
12 | return r;
13 | }
14 |
15 |
16 | // Example
17 | #include
18 |
19 | int
20 | main(void)
21 | {
22 | #define N 40
23 | char buf[68*N + 1];
24 | uint64_t s[4] = {0, 1, 2, 3};
25 | for (int i = 0; i < N; i++) {
26 | unsigned long long a = splitxix33(s+0);
27 | unsigned long long b = splitxix33(s+1);
28 | unsigned long long c = splitxix33(s+2);
29 | unsigned long long d = splitxix33(s+3);
30 | sprintf(buf + i*68, "%016llx %016llx %016llx %016llx\n", a, b, c, d);
31 | }
32 | return !(fwrite(buf, 68, N, stdout) == N);
33 | }
34 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.cc:
--------------------------------------------------------------------------------
1 | // splitxix33: a splitmix64 with memorable constants
2 | // This is free and unencumbered software released into the public domain.
3 | #include
4 | #include
5 |
6 | std::function
7 | splitxix33(uint64_t seed)
8 | {
9 | uint64_t x = seed;
10 | return [=]() mutable {
11 | uint64_t r = (x += 1111111111111111111U);
12 | r ^= r >> 33; r *= 1111111111111111111U;
13 | r ^= r >> 33; r *= 1111111111111111111U;
14 | r ^= r >> 33;
15 | return r;
16 | };
17 | }
18 |
19 |
20 | // Example
21 | #include
22 |
23 | int
24 | main()
25 | {
26 | std::function f[] = {
27 | splitxix33(0), splitxix33(1), splitxix33(2), splitxix33(3)
28 | };
29 | #define N 40
30 | char buf[68*N + 1];
31 | for (int i = 0; i < N; i++) {
32 | unsigned long long a = f[0]();
33 | unsigned long long b = f[1]();
34 | unsigned long long c = f[2]();
35 | unsigned long long d = f[3]();
36 | sprintf(buf + i*68, "%016llx %016llx %016llx %016llx\n", a, b, c, d);
37 | }
38 | return !(fwrite(buf, 68, N, stdout) == N);
39 | }
40 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.el:
--------------------------------------------------------------------------------
1 | ;; splitxix33: a splitmix64 with memorable constants -*- lexical-binding: t; -*-
2 | ;; This is free and unencumbered software released into the public domain.
3 |
4 | (defun splitxix33 (seed)
5 | (let ((s seed))
6 | (lambda ()
7 | (let ((r (setf s (logand #xffffffffffffffff (+ s 1111111111111111111)))))
8 | (setf r (logxor r (lsh r -33))
9 | r (logand #xffffffffffffffff (* r 1111111111111111111))
10 | r (logxor r (lsh r -33))
11 | r (logand #xffffffffffffffff (* r 1111111111111111111))
12 | r (logxor r (lsh r -33)))))))
13 |
14 |
15 | ;; Example
16 | (let ((a (splitxix33 0)) (b (splitxix33 1))
17 | (c (splitxix33 2)) (d (splitxix33 3)))
18 | (dotimes (_ 40)
19 | (princ (format "%016x %016x %016x %016x\n"
20 | (funcall a) (funcall b) (funcall c) (funcall d)))))
21 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.go:
--------------------------------------------------------------------------------
1 | // splitxix33: a splitmix64 with memorable constants
2 | // This is free and unencumbered software released into the public domain.
3 | package main
4 |
5 | import (
6 | "fmt"
7 | "math/rand"
8 | )
9 |
10 | type Splitxix33 uint64
11 |
12 | var _ rand.Source64 = (*Splitxix33)(nil)
13 |
14 | func (s *Splitxix33) Seed(seed int64) {
15 | *s = Splitxix33(seed)
16 | }
17 |
18 | func (s *Splitxix33) Int63() int64 {
19 | return int64(s.Uint64() >> 1)
20 | }
21 |
22 | func (s *Splitxix33) Uint64() uint64 {
23 | *s += 1111111111111111111
24 | x := uint64(*s)
25 | x ^= x >> 33
26 | x *= 1111111111111111111
27 | x ^= x >> 33
28 | x *= 1111111111111111111
29 | x ^= x >> 33
30 | return x
31 | }
32 |
33 | func main() {
34 | g := [...]Splitxix33{0, 1, 2, 3}
35 | for i := 0; i < 40; i++ {
36 | fmt.Printf("%016x %016x %016x %016x\n",
37 | g[0].Uint64(), g[1].Uint64(), g[2].Uint64(), g[3].Uint64())
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.js:
--------------------------------------------------------------------------------
1 | // splitxix33: a splitmix64 with memorable constants
2 | // This is free and unencumbered software released into the public domain.
3 | function splitxix33(seed) {
4 | let s = BigInt(seed)
5 | return function() {
6 | s += 1111111111111111111n; s &= 0xffffffffffffffffn
7 | let r = s ^ s>>33n;
8 | r *= 1111111111111111111n; r &= 0xffffffffffffffffn; r ^= r >> 33n
9 | r *= 1111111111111111111n; r &= 0xffffffffffffffffn; r ^= r >> 33n
10 | return r
11 | }
12 | }
13 |
14 | let g = [splitxix33(0), splitxix33(1), splitxix33(2), splitxix33(3)]
15 | for (let i = 0; i < 40; i++) {
16 | function f(x) { return ("0000000000000000" + x.toString(16)).slice(-16) }
17 | console.log(f(g[0]()), f(g[1]()), f(g[2]()), f(g[3]()))
18 | }
19 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.lua:
--------------------------------------------------------------------------------
1 | -- splitxix33: a splitmix64 with memorable constants
2 | -- This is free and unencumbered software released into the public domain.
3 |
4 | function splitxix33(seed)
5 | return function()
6 | seed = seed + 1111111111111111111
7 | local r = seed
8 | r = r ~ r >> 33; r = r * 1111111111111111111
9 | r = r ~ r >> 33; r = r * 1111111111111111111
10 | r = r ~ r >> 33
11 | return r
12 | end
13 | end
14 |
15 | local g = {splitxix33(0), splitxix33(1), splitxix33(2), splitxix33(3)}
16 | for i = 1, 40 do
17 | print(string.format("%016x %016x %016x %016x",
18 | g[1](), g[2](), g[3](), g[4]()))
19 | end
20 |
--------------------------------------------------------------------------------
/splitxix33/splitxix33.py:
--------------------------------------------------------------------------------
1 | # splitxix33: a splitmix64 with memorable constants
2 | # This is free and unencumbered software released into the public domain.
3 | import numpy
4 | import typing
5 |
6 | numpy.seterr(over="ignore")
7 |
8 | def splitxix33(seed: int) -> typing.Generator[int, None, None]:
9 | m: numpy.uint64 = numpy.uint64(1111111111111111111)
10 | s: numpy.uint64 = numpy.uint64(33)
11 | x: numpy.uint64 = numpy.uint64(seed)
12 | r: numpy.uint64
13 | while True:
14 | x += m
15 | r = x; r ^= r >> s
16 | r *= m; r ^= r >> s
17 | r *= m; r ^= r >> s
18 | yield int(r)
19 |
20 |
21 | # Example
22 | g = tuple(splitxix33(i) for i in range(4))
23 | for _ in range(40):
24 | print(*(f"{next(g):016x}" for g in g))
25 |
--------------------------------------------------------------------------------
/uuid/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = cc
3 | CFLAGS = -std=c99 -O3 -Wall -Wextra
4 | LDFLAGS = -s
5 | LDLIBS =
6 |
7 | uuidgen$(EXE): etc/main.c uuidgen.c uuidgen.h
8 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ etc/main.c uuidgen.c $(LDLIBS)
9 |
10 | clean:
11 | rm -f uuidgen$(EXE)
12 |
--------------------------------------------------------------------------------
/uuid/README.md:
--------------------------------------------------------------------------------
1 | # Fast, secure, embeddable UUID generator for C
2 |
3 | Supports Linux, \*BSD, Windows, and macOS — and probably more by accident.
4 |
5 | ## Usage example
6 |
7 | ```c
8 | char buf[37];
9 | struct uuidgen g = UUIDGEN_INIT;
10 |
11 | uuidgen(&g, buf);
12 | buf[36] = 0;
13 | puts(buf);
14 | ```
15 |
16 | `etc/main.c` is a command line UUID generator, too.
17 |
18 | ## Other implementations
19 |
20 | This repository also includes UUID generators for other languages.
21 |
--------------------------------------------------------------------------------
/uuid/uuid.js:
--------------------------------------------------------------------------------
1 | /* This is free and unencumbered software released into the public domain. */
2 |
3 | /**
4 | * Generate and return a new UUID. This function makes no allocations
5 | * except for the returned string.
6 | */
7 | let UUID = (function() {
8 | const HEX = '0123456789abcdef'.split(/(?:)/);
9 | const VER = '89ab'.split(/(?:)/);
10 | const out = '........-....-4...-v...-............'.split(/(?:)/);
11 | const raw = new Uint8Array(16);
12 | return function UUID() {
13 | window.crypto.getRandomValues(raw);
14 | out[ 0] = HEX[raw[ 0] >> 4];
15 | out[ 1] = HEX[raw[ 0] & 15];
16 | out[ 2] = HEX[raw[ 1] >> 4];
17 | out[ 3] = HEX[raw[ 1] & 15];
18 | out[ 4] = HEX[raw[ 2] >> 4];
19 | out[ 5] = HEX[raw[ 2] & 15];
20 | out[ 6] = HEX[raw[ 3] >> 4];
21 | out[ 7] = HEX[raw[ 3] & 15];
22 | out[ 9] = HEX[raw[ 4] >> 4];
23 | out[10] = HEX[raw[ 4] & 15];
24 | out[11] = HEX[raw[ 5] >> 4];
25 | out[12] = HEX[raw[ 5] & 15];
26 | out[15] = HEX[raw[ 6] & 15];
27 | out[16] = HEX[raw[ 7] >> 4];
28 | out[17] = HEX[raw[ 7] & 15];
29 | out[19] = VER[raw[ 8] & 3];
30 | out[20] = HEX[raw[ 8] & 15];
31 | out[21] = HEX[raw[ 9] >> 4];
32 | out[22] = HEX[raw[ 9] & 15];
33 | out[24] = HEX[raw[10] >> 4];
34 | out[25] = HEX[raw[10] & 15];
35 | out[26] = HEX[raw[11] >> 4];
36 | out[27] = HEX[raw[11] & 15];
37 | out[28] = HEX[raw[12] >> 4];
38 | out[29] = HEX[raw[12] & 15];
39 | out[30] = HEX[raw[13] >> 4];
40 | out[31] = HEX[raw[13] & 15];
41 | out[32] = HEX[raw[14] >> 4];
42 | out[33] = HEX[raw[14] & 15];
43 | out[34] = HEX[raw[15] >> 4];
44 | out[35] = HEX[raw[15] & 15];
45 | return out.join('');
46 | };
47 | }());
48 |
--------------------------------------------------------------------------------
/uuid/uuidgen.h:
--------------------------------------------------------------------------------
1 | // This is free and unencumbered software released into the public domain.
2 | #ifndef UUID_H
3 | #define UUID_H
4 |
5 | #include
6 |
7 | // UUID generator, initialize to all zeros (UUIDGEN_INIT).
8 | struct uuidgen {
9 | uint32_t s[16];
10 | char tmp[3][36];
11 | int n;
12 | };
13 | #define UUIDGEN_INIT {.n = 0}
14 |
15 | // Generate one v4 UUID and write exactly 36 bytes to the destination.
16 | // Does not include a terminating null byte.
17 | void uuidgen(struct uuidgen *, char *);
18 |
19 | #endif // UUID_H
20 |
--------------------------------------------------------------------------------
/w32bundle/.gitignore:
--------------------------------------------------------------------------------
1 | *.dll
2 | *.exe
3 | *.stub
4 |
--------------------------------------------------------------------------------
/w32bundle/GNUmakefile:
--------------------------------------------------------------------------------
1 | CC = cc
2 | CPPFLAGS = -g3 -Wall -Wextra -Wconversion -fsanitize=undefined -fsanitize-trap
3 |
4 | all: builder.exe builderw.exe
5 |
6 | builder.exe: builder.cpp common.cpp loader.stub
7 | $(CC) -nostartfiles -DLOADER='u"loader.stub"' $(CPPFLAGS) -o $@ $<
8 |
9 | builderw.exe: builder.cpp common.cpp loaderw.stub
10 | $(CC) -nostartfiles -DLOADER='u"loaderw.stub"' $(CPPFLAGS) -o $@ $<
11 |
12 | loader.stub: loader.cpp common.cpp
13 | $(CC) -nostartfiles $(CPPFLAGS) -o $@ $<
14 |
15 | loaderw.stub: loader.cpp common.cpp
16 | $(CC) -nostartfiles -mwindows -e mainCRTStartup $(CPPFLAGS) -o $@ $<
17 |
18 | message.dll: message.c
19 | $(CC) -nostdlib -shared -s -e0 -o $@ $<
20 |
21 | test.exe: test.c message.dll
22 | $(CC) -s -O -o $@ $^
23 |
24 | wrap.exe: builder.exe loader.stub test.exe message.dll
25 | ./builder test.exe message.dll >$@
26 |
27 | clean:
28 | rm -f builder.exe loader.stub builderw.exe loaderw.stub \
29 | message.dll test.exe wrap.exe
30 |
--------------------------------------------------------------------------------
/w32bundle/README.md:
--------------------------------------------------------------------------------
1 | # Win32 Bundler
2 |
3 | Bundles an application with its runtime and data into a single EXE. When
4 | executed, the wrapper EXE dumps all the files in a unique directory in the
5 | temporary directory, runs the first file, waits for it to exit, cleans up,
6 | and passes through the original exit status.
7 |
8 | Files are concatenated to the "loader" stub program with a file listing.
9 | No linker or other build tools are needed when bundling an application.
10 | The file bundle is a 4-byte-aligned block of data, beginning with a file
11 | listing, one entry per file, plus a terminating zero entry:
12 |
13 | ```c
14 | struct entry {
15 | i32 name_offset;
16 | i32 data_offset;
17 | i32 data_length;
18 | };
19 | ```
20 |
21 | Offsets are relative to the start of the block. Names are aligned,
22 | null-terminated, [potentially ill-formed UTF-16][UTF-16] ready for use
23 | with in any Win32 API. The block ends with an aligned 32-bit integer
24 | giving its total size, including size integer. This integer is located at
25 | the end of the wrapper EXE, from which the wrapper can find the beginning
26 | of the bundle and so the file listing.
27 |
28 | `builder.exe` creates a console subsystem wrapper, and `builderw.exe`
29 | creates a windows subsystem wrapper (e.g. for GUI applications). This is
30 | done using different stubs compiled for each subsystem. A smarter version
31 | would flip the appropriate bit in the stub PE image so that only one stub
32 | is necessary.
33 |
34 | $ builder main.exe util.dll data.bin >bundle.exe
35 |
36 | The builder program only runs on Windows and has not been ported for
37 | "cross-bundling" use. The makefile is designed for w64devkit, but the
38 | application compiles with Clang and MSVC using the proper sequence of
39 | commands. The `wrap.exe` target demos the console subsystem builder.
40 |
41 | $ make wrap.exe
42 | $ ./wrap
43 |
44 | This program is mainly a proof of concept. The user interface is lacking,
45 | and many error checks are omitted (see `TODO` in the sources). It would be
46 | a lot more useful if it could bundle a whole directory hierarchy, e.g. it
47 | could bundle up an entire "portable" application or even a game into a
48 | single EXE. The offsets and sizes should probably be 64-bit, too. This
49 | little project was inspired by [HexLoader][].
50 |
51 |
52 | [HexLoader]: https://github.com/crepps/HexLoader
53 | [UTF-16]: https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16
54 |
--------------------------------------------------------------------------------
/w32bundle/message.c:
--------------------------------------------------------------------------------
1 | __declspec(dllexport) char message[] = "hello world";
2 |
--------------------------------------------------------------------------------
/w32bundle/test.c:
--------------------------------------------------------------------------------
1 | #include
2 | extern char message[];
3 | int main(void) { puts(message); }
4 |
--------------------------------------------------------------------------------
/water-sort/GNUmakefile:
--------------------------------------------------------------------------------
1 | CC = cc
2 | CFLAGS = -O2
3 | LDFLAGS = -s
4 | DBG_CFLAGS = -g3 -Wall -Wextra -Wconversion -Wno-sign-conversion \
5 | -fsanitize=undefined -fsanitize-trap
6 | SDL2_FLAGS != pkg-config --cflags --libs sdl2
7 |
8 | water-sort-sdl2$(EXE): main_sdl2.c water-sort.c
9 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ main_sdl2.c $(SDL2_FLAGS)
10 |
11 | debug-sdl2$(EXE): main_sdl2.c water-sort.c
12 | $(CC) $(DBG_CFLAGS) -o $@ main_sdl2.c $(SDL2_FLAGS)
13 |
14 | water-sort.wasm: main_wasm.c water-sort.c
15 | clang --target=wasm32 -nostdlib -Wall -Wextra $(CFLAGS) \
16 | $(LDFLAGS) -Wl,--no-entry -fno-builtin -o $@ main_wasm.c
17 |
18 | water-sort.wasm.b64: water-sort.wasm
19 | (printf '"'; base64 <$^ | tr -d '\n'; printf '"') >$@
20 |
21 | index.html: index.html.in seeds.txt water-sort.wasm.b64
22 | clang -E -P -undef -nostdinc -x c -o $@ index.html.in
23 |
24 | water-sort.exe: main_windows.c water-sort.c
25 | $(CC) -nostartfiles -mwindows -fno-builtin $(CFLAGS) $(LDFLAGS) \
26 | -o $@ main_windows.c
27 |
28 | debug.exe: main_windows.c water-sort.c
29 | $(CC) -nostartfiles -mwindows $(DBG_CFLAGS) -o $@ main_windows.c
30 |
31 | clean:
32 | rm -f water-sort-sdl$(EXE) debug-sdl$(EXE) water-sort.exe debug.exe \
33 | water-sort.wasm water-sort.wasm.b64 index.html
34 |
--------------------------------------------------------------------------------
/water-sort/README.md:
--------------------------------------------------------------------------------
1 | # Water Sort Puzzle Game (SDL2, WASM, Win32)
2 |
3 | Move water between bottles until each bottle is a single color. Bottles
4 | can only hold four units of water, and water can only be poured onto alike
5 | or into empty bottles.
6 |
7 | Play online (WASM): [Water Sort Puzzle](https://nullprogram.com/water-sort/)
8 |
9 | ## Build
10 |
11 | For the native application, get any C compiler and SDL2, then:
12 |
13 | $ eval cc -O water-sort-puzzle.c $(pkg-config --cflags --libs sdl2)
14 |
15 | Or just run `make`. For WASM, get Clang, then:
16 |
17 | $ make index.html
18 |
19 | Then visit `index.html` in a browser. For a Win32 program:
20 |
21 | $ cc -nostartfiles -mwindows -O -o water-sort.exe
22 |
23 | Or with MSVC:
24 |
25 | $ cl /GS- /O1 /Fe:water-sort.exe main_windows.c
26 |
27 | Or run `make water-sort.exe` (w64devkit).
28 |
29 | ## User interface
30 |
31 | * left-click the "bottles" to make moves
32 | * middle-click to get a hint
33 | * right-click to undo
34 | * h: hint move
35 | * q: quit the game
36 | * r: reset puzzle
37 | * u: undo last move
38 | * 1-5: generate new puzzle (1=easy, 5=hard) [SDL only]
39 | * *left/right arrows*: navigate puzzle list [Win32 only]
40 |
41 | ## See Also
42 |
43 | * [Lipuzz: Water Sort | The Complete Strategy Guide](https://www.coolmathgames.com/blog/how-to-play-lipuzz-water-sort)
44 | * [Lessons learned from my first dive into WebAssembly](https://nullprogram.com/blog/2025/04/04/)
45 | * [r/watersortpuzzle](https://old.reddit.com/r/watersortpuzzle/)
46 |
--------------------------------------------------------------------------------
/water-sort/genseeds.c:
--------------------------------------------------------------------------------
1 | // Used to generate a seed list for WASM build.
2 | #include "water-sort.c"
3 | #include
4 | #include
5 |
6 | int main(void)
7 | {
8 | #pragma omp parallel for
9 | for (int seed = 0; seed <= 1<<24; seed++) {
10 | char *mem = malloc(SOLVE_MEM);
11 | Arena a = {mem, mem+SOLVE_MEM};
12 | State s = genpuzzle(seed, MAXBOTTLE);
13 | Solution r = solve(s, MAXBOTTLE, &a);
14 | if (r.len >= 44) {
15 | #pragma omp critical
16 | {
17 | printf("%8d%3d%6d\n", seed, r.len, r.width);
18 | fflush(stdout);
19 | }
20 | }
21 | free(mem);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/water-sort/main_wasm.c:
--------------------------------------------------------------------------------
1 | #include "water-sort.c"
2 |
3 | static Game *game;
4 | static Arena perm;
5 |
6 | __attribute((export_name("game_init")))
7 | void game_init(i32 seed)
8 | {
9 | static char heap[SOLVE_MEM];
10 | perm.beg = heap;
11 | perm.end = heap + SOLVE_MEM;
12 |
13 | game = new(&perm, 1, Game);
14 | game->nbottle = MAXBOTTLE;
15 | game->ui.select = -1;
16 | game->puzzle = genpuzzle(seed, game->nbottle);
17 | push(game, game->puzzle);
18 | }
19 |
20 | __attribute((export_name("game_render")))
21 | DrawList *game_render(i32 width, i32 height, i32 mousex, i32 mousey)
22 | {
23 | game->ui.width = width;
24 | game->ui.height = height;
25 | game->ui.mousex = mousex;
26 | game->ui.mousey = mousey;
27 | Arena scratch = perm;
28 | return renderui(top(game), game->nbottle, &game->ui, &scratch);
29 | }
30 |
31 | __attribute((export_name("game_update")))
32 | void game_update(i32 input, i32 x, i32 y, i32 now)
33 | {
34 | game->input = input;
35 | game->ui.mousex = x;
36 | game->ui.mousey = y;
37 | update(game, now, perm);
38 | }
39 |
--------------------------------------------------------------------------------
/wgl-demo/Makefile:
--------------------------------------------------------------------------------
1 | .POSIX:
2 | CC = x86_64-w64-mingw32-gcc
3 | CFLAGS = -std=c99 -Os -ffreestanding -Wall -Wextra -Werror \
4 | -fno-stack-check -fno-stack-protector -mno-stack-arg-probe \
5 | -DNDEBUG
6 | LDFLAGS = -s -nostdlib -mwindows
7 | LDLIBS = -lkernel32 -luser32 -lgdi32 -lopengl32
8 |
9 | main.exe: main.c
10 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ main.c $(LDLIBS)
11 |
12 | clean:
13 | rm -f main.exe
14 |
--------------------------------------------------------------------------------
/windows/README.md:
--------------------------------------------------------------------------------
1 | # Windows-only utilities
2 |
3 | A collection of utilities specifically for Win32 that are too trivial to
4 | warrant their own top-level directory, and not worth porting to other
5 | platforms. In most cases the primarily toolchain is [w64devkit][], but
6 | they should still work with MSVC.
7 |
8 | [w64devkit]: https://github.com/skeeto/w64devkit
9 |
--------------------------------------------------------------------------------
/windows/getfiletype.c:
--------------------------------------------------------------------------------
1 | // getfiletype: Report the standard output handle type on standard error
2 | // $ cc -nostartfiles -o getfiletype.exe getfiletype.c
3 | // $ cl /GS- getfiletype.c /link /subsystem:console kernel32.lib
4 | //
5 | // The purpose is to probe the behavior of various shells, particularly
6 | // PowerShell, which, lacking of file redirection, strangely connects
7 | // the ">" operator to a pipe.
8 | //
9 | // This is free and unencumbered software released into the public domain.
10 | #define WIN32_LEAN_AND_MEAN
11 | #include
12 |
13 | // Minimal perfect hash that maps FILE_TYPE_* onto 0..4
14 | #define HASH(x) (int)((x * 0x20010000u)>>29)
15 |
16 | static struct {
17 | char name[18];
18 | short length;
19 | } types[] = {
20 | #define E(s) {s "\n", sizeof(s)}
21 | [HASH(FILE_TYPE_UNKNOWN)] = E("FILE_TYPE_UNKNOWN"),
22 | [HASH(FILE_TYPE_DISK)] = E("FILE_TYPE_DISK"),
23 | [HASH(FILE_TYPE_CHAR)] = E("FILE_TYPE_CHAR"),
24 | [HASH(FILE_TYPE_PIPE)] = E("FILE_TYPE_PIPE"),
25 | [HASH(FILE_TYPE_REMOTE)] = E("FILE_TYPE_REMOTE"),
26 | };
27 |
28 | int mainCRTStartup(void)
29 | {
30 | HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
31 | HANDLE stderr = GetStdHandle(STD_ERROR_HANDLE);
32 | DWORD type = GetFileType(stdout);
33 | char *name = types[HASH(type)].name;
34 | DWORD length = types[HASH(type)].length;
35 | return !WriteFile(stderr, name, length, &length, 0);
36 | }
37 |
--------------------------------------------------------------------------------
/windows/imageview.c:
--------------------------------------------------------------------------------
1 | // Load and run the old "picture and fax viewer" a la rundll32
2 | // $ cc -nostartfiles -mwindows -Os -s -o imageview.exe imageview.c -lshell32
3 | // $ cl /O2 imageview.c /link /subsystem:windows kernel32.lib user32.lib shell32.lib
4 | // This is free and unencumbered software released into the public domain.
5 | typedef unsigned short wchar_t;
6 | typedef void (__stdcall *rundll32)(void *, void *, wchar_t *, int);
7 |
8 | #define W32(r) __declspec(dllimport) r __stdcall
9 | W32(wchar_t **) CommandLineToArgvW(wchar_t * ,int *);
10 | W32(void) ExitProcess(int);
11 | W32(int) ExpandEnvironmentStringsW(wchar_t *, wchar_t *, int);
12 | W32(wchar_t *) GetCommandLineW(void);
13 | W32(void *) GetProcAddress(void *, char *);
14 | W32(void *) LoadLibraryW(wchar_t *);
15 | W32(int) MessageBoxA(void *, char *, char *, int);
16 |
17 | void WinMainCRTStartup(void)
18 | {
19 | wchar_t dll[512];
20 | wchar_t *var = L"%SystemRoot%\\system32\\shimgvw.dll";
21 | *dll = 0;
22 | ExpandEnvironmentStringsW(var, dll, sizeof(dll)-1);
23 |
24 | void *h = LoadLibraryW(dll);
25 | if (!h) {
26 | MessageBoxA(0, "Could not load shimgvw.dll", "ImageView", 0);
27 | ExitProcess(1);
28 | }
29 | rundll32 entry = GetProcAddress(h, "ImageView_FullscreenW");
30 | if (!entry) {
31 | MessageBoxA(0, "Could not find ImageView_Fullscreen", "ImageView", 0);
32 | ExitProcess(1);
33 | }
34 |
35 | int argc;
36 | wchar_t *cmd = GetCommandLineW();
37 | wchar_t **argv = CommandLineToArgvW(cmd, &argc);
38 | if (argc < 2) {
39 | entry(0, 0, L"", 0);
40 | } else {
41 | entry(0, 0, argv[1], 0);
42 | }
43 | ExitProcess(0);
44 | }
45 |
--------------------------------------------------------------------------------