├── 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 | ![](./iseven.png) 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", scale*3, scale*3); 44 | fprintf(f, "\n"); 45 | for (int y = 0; y < 3; y++) { 46 | for (int x = 0; x < 3; x++) { 47 | int i = y*3 + x; 48 | char *fill = v>>i & 1 ? "" : "fill:white;"; 49 | fprintf(f, "\n", 51 | scale/2 + x*scale, scale/2 + y*scale, 52 | scale*4/10, fill, scale/15); 53 | } 54 | } 55 | 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 | ![](./examples.png) 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 | --------------------------------------------------------------------------------