Vim: Insert a line of characters

I need an 80 character divider of text in Vim. I can never remember the sequence so I'm writing it down:

80i/<ESC>

Will generate:

////////////////////////////////////////////////////////////////////////////////
Tags:
Leave A Reply

Comparing 32bit and 64bit performance on low end micro-controllers

Testing 32bit vs 64bit PRNGs on a 32bit ESP32-C3 I'm seeing:

32bit

PRNG Iterations Output bits Bytes per second
xoroshiro64** 509038 32 2036152.0
pcg32 487697 32 1950788.0

64bit

PRNG Iterations Output bits Bytes per second
xoshiro256+ 487696 64 3901568.0
xoshiro512++ 441630 64 3533040.0
splitmix64 464875 64 3719000.0
pcg64 529955 64 4239640.0
biski64 484715 64 3877720.0

Very little difference on PRNGs that use 64bit operations vs 32bit operations. Even on limited hardware like this it makes sense to use a 64bit PRNG because you get more bytes per cycle.

Tags:
Leave A Reply

Vim: Convert your syntax highlighted text into HTML

Vim is my code editor of choice as it has great features, excellent syntax highlighting, and a robust plug-in infrastructure. I'm very used to look and feel of Vim. If you want to share some of your code online, converting things to HTML can be problematic. Luckily Vim has a built in code to HTML converter:

:TOhtml

Simply run the :TOhtml command in an open text file and your buffer will be redrawn in HTML which you can then save. Here is a quick sample of my pcg32.pl script converted to HTML.

Tags:
Leave A Reply

What kind of number makes a good seed for a PRNG?

Pseudo-random number generators use complex math to generate random numbers on your computer. These random numbers are used for all sorts of things: simulations, fractals, games, art, and even math experiments. Computers can only do math, which makes generating a random number difficult.

PRNGs need a "seed" number to kick off the math that generates sequences of random numbers. Some PRNGs require a 32bit seed, and some require a 64bit seed. Some PRNGs require one seed, and some require four (or more). It is important to know what type of seed your PRNG needs.

A 32bit number is between 0 and 4.2 billion and a 64bit number is between 0 and 18.4 quintillion. The larger a number is, the more bits are required to store it, and the better a seed it will make. The closer your seed is to the upper end of the number range the better. As a general rule a good seed will be a decimal number with 18 or 19 digits.

12 is a small number and not a good seed, 4611686018427387906 is a big number but still not a great seed. Seeds should not have large sections of zero/one bits. This is why small numbers do not make good seeds. Bits can be visualized by printing the number in binary:

# Horrible
$ perl -E 'printf("%064b\n", 4611686018427387906)'
0100000000000000000000000000000000000000000000000000000000000010

# Bad
$ perl -E 'printf("%064b\n", 17770)'
0000000000000000000000000000000000000000000000000100010101101010

# Poor
$ perl -E 'printf("%064b\n", 2850756010)'
0000000000000000000000000000000010101001111010110001010110101010

# Good
$ perl -E 'printf("%064b\n", 11337502976607798025)'
1001110101010110111001101110001101111000101001000100001100001001

Good seeds should have a roughly even mix of zero and one bits. 9223372036854775808 is a large number and looks promising but it has 63 zeros, and only a single one bit. You can visualize the quality of your seed with seed_quality.pl. Quality above 75% should make for good seed numbers.

Seeds should not be predictable. Do not use dates, times, or phone numbers as they are potentially guessable. Combinations of numbers can be good sources. Process PID, UID, unixtime are good potential sources if they are combined together in a non-predictable way. PID multiplied by UID multiplied by Unixtime is an example of combining values. Memory locations of variables, especially if ASLR is in use is a potentially good source as well.

Hashing numbers, strings, or combinations of numbers can be a good way to generate seeds. Hashing a value with Komihash or xxHash will generate a suitable 64bit number. Hashing a value with SHA256 will generate a 256bit value which can be split into four 64bit values. Hashing functions also do a good job of ensuring the bits are mixed well and do not include large repeating sections.

The best source of seed numbers is directly from your OS. On Linux this is /dev/urandom and on Windows you can interface with the RtlGenRandom API. These are carefully curated sources of true randomness, but they can be slow-ish. Using them as a source for a fast PRNG is best practice.

sub get_64bit_seed {
    open my $urandom, '<:raw', '/dev/urandom' or croak("Couldn't open /dev/urandom: $!");
    sysread($urandom, my $buf, 8) or croak("Couldn't read from csprng: $!");

    return unpack("Q*", $buf);
}
Tags:
Leave A Reply

Perl: Multiply-Shift Hash

I've been using the multiply-shift hash lately and have had good results. It's simple, fast, and well tested.

// Multiply-Shift Hash
static uint64_t hash_msh(uint64_t x) {
    uint64_t prime = 0x9e3779b97f4a7c15; // A large prime constant
    x ^= (x >> 30);
    x *= prime;
    x ^= (x >> 27);
    x *= prime;
    x ^= (x >> 31);
    return x;
}

Whenever I find interesting code like this I like to try and implement it in Perl:

sub hash_msh {
    my $x     = $_[0];
    my $prime = 11400714819323198485;

    $x ^= ($x >> 30);
    $x = multiply_uv($x, $prime);
    $x ^= ($x >> 27);
    $x = multiply_uv($x, $prime);
    $x ^= ($x >> 31);

    return $x;
}

# Perl converts numbers larger than 2^64 - 1 to floating point so
# we 'use integer' to force integer math which retains any overflow.
sub multiply_uv {
    my ($one, $two) = @_;

    use integer;
    my $ret = $one * $two;
    no integer;

    # Convert signed IV to unsinged UV
    if ($ret < 0) {
        $ret += 18446744073709551615;
        $ret += 1;
    }

    return $ret;
}
Tags:
Leave A Reply

Perl: Calculate number of bits needed to store a number

Quick Perl function to calculate the number of bits required to store a given number.

sub bits_required {
    my ($n) = @_;

    # Handle special case for 0
    return 0 if $n == 0;

    # Use logarithm to calculate the number of bits
    my $bits = int(log($n) / log(2)) + 1;
    return $bits;
}
Tags:
Leave A Reply

Implmenting PRNGs in Perl

I'm a big fan of the PCG32 PRNG. It's simple, fast, and well documented. As is usually the case when I find interesting code I try and find a way to implement it in Perl. PCG32 poses an interesting problem when one tries to implement it in Perl because all the math is performed using unsigned integers and overflow. Most PRNGs use large numbers and overflow to work, that's their secret sauce.

Perl does not have a native unsigned type so I had to learn the guts of how Perl does math so I could emulate it. I ended up coming up with two different implementations, a native Perl implementation, and a version that uses Math::Int64. Surprisingly the native version was significantly faster.

Both implementations with detailed comments are available in pcg32.pl if you're interested in learning more about how to do integer style math in Perl.

As a bonus I also ported the xoshiro256 family into Perl. Splitmix64 ended up being a little more complicated to port, but I got it as well.

Tags:
Leave A Reply

FFMPEG: Limit the output to only the encoding stats for quieter scripting

FFMPEG is a great tool, but it is very chatty. If you want to encode a file you'll get about 40 lines of headers and track information, most of which you probably will not read. For scripting purposes you probably only want to see the statistics. If you start FFMPEG, hide the banner, and set the loglevel low you can output only the stats you need

ffmpeg -y -hide_banner -loglevel quiet -stats ...
Tags:
Leave A Reply

Perl: Using sha256 to hash strings into integers

I need 64bit integers to seed some PRNG work I'm doing. I found out that you can easily create four 64bit numbers from any string by using SHA256.

use Digest::SHA;

my $input = $ARGV[0] || int(rand() * 1000000);

# Get raw bytes and convert to an array of uint64_t
my $hash = Digest::SHA::sha256($input);
my @nums = unpack("Q*", $hash);

print "SHA256 Hashing '$input' to: " . join(", ", @nums) . "\n";

Note: We are using sha256 here, not sha256_hex because we need raw bytes to convert to integers with unpack.

Tags:
Leave A Reply

Komihash is pretty amazing and simple hashing algorithm

I need a simple way to hash strings into 64bit integers so I started some research. Initially I was focusing on xxHash but it's slightly complicated to implement. I ended up landing on the amazing Komihash which bills itself as: "a very fast 64-bit hash function, mainly designed for hash-table, hash-map, and bloom-filter uses".

Komihash is available as a single Komihash.h file and is extremely easy to implement into existing code.

#include <stdio.h>
#include <stdlib.h>
#include "komihash.h"

int main(int argc, char *argv[]) {
    int seed        = 0;
    const char *buf = "Hello world";

    uint64_t hash_num = komihash(buf, strlen(buf), seed);

    printf("Komihash: %s = %llu\n", buf, hash_num); // 3745467240760726046
}

As a bonus it also comes with a PRNG which is equally simple to implement:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "komihash.h"

int main(int argc, char *argv[]) {
    uint64_t seed1 = time(NULL) * 0x61c8864680b583ebull; // hash64
    uint64_t seed2 = seed1      * 0x61c8864680b583ebull; // hash64

    for (int i = 0; i < 5; i++) {
        uint64_t rand64 = komirand(&seed1, &seed2);
        printf("Komirand: %llu\n", rand64);
    }
}

In fact, I liked it so much I ported it to Perl and called it Crypt::Komihash.

Tags:
Leave A Reply

Perl: Warning about non-portable numbers

If you get a Perl warning about non-portable numbers like this:

Hexadecimal number > 0xffffffff non-portable at /tmp/x.pl line 19.

It means that you are using a hex number greater than 2^32. I dunno why this is a warning when everything is 64bit these days, but it is. There have been a couple of times I needed this in my code so you can disable these warnings with:

no warnings 'portable';
Tags:
Leave A Reply

Books of 2025

List of books I read in 2025. Also see the list of 2024. The date indicated denotes the date I started reading the book.

2025-01-06 - Mistborn by Brandon Sanderson - 643 pages
2025-01-17 - Ender's Game by Orson Scott Card - 324 pages
2025-01-22 - Thinner by Stephen King - 318 pages
2025-01-26 - The Dead Zone by Stephen King - 426 pages
2025-02-02 - The Neverending Story by Michael Ende - 377 pages
2025-02-08 - The Well Of Ascension by Brandon Sanderson - 785 pages
2025-02-21 - Skeleton Crew - The Monkey by Stephen King - 32 pages
2017-02-21 - Speaker for the Dead by Orson Scott Card - 395 Pages
2025-02-27 - Insomnia by Stephen King - 787 pages
2025-03-11 - Hero Of Ages by Brandon Sanderson - 752 pages
2025-03-23 - Xenocide by Orson Scott Card - 592 pages
2025-04-01 - Tainted Cup by Robert Jackson Bennett - 410 pages
2025-04-07 - Star Wars: Sacrifice by Karen Traviss - 487 pages
2025-04-15 - The Sword Of Shannara by Terry Brooks - 726 pages
2025-04-26 - Everything Is Tuberculosis by John Green - 198 pages
2025-04-29 - Children Of The Mind by Orson Scott Card - 370 pages
2025-05-22 - Bookshops And Bonedust by Travis Baldree - 332 pages
2025-05-27 - Ender's Shadow by Orson Scott Card - 467 pages
2025-06-04 - The Claiming Of Sleeping Beauty by Anne Rice - 230 pages
2025-06-12 - Never Flinch by Stephen King - 439 pages
2025-06-20 - Shadow Of The Hegemon by Orson Scott Card - 451 pages
2025-07-05 - Star Wars: Inferno by Troy Denning - 320 pages
2025-07-10 - Shadow Puppets by Orson Scott Card - 372 pages
2025-07-19 - Dune: House Harkonnen by Brian Herbert - 603 pages
2025-07-29 - Naked Lunch by William S. Burroughs - 289 pages
2025-08-03 - The Cat Who Knew Shakespeare by Lilian Jackson Braun - 201 pages
2025-08-07 - Hyperion by Dan Simmons - 482 pages [1]
2025-08-14 - Shadow Of The Giant by Orson Scott Card - 367 pages
2025-08-20 - The Shining by Stephen King - 447 pages
2025-09-01 - Between Two Kingdoms by Suleika Jaouad - 340 pages
2025-09-06 - Star Wars: Fury by Aaron Allston - 356 pages
2025-09-20 - Treasure by Clive Cussler - 547 pages
2025-09-28 - Doctor Sleep by Stephen King - 531 pages
2025-10-13 - Four Past Midnight by Stephen King - 763 pages
2025-10-26 - Carrie - 199 pages
2025-10-29 - The Electric Kool-aid Acid Test by Tom Wolfe - 416 pages
2025-11-11 - Rocket Dreams by Christian Davenport - 323 pages
2025-11-16 - Dirk Gently's Holistic Detective Agency by Douglas Adams - 260 pages
2025-11-21 - Astrophysics For People In A Hurry by Neil deGrasse Tyson - 208 pages
2025-11-24 - Sherlock Holmes Vs. Cthulhu: The Adventure Of The Neural Psychoses by Lois H. Gresh - 398 pages
2025-11-29 - Dreamcatcher by Stephen King - 612 pages
2025-12-09 - King Sorrow by Joe Hill - 859 pages
2025-12-19 - The Cat Who Sniffed Glue by Lilian Jackson Braun - 278 pages
2025-12-24 - Gardens Of The Moon by Steven Erikson - 488 pages

J.R.R. Tolkien

2025-08-27 - The Hobbit by J.R.R. Tolkien - 303 pages
2024-09-12 - The Fellowship of the Ring by J.R.R. Tolkien - 527 pages
2024-10-07 - The Two Towers by J.R.R. Tolkien - 447 pages
2024-11-05 - Return of the King by J.R.R. Tolkien - 385 pages

Coming of age novels
2025-05-11 - Middlesex by Jeffrey Eugenides - 529 pages
2025-06-27 - A Tree Grows In Brooklyn by Betty Smith - 443 pages
2025-07-17 - The Perks Of Being A Wallflower by Stephen Chbosky - 240 pages

Books under 200 pages that marked you
2025-05-05 - Murderbot Diaries #1: All Systems Red by Martha Wells - 149 pages
2025-06-08 - Murderbot Diaries #2: Artificial Condition by Martha Wells - 149
2025-06-10 - Murderbot Diaries #3: Rogue Protocol by Martha Wells - 149 pages
2025-05-07 - We Have Always Lived In The Castle by Shirley Jackson - 146 pages
2025-05-09 - Of Mice And Men by John Steinbeck - 107 pages
2025-05-20 - To Be Taught, If Fortunate by Becky Chambers - 142 pages

Tags:
Leave A Reply - 1 Reply

C: Nanoseconds since Unix epoch

I needed a function to use as a simple seed for srand(). Unixtime in nanoseconds changes very frequently and serves as a semi-decent random seed.

#include <time.h> // for clock_gettime()

// Nanoseconds since Unix epoch
uint64_t nanos() {
    struct timespec ts;

    // int8_t ok = clock_gettime(CLOCK_MONOTONIC, &ts); // Uptime
    int8_t ok = clock_gettime(CLOCK_REALTIME, &ts);  // Since epoch

    if (ok != 0) {
        return 0; // Return 0 on failure (you can handle this differently)
    }

    // Calculate nanoseconds
    uint64_t ret = (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;

    return ret;
}

See also: Microseconds since epoch in Perl

Tags:
Leave A Reply

Git: Show all changes to a given file

If you want to view the history of all the changes you've made to a specific file in Git you can use the log command in Git. This will show you all the commits that touched that file, and the associated commit message.

git log README.md

If you want to see a diff/patch for each commit you can run:

git log --follow --patch README

This can be very useful to track down when a specific piece of code went into (or was taken out of) a file. Be careful as this command only shows you the diff/patch for the file you request. If the commit contains changes to other files you will not see those unless you view the full commit.

Tags:
Leave A Reply

C/C++: List all #define macros

I need to target a specific platform with some code I'm writing. You can list all of the #define macros on a given platform with these commands:

gcc -dM -E - < /dev/null
clang -dM -E - < /dev/null

In this big list of macros you should find something to help you target a given platform.

Tags:
Leave A Reply